swift - Swift 中的地址簿外部更改回调(使用 C 函数指针?)

标签 swift abaddressbook

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

我正在尝试在我的 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/

相关文章:

ios - CIQRCodeGenerator 提供不一致的结果

ios - 当应用于 WKWebView 内的视频 srcObject 时,有什么方法可以防止 getUserMedia "Live Broadcast"?

iphone - iPhone 上 ABPeoplePickerNavigationController 的自定义地址簿

iphone - 从地址簿添加联系人时 EXC_BAD_ACCESS?

iOS ABPersonViewController

ios - 如何在 swift 中从树数据结构制作 UIButtons

ios - tableView 中的索引超出范围

swift - 字典的扩展 where <String, AnyObject>

iOS 如何检查 ABRecordRef ABAddressBook、ABPerson 是否启用了 WhatsApp?

ios - ABMultiValueCopyLabelAtIndex() 中的标签顺序是什么