Swift中的地址簿外部更改回调(使用C功能指针?)

knl*_*knl 9 abaddressbook swift

原始问题(见下面的解决方案):

我试图在我的Swift应用程序中使用AddressBook.framework,但无法弄清楚如何实现该ABAddressBookRegisterExternalChangeCallback功能.

在Objective-C中,我只是将回调实现为C函数并传递其指针:

// somewhere in the initializer of the MyAddressBook class:
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(nil, nil);
ABAddressBookRegisterExternalChangeCallback(addressBook, externalChangeCallback, (__bridge void *)(self));

// somewhere else in the MyAddressBook class:
void externalChangeCallback(ABAddressBookRef reference, CFDictionaryRef info, void *context)
{
    [(__bridge MyAddressBook *)context addressBookDidChangeExternally];
}

- (void)addressBookDidChangeExternally
{
    // good old Obj-C from here on!
}
Run Code Online (Sandbox Code Playgroud)

在Swift中,我很难处理C函数.我发现Apple增加了在beta 3中传递C函数指针的能力,但是我如何声明这样的函数呢?使用Swift的闭包语法会很好,但这是否可能?

这是我创建的地方ABAddressBookRef:

var addressBookRef: ABAddressBookRef = {
    let addressBookRef: ABAddressBookRef = ABAddressBookCreateWithOptions(nil, nil).takeRetainedValue()

    // TODO: how do I make this work?
    let externalChangeCallback: ABExternalChangeCallback = {
        println("Address book changed externally!")
    }
    ABAddressBookRegisterExternalChangeCallback(addressBookRef, externalChangeCallback, nil)

    return addressBookRef
}()
Run Code Online (Sandbox Code Playgroud)

那么如何在Swift中实现呢?


解决方案(有缺陷):

正如pNre所建议的那样,这就是我现在实现它的方式:

在Objective-C中:

AddressBookExternalChangeCallback.h:

#import <AddressBook/AddressBook.h>
void registerExternalChangeCallbackForAddressBook(ABAddressBookRef addressBookRef);
Run Code Online (Sandbox Code Playgroud)

AddressBookExternalChangeCallback.m:

#import "AddressBookExternalChangeCallback.h"

void addressBookExternalChangeCallback(ABAddressBookRef addressBookRef, CFDictionaryRef info, void *context)
{
    dispatch_async(dispatch_get_main_queue(), ^{
        [[NSNotificationCenter defaultCenter] postNotificationName:@"AddressBookDidChangeExternallyNotification" object:nil];
    });
}

void registerExternalChangeCallbackForAddressBook(ABAddressBookRef addressBookRef)
{
    ABAddressBookRegisterExternalChangeCallback(addressBookRef, addressBookExternalChangeCallback, nil);
}
Run Code Online (Sandbox Code Playgroud)

在Swift中:

导入桥接头后:

registerExternalChangeCallbackForAddressBook(addressBookRef)
Run Code Online (Sandbox Code Playgroud)

每当地址簿发生变化时,都会发布通知.@objc但是,只有类可以注册通知,所以有没有办法调用Swift函数或方法呢?

pNr*_*Nre 5

ABExternalChangeCallback 被定义为

typealias ABExternalChangeCallback = CFunctionPointer<((ABAddressBookRef!, CFDictionary!, UnsafeMutablePointer<()>) -> Void)>
Run Code Online (Sandbox Code Playgroud)

来自 Xcode 发行说明:

但是,您不能调用 C 函数指针 ( CFunctionPointer) 或将闭包转换为 C 函数指针类型。

这意味着您不能按照您的方式分配块。但是,您可以ABAddressBookRegisterExternalChangeCallback在 objc 函数中调用并从 swift 代码中调用它来绕过此限制。