2016-05-04 11 views
0

iOS 9連絡先フレームワークを使用してデバイス上のすべての統合連絡先を取得しようとしました。 > 800の連絡先を取得しようとすると、アプリがクラッシュしています。iOS 9連絡先フレームワークを使用して> 800件の連絡先を取得するとアプリケーションがクラッシュする

これはメモリの問題だと思います。

以下

@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; 
     } 

EDIT

だから、私はシミュレータでの連絡先の束を追加し、再現することができますクラッシュ。

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) 

これはしかしなぜ起こるかわからない。:ここで

は、スタックトレースです。 enter image description here

+0

クラッシュに関する質問を投稿する場合は、クラッシュに関する詳細をお知らせください。どのラインがクラッシュを引き起こしますか?エラーメッセージとは何ですか? – rmaddy

+0

奇妙なことは、私のクラッシュ報告システム(getsentry.com)に何も登録されていないということです。メモリがクラッシュしても、そのようなレポートは生成されません。何か案は? @rmaddy? – Ismailp

+0

デバッガで実行中にクラッシュさせることはできますか?問題の詳細を提示しないと、ここに誰も本当に助けにならない。 – rmaddy

答えて

0

この場合、thumbnailImageDataがnilであるかどうかを確認して無視します。レコードにサムネイルがあるとマークされている可能性はありますが、互換性のないイメージタイプのように何らかの理由でロードできない可能性があります。

3

私はあなたのコードを試してみましたが、すぐにまた問題なく1200レコードを読み込むことができました。最初はコードを変更していなかったので、なぜクラッシュするのか分かりません。私はいくつかの考えを持っていた。まず、CNContactFetchRequestの述語フィールドを使用しないのはなぜですか?私はそれが物事をはるかに速くし、サブセットを得ると思う。私はあなたのニーズに応えられないかもしれないことを理解しています。私は辞書に接触を変換するCNContactに拡張を作成し

func searchContacts(searchText: String?, callback: (NSArray) ->()) -> Void { 
    let contactStore = CNContactStore() 

    let keysToFetch = [ CNContactGivenNameKey, CNContactFamilyNameKey, CNContactImageDataAvailableKey, CNContactThumbnailImageDataKey ] 

    do { 
     var contacts = [NSDictionary](); 

     let fetchRequest = CNContactFetchRequest(keysToFetch: keysToFetch) 

     fetchRequest.sortOrder = CNContactSortOrder.GivenName 

     // Create a predicate here based on the search text passed in 
     fetchRequest.predicate = CNContact.predicateForContactsMatchingName(searchText!) 

     try contactStore.enumerateContactsWithFetchRequest(fetchRequest) { (cNContact, pointer) -> Void in 
      // Just append the contact because we won't have any that don't 
      // contain the search string since we used a predicate. 

      // The .dictionary property is from our extension and it converts 
      // the CNContact object to a dictionary 
      contacts.append(cNContact.dictionary) 
     } 

     callback([NSNull(), contacts]) 
    } 
    catch let error as NSError { 
     NSLog("Problem getting unified Contacts") 
     NSLog(error.localizedDescription) 

     callback([error.localizedDescription, NSNull()]) 
    } 

} 

注:ただし、ここではそれは私が試したリファクタリングと次のようになります。私は連絡先を検索するボイラープレートマスター詳細テーブルビューのプロジェクトにコードを投げ、私のリファクタリングを適用

好奇心のうち
extension CNContact { 
    var dictionary : NSDictionary { 

     var contact = [String: AnyObject]() 
     let phoneNumbers = NSMutableArray() 

     contact["identifier"]   = self.identifier 
     contact["givenName"]   = self.givenName 
     contact["familyName"]   = self.familyName 
     contact["imageDataAvailable"] = self.imageDataAvailable 

     if (self.imageDataAvailable) { 
      let thumbnailImageDataAsBase64String = self.thumbnailImageData!.base64EncodedStringWithOptions([]) 
      contact["thumbnailImageData"] = thumbnailImageDataAsBase64String     
     } 

     if (self.isKeyAvailable(CNContactPhoneNumbersKey)) { 
      for number in self.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; 
    } 
} 

:このコードは(CNContact)自己を除いて、コンテキストコンバージョンコードと同じです。ここから取得することができます:https://github.com/perlmunger/MemoryContacts。 (サンプルプロジェクトの検索バーには、検索する前に少なくとも3文字を入力する必要があります.btw)

+0

ありがとう、私は再現されたクラッシュで私の質問を編集しました。何か案は? – Ismailp

+0

@Ismailpデバイスで実行しようとしましたか? –

+0

はい、同じ動作 – Ismailp

関連する問題