原始问题(参见下面的解决方案):
我正在尝试在我的 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!
}
在 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
}()
那么我该如何在 Swift 中实现它呢?
解决方案(有缺陷):
正如 pNre 所建议的,这就是我现在实现它的方式:
在 Objective-C 中:
AddressBookExternalChangeCallback.h:
#import <AddressBook/AddressBook.h>
void registerExternalChangeCallbackForAddressBook(ABAddressBookRef addressBookRef);
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);
}
在 Swift 中:
导入桥接头后:
registerExternalChangeCallbackForAddressBook(addressBookRef)
每本地址簿更改时都会发布通知。不过,只有 @objc
类可以注册通知,所以有没有办法改为调用 Swift 函数或方法?
最佳答案
ABExternalChangeCallback
定义为
typealias ABExternalChangeCallback = CFunctionPointer<((ABAddressBookRef!, CFDictionary!, UnsafeMutablePointer<()>) -> Void)>
来自 Xcode 发行说明:
However, you cannot call a C function pointer (
CFunctionPointer
) or convert a closure to C function pointer type.
这意味着您不能像现在这样分配 block 。
但是,您可以绕过此限制,在 objc 函数中调用 ABAddressBookRegisterExternalChangeCallback
并从您的 swift 代码中调用它。
关于swift - Swift 中的地址簿外部更改回调(使用 C 函数指针?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25346563/