Swift 4中UILocalizedIndexedCollation报unrecognized selector错误求助
你的问题核心很明确:你给UILocalizedIndexedCollation传了一个完全不匹配的selector,同时你的Contact类没有满足Objective-C API的交互要求,导致系统找不到对应的方法而抛出错误。下面一步步帮你修复:
1. 错误根源分析
你用了#selector(getter: UIApplicationShortcutItem.localizedTitle)这个selector,但你的objects数组里是Contact类型的对象,Contact根本没有localizedTitle这个属性,所以系统调用这个方法时就会出现unrecognized selector错误。
另外,Swift 4中默认不会把Swift类/属性暴露给Objective-C,而UILocalizedIndexedCollation是Objective-C时代的API,要求操作的对象必须是NSObject子类,且要排序的属性必须用@objc修饰。
2. 修复Contact模型
首先修改你的Contact类,让它继承NSObject,并添加一个用于排序分组的@objc修饰的属性(比如联系人全名):
class Contact: NSObject { let givenName: String let familyName: String let phoneNumbers: [CNLabeledValue<CNPhoneNumber>] // 用@objc修饰这个计算属性,让Objective-C能访问到 @objc var fullName: String { return "\(givenName) \(familyName)" } init(contact: CNContact) { self.givenName = contact.givenName self.familyName = contact.familyName self.phoneNumbers = contact.phoneNumbers super.init() // 必须调用NSObject的初始化方法 } }
3. 修正Collation的Selector
把原来错误的selector替换成Contact类里的fullName属性的selector,同时优化代码的类型安全:
let collation = UILocalizedIndexedCollation.current() var sections: [[Contact]] = [] // 这里直接用[Contact]代替AnyObject更安全 var objects: [Contact] = [] { didSet { // 使用自己模型的selector let selector = #selector(getter: Contact.fullName) sections = Array(repeating: [], count: collation.sectionTitles.count) let sortedObjects = collation.sortedArray(from: objects, collationStringSelector: selector) for object in sortedObjects { guard let contact = object as? Contact else { continue } let sectionNumber = collation.section(for: contact, collationStringSelector: selector) sections[sectionNumber].append(contact) } DispatchQueue.main.async { self.tableView.reloadData() } } }
4. 关于Contacts XPC Service错误
你看到的Error communicating with XPC Service: Error Domain=NSCocoaErrorDomain Code=4101这个日志,其实是Contacts框架的一个常见非致命日志,只要你能正常获取到联系人,这个错误不会影响你的功能,可以忽略它。
内容的提问来源于stack exchange,提问作者user8169082

