获取时应用程序崩溃 >800 个使用 iOS 9 联系人框架的联系人 [英] App crashing when fetching > 800 contacts using iOS 9 Contacts framework
问题描述
尝试使用 iOS 9 联系人框架获取设备上的所有统一联系人.尝试获取 > 800 个联系人时,应用程序崩溃.
Trying to fetch all the unified contacts on a device using the iOS 9 Contacts framework. The app is crashing when trying to fetch > 800 contacts.
我认为这是一个内存问题.
I think this is a memory issue.
下面是我的实现
@objc func searchContacts(searchText: String?, callback: (NSObject) -> ()) -> Void {
let contactStore = CNContactStore()
let keysToFetch = [ CNContactGivenNameKey, CNContactFamilyNameKey, CNContactImageDataAvailableKey, CNContactThumbnailImageDataKey ]
do {
var cNContacts = [CNContact]()
let fetchRequest = CNContactFetchRequest(keysToFetch: keysToFetch)
fetchRequest.sortOrder = CNContactSortOrder.GivenName
try contactStore.enumerateContactsWithFetchRequest(fetchRequest) { (cNContact, pointer) -> Void in
if !cNContact.givenName.isEmpty { // Ignore any Contacts that don't have a Given Name. Garbage Contact.
if searchText == nil {
// Add all Contacts if no searchText is provided.
cNContacts.append(cNContact)
}
else {
// If the Contact contains the search string then add it.
if self.contactContainsText( cNContact, searchText: searchText! ) {
cNContacts.append(cNContact)
}
}
}
}
var contacts = [NSDictionary]();
for cNContact in cNContacts {
contacts.append( convertCNContactToDictionary(cNContact) )
}
callback([NSNull(), contacts])
}
catch let error as NSError {
NSLog("Problem getting unified Contacts")
NSLog(error.localizedDescription)
callback([error.localizedDescription, NSNull()])
}
}
这里是字典转换器:
func convertCNContactToDictionary(cNContact: CNContact) -> NSDictionary {
var contact = [String: AnyObject]()
let phoneNumbers = NSMutableArray()
contact["identifier"] = cNContact.identifier
contact["givenName"] = cNContact.givenName
contact["familyName"] = cNContact.familyName
contact["imageDataAvailable"] = cNContact.imageDataAvailable
if (cNContact.imageDataAvailable) {
let thumbnailImageDataAsBase64String = cNContact.thumbnailImageData!.base64EncodedStringWithOptions([])
contact["thumbnailImageData"] = thumbnailImageDataAsBase64String
// let imageDataAsBase64String = cNContact.imageData!.base64EncodedStringWithOptions([])
// contact["imageData"] = imageDataAsBase64String
}
if (cNContact.isKeyAvailable(CNContactPhoneNumbersKey)) {
for number in cNContact.phoneNumbers {
var numbers = [String: AnyObject]()
let phoneNumber = (number.value as! CNPhoneNumber).valueForKey("digits") as! String
let countryCode = (number.value as! CNPhoneNumber).valueForKey("countryCode") as? String
let label = CNLabeledValue.localizedStringForLabel(number.label)
numbers["number"] = phoneNumber
numbers["countryCode"] = countryCode
numbers["label"] = label
phoneNumbers.addObject(numbers)
}
contact["phoneNumbers"] = phoneNumbers
}
let contactAsNSDictionary = contact as NSDictionary
return contactAsNSDictionary;
}
编辑
所以我在我的模拟器中添加了一堆联系人并且可以重现崩溃.
So I add a bunch of contacts in my simulator and can reproduce the crash.
这是堆栈跟踪:
libswiftCore.dylib`function signature specialization <Arg[0] = Exploded, Arg[1] = Exploded, Arg[2] = Dead, Arg[3] = Dead> of Swift._fatalErrorMessage (Swift.StaticString, Swift.StaticString, Swift.StaticString, Swift.UInt) -> ():
0x107e73180 <+0>: pushq %rbp
0x107e73181 <+1>: movq %rsp, %rbp
0x107e73184 <+4>: pushq %rbx
0x107e73185 <+5>: pushq %rax
0x107e73186 <+6>: movq %rcx, %r10
0x107e73189 <+9>: testb $0x1, %dl
0x107e7318c <+12>: jne 0x107e731aa ; <+42>
0x107e7318e <+14>: testq %rsi, %rsi
0x107e73191 <+17>: js 0x107e731f9 ; <+121>
0x107e73193 <+19>: addq %rdi, %rsi
0x107e73196 <+22>: movzbl %r9b, %eax
0x107e7319a <+26>: movq %r10, %rdx
0x107e7319d <+29>: movq %r8, %rcx
0x107e731a0 <+32>: movl %eax, %r8d
0x107e731a3 <+35>: callq 0x107eccea0 ; function signature specialization <Arg[0] = Exploded, Arg[1] = Exploded> of Swift.(_fatalErrorMessage (Swift.StaticString, Swift.StaticString, Swift.StaticString, Swift.UInt) -> ()).(closure #2)
-> 0x107e731a8 <+40>: ud2
0x107e731aa <+42>: movq $0x0, -0x10(%rbp)
0x107e731b2 <+50>: movl %edi, %eax
0x107e731b4 <+52>: cmpq %rax, %rdi
0x107e731b7 <+55>: jne 0x107e73303 ; <+387>
0x107e731bd <+61>: cmpl $0xd7ff, %edi ; imm = 0xD7FF
0x107e731c3 <+67>: ja 0x107e73222 ; <+162>
0x107e731c5 <+69>: xorl %esi, %esi
0x107e731c7 <+71>: cmpl $0x80, %edi
0x107e731cd <+77>: movl $0x0, %r11d
0x107e731d3 <+83>: jb 0x107e732f6 ; <+374>
0x107e731d9 <+89>: movl %edi, %r11d
0x107e731dc <+92>: shrl $0x6, %r11d
0x107e731e0 <+96>: cmpl $0x800, %edi ; imm = 0x800
0x107e731e6 <+102>: jae 0x107e7329b ; <+283>
0x107e731ec <+108>: orb $-0x40, %r11b
0x107e731f0 <+112>: xorl %esi, %esi
0x107e731f2 <+114>: xorl %ebx, %ebx
0x107e731f4 <+116>: jmp 0x107e732c6 ; <+326>
0x107e731f9 <+121>: leaq 0xd3d92(%rip), %rdi ; "fatal error"
0x107e73200 <+128>: leaq 0xd3f89(%rip), %rcx ; "UnsafeBufferPointer with negative count"
0x107e73207 <+135>: movl $0xb, %esi
0x107e7320c <+140>: movl $0x2, %edx
0x107e73211 <+145>: movl $0x27, %r8d
0x107e73217 <+151>: movl $0x2, %r9d
0x107e7321d <+157>: callq 0x107e73180 ; <+0>
0x107e73222 <+162>: cmpl $0xe000, %edi ; imm = 0xE000
0x107e73228 <+168>: jb 0x107e73272 ; <+242>
0x107e7322a <+170>: cmpl $0x110000, %edi ; imm = 0x110000
0x107e73230 <+176>: jae 0x107e73352 ; <+466>
0x107e73236 <+182>: movl %edi, %r11d
0x107e73239 <+185>: shrl $0x6, %r11d
0x107e7323d <+189>: movl %edi, %eax
0x107e7323f <+191>: shrl $0xc, %eax
0x107e73242 <+194>: cmpl $0xffff, %edi ; imm = 0xFFFF
0x107e73248 <+200>: jbe 0x107e732a0 ; <+288>
0x107e7324a <+202>: movl %edi, %ecx
0x107e7324c <+204>: shrl $0x12, %ecx
0x107e7324f <+207>: orl $0xf0, %ecx
0x107e73255 <+213>: movzbl %cl, %edx
0x107e73258 <+216>: cmpl %edx, %ecx
0x107e7325a <+218>: jne 0x107e73303 ; <+387>
0x107e73260 <+224>: andb $0x3f, %al
0x107e73262 <+226>: orb $-0x80, %al
0x107e73264 <+228>: movzbl %cl, %edx
0x107e73267 <+231>: movq %rdx, -0x10(%rbp)
0x107e7326b <+235>: movl $0x1, %esi
0x107e73270 <+240>: jmp 0x107e732a6 ; <+294>
0x107e73272 <+242>: leaq 0xd3d19(%rip), %rdi ; "fatal error"
0x107e73279 <+249>: leaq 0xd4a80(%rip), %rcx ; "high- and low-surrogate code points are not valid Unicode scalar values"
0x107e73280 <+256>: movl $0xb, %esi
0x107e73285 <+261>: movl $0x2, %edx
0x107e7328a <+266>: movl $0x47, %r8d
0x107e73290 <+272>: movl $0x2, %r9d
0x107e73296 <+278>: callq 0x107e73180 ; <+0>
0x107e7329b <+283>: movl %edi, %eax
0x107e7329d <+285>: shrl $0xc, %eax
0x107e732a0 <+288>: orb $-0x20, %al
0x107e732a2 <+290>: xorl %esi, %esi
0x107e732a4 <+292>: xorl %edx, %edx
0x107e732a6 <+294>: leaq (,%rsi,8), %rcx
0x107e732ae <+302>: andb $0x3f, %r11b
0x107e732b2 <+306>: orb $-0x80, %r11b
0x107e732b6 <+310>: movzbl %al, %ebx
0x107e732b9 <+313>: shlq %cl, %rbx
0x107e732bc <+316>: orq %rdx, %rbx
0x107e732bf <+319>: movq %rbx, -0x10(%rbp)
0x107e732c3 <+323>: incq %rsi
0x107e732c6 <+326>: movl $0x8, %ecx
0x107e732cb <+331>: movq %rsi, %rax
0x107e732ce <+334>: mulq %rcx
0x107e732d1 <+337>: jo 0x107e73303 ; <+387>
0x107e732d3 <+339>: cmpq $0x3f, %rax
0x107e732d7 <+343>: ja 0x107e73329 ; <+425>
0x107e732d9 <+345>: andl $0x3f, %edi
0x107e732dc <+348>: orq $0x80, %rdi
0x107e732e3 <+355>: movzbl %r11b, %r11d
0x107e732e7 <+359>: movb %al, %cl
0x107e732e9 <+361>: shlq %cl, %r11
0x107e732ec <+364>: orq %rbx, %r11
0x107e732ef <+367>: movq %r11, -0x10(%rbp)
0x107e732f3 <+371>: incq %rsi
0x107e732f6 <+374>: movl $0x8, %ecx
0x107e732fb <+379>: movq %rsi, %rax
0x107e732fe <+382>: mulq %rcx
0x107e73301 <+385>: jno 0x107e73305 ; <+389>
0x107e73303 <+387>: ud2
0x107e73305 <+389>: cmpq $0x40, %rax
0x107e73309 <+393>: jae 0x107e73329 ; <+425>
0x107e7330b <+395>: movzbl %dil, %edx
0x107e7330f <+399>: movb %al, %cl
0x107e73311 <+401>: shlq %cl, %rdx
0x107e73314 <+404>: orq %r11, %rdx
0x107e73317 <+407>: movq %rdx, -0x10(%rbp)
0x107e7331b <+411>: leaq -0x10(%rbp), %rdi
0x107e7331f <+415>: leaq 0x1(%rsi,%rdi), %rsi
0x107e73324 <+420>: jmp 0x107e73196 ; <+22>
0x107e73329 <+425>: leaq 0xd3c62(%rip), %rdi ; "fatal error"
0x107e73330 <+432>: leaq 0xd3df9(%rip), %rcx ; "shift amount is larger than type size in bits"
0x107e73337 <+439>: movl $0xb, %esi
0x107e7333c <+444>: movl $0x2, %edx
0x107e73341 <+449>: movl $0x2d, %r8d
0x107e73347 <+455>: movl $0x2, %r9d
0x107e7334d <+461>: callq 0x107e73180 ; <+0>
0x107e73352 <+466>: leaq 0xd3c39(%rip), %rdi ; "fatal error"
0x107e73359 <+473>: leaq 0xd49f0(%rip), %rcx ; "value is outside of Unicode codespace"
0x107e73360 <+480>: movl $0xb, %esi
0x107e73365 <+485>: movl $0x2, %edx
0x107e7336a <+490>: movl $0x25, %r8d
0x107e73370 <+496>: movl $0x2, %r9d
0x107e73376 <+502>: callq 0x107e73180 ; <+0>
0x107e7337b <+507>: nopl (%rax,%rax)
我不知道为什么会发生这种情况.
I don't know why this happens though.
推荐答案
我会检查缩略图图像数据是否为 nil,在这种情况下忽略它.可能记录被标记为有缩略图,但由于某种原因无法加载,例如不兼容的图像类型.
I would check if thumbnailImageData is nil and ignore it in that case. It's possible that a record is marked as having a thumbnail but it can't be loaded for some reason, like an incompatible image type.
这篇关于获取时应用程序崩溃 >800 个使用 iOS 9 联系人框架的联系人的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!