iOS获取联系人姓名部分设备崩溃:Unrecognized selector异常求助
崩溃原因及解决方案
核心崩溃原因
部分旧iOS系统版本的Contacts框架不支持将NSCompoundPredicate作为CNContactFetchRequest的查询谓词使用。CNContact.predicateForContacts(matching:)返回的是Contacts框架专属的CNPredicate子类实例,你用NSCompoundPredicate对其包装后,框架内部尝试调用仅CNPredicate子类才有的cn_triageWithLog:serialNumber:方法,而NSCompoundPredicate未实现该方法,因此触发NSInvalidArgumentException崩溃。
另外,你的代码里用NSCompoundPredicate包装单个谓词完全是冗余操作——仅需单个查询条件时,根本不需要复合谓词组合。
修改后的代码
func getContactName(phoneNumber: String, completion: @escaping (String) -> Void ) { let phoneNumber = CNPhoneNumber(stringValue: phoneNumber) let phoneNumberPredicate = CNContact.predicateForContacts(matching: phoneNumber) let fetchRequest = CNContactFetchRequest(keysToFetch: [ CNContactGivenNameKey as CNKeyDescriptor, CNContactFamilyNameKey as CNKeyDescriptor ]) // 直接使用单个谓词,去掉冗余的NSCompoundPredicate包装 fetchRequest.predicate = phoneNumberPredicate let store = CNContactStore() do { try store.enumerateContacts(with: fetchRequest) { (contact, stop) in let contactName = contact.givenName completion(contactName) // 找到匹配项后立即停止枚举,提升性能 stop.pointee = true } } catch { // 补充错误处理,避免调用者一直等待 completion("") } }
额外优化建议
- 找到第一个匹配联系人后设置
stop.pointee = true,避免遍历所有联系人,提升查询效率。 - 不要忽略错误处理,至少在catch块中给completion返回默认值,避免调用方出现异常。
内容的提问来源于stack exchange,提问作者Joice George
相关产品推荐
相关产品推荐

