2016-06-09 4 views
0

Я внедряю ABAddressBook в iOS 8, и я начал с создания образца проекта, чтобы начать работу. Я создал проект с использованием шаблона приложения Single View. В viewDidAppear от ViewController.swiftViewController Я добавил код ниже:Утечка памяти в ABAddressBook iOS 8 в Swift

if ABAddressBookGetAuthorizationStatus() != .Authorized { 
    return 
} 
var error: Unmanaged<CFError>? 
if let addressBook: ABAddressBook? = ABAddressBookCreateWithOptions(nil, &error)?.takeRetainedValue() { 
    ABAddressBookRequestAccessWithCompletion(addressBook) { granted, error in 
     if error == nil && granted { 
      if let contacts = ABAddressBookCopyArrayOfAllPeople(addressBook)?.takeRetainedValue() as? NSArray { 
       for contact in contacts { 
        print("new contact") 
       } 
      } 
     } 
    } 
} else { 
    print(error?.takeRetainedValue()) 
} 

Это единственный код, у меня есть и приложение протечки! Я запускаю инструмент «Утечки», и он не дает достаточно хорошего контекста, почему приложение протекает.

Leak Инструмент Снимок Memory leaks tool snapshot

Вызов дерева Снимок

Memory leak call tree snapshot

Leak цикл Снимок

Memory leak cycle snapshot

ли я не выпускать что-то, что должно быть? Также я не могу позвонить CFRelease, потому что у меня включен ARC.

+0

Этот код выглядит хорошо для меня. Если вы случайно использовали 'takeUnretainedValue' где-нибудь, это может просочиться, но я не вижу ничего в вашем фрагменте кода. У iOS есть несколько подобных крошечных утечек, поэтому я не буду беспокоиться о них, если он не большой или вы видите, что какой-либо из ваших классов не освобождается. Кстати, если возможно, подумайте об использовании структуры «Контакты», которая проще в использовании и не требует хрупкого процесса вызовов «takeRetainedValue», которые делает инфраструктура AddressBook. – Rob

+1

'ABAddressBook' устарел в iOS 9. Вам, вероятно, удастся перейти к использованию' CNContactStore'. – gjeck

+0

@gjeck Я поддерживаю устройства iOS 8, поэтому я не могу использовать CNContactStore на устройствах iOS 8. – lostAtSeaJoshua

ответ

0

я не смог воспроизвести, но для того, что это стоит не следующие дало никаких утечек либо:

var addressBook: ABAddressBookRef? 

func extractABAddressBookRef(abRef: Unmanaged<ABAddressBookRef>!) -> ABAddressBookRef? { 
    if let ab = abRef { 
     return Unmanaged<NSObject>.fromOpaque(ab.toOpaque()).takeUnretainedValue() 
    } 
    return nil 
} 

func fetchAllContacts(completion: ((contacts: [String]?) -> Void)?) { 
    let authorizationStatus = ABAddressBookGetAuthorizationStatus() 
    switch authorizationStatus { 
    case .NotDetermined: 
     print("requesting access...") 
     var errorRef: Unmanaged<CFError>? = nil 
     addressBook = extractABAddressBookRef(ABAddressBookCreateWithOptions(nil, &errorRef)) 
     ABAddressBookRequestAccessWithCompletion(addressBook, { [weak self] success, error in 
      if success { 
       completion?(contacts: self?.getContactNames()) 
      } 
      else { 
       print("error") 
       completion?(contacts: nil) 
      } 
     }) 
    case .Denied, .Restricted: 
     print("access denied") 
     completion?(contacts: nil) 
    case .Authorized: 
     print("access granted") 
     completion?(contacts: self.getContactNames()) 
    } 
} 

func getContactNames() -> [String]? { 
    var errorRef: Unmanaged<CFError>? 
    addressBook = extractABAddressBookRef(ABAddressBookCreateWithOptions(nil, &errorRef)) 
    let contactList: NSArray = ABAddressBookCopyArrayOfAllPeople(addressBook).takeRetainedValue() 
    print("records in the array \(contactList.count)") 

    return contactList.map({ (record: AnyObject) -> String in 
     let contactRef: ABRecordRef = record 
     let contactName: String = ABRecordCopyCompositeName(contactRef).takeRetainedValue() as String 
     return contactName 
    }) 
} 

override func viewDidLoad() { 
    super.viewDidLoad() 

    fetchAllContacts { (contacts) in 
     print("fetched contacts \(contacts)") 
    } 
} 
+1

При получении 'AddressBookRef' вы должны использовать' takeRetainedValue', а не 'takeUnretainedValue'. Вам также не нужно заниматься танцем 'fromOpaque' /' toOpaque'. (Мы должны были сделать это в ранних версиях Swift, но не больше). – Rob

 Смежные вопросы

  • Нет связанных вопросов^_^