Получите значение как быстрый тип из неуправляемого <AnyObject>. Например: ABRecordRef

Как получить значение типа Swift из объекта типа Unmanaged<AnyObject>. В моем примере используется ABRecordRef

Я создаю контактный объект для управления, когда получаю ABRecordRef, но у меня проблемы с переводом с ObjC. Вот что у меня есть:

init(recordRef: ABRecordRef) {
    if let firstName = ABRecordCopyValue(recordRef, kABPersonFirstNameProperty) {
        self.firstName = firstName

    }
}

Если бы это был ObjC, я бы сделал:

CFTypeRef firstNameRef = ABRecordCopyValue(recordRef, kABPersonFirstNameProperty);
if (firstNameRef) {
    self.firstName = (__bridge NSString *)firstNameRef;
}

Я не могу найти правильную комбинацию downcasting/conversion, поэтому любая помощь будет оценена.

Ответы

Ответ 1

Поскольку NoOne ответил, прежде чем я его решила, я добавлю ответ здесь:

firstName.takeRetainedValue() as? String

Если вы посмотрите на заголовок типа структуры Unmanaged, вы найдете следующее:

/// Get the value of this unmanaged reference as a managed
/// reference and consume an unbalanced retain of it.
///
/// This is useful when a function returns an unmanaged reference
/// and you know that you're responsible for releasing the result.
func takeRetainedValue() -> T

Итак, поскольку CFTypeRef преобразуется в Unmanaged<AnyObject> в Swift.

Unmanaged использует generics для определения возвращаемого типа и объявляется следующим образом:

Unmanaged<T> 

Наш объект имеет тип Unmanaged<AnyObject>, что означает, что takeRetainedValue() вернет тип T, или в нашем случае введите AnyObject. Я использую необязательный downcasting, поскольку мое свойство firstName имеет тип String?.

Вы можете использовать метод takeRetainedValue, чтобы получить значение из вашего объекта Unmanaged. В API Foundation API, я предполагаю, что они будут в основном иметь тип Unmanaged<AnyObject>!, и потребуется понижение. Общая формула выглядит следующим образом:

var unmanagedObject: Unmanaged<AnyObject> = someFunctionThatReturnsAnUnmanagedObject()
var newValue: Type = unmanagedObject.takeRetainedValue as Type

Ответ 2

import UIKit
import AddressBook

class ViewController: UIViewController {

lazy var addressBook: ABAddressBookRef = {
    var error: Unmanaged<CFError>?
    return ABAddressBookCreateWithOptions(nil, &error).takeRetainedValue() as ABAddressBookRef
}()

@IBAction func GetPeople(sender: UIButton) {
    var ab: ABAddressBookRef = addressBook

    switch ABAddressBookGetAuthorizationStatus(){
    case .Authorized:
        println("Authorized")
        readFromAddressBook(addressBook)
    case .Denied:
        println("Denied")
    case .Restricted:
        println("Restricted")
    case .NotDetermined:
        println("Not determined")
        ABAddressBookRequestAccessWithCompletion(addressBook,
            {[weak self] (granted: Bool, error: CFError!) in
                if granted {
                    let strongSelf = self!
                    println("Access is granted")
                    strongSelf.readFromAddressBook(strongSelf.addressBook)
                }
                else{
                    println("Access is not granted")
                }
        })
    default:
        break
    }
}

func readFromAddressBook(addressBook: ABAddressBookRef){
    let allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook).takeRetainedValue() as NSArray

    for person:ABRecordRef in allPeople{
        if let firstName = ABRecordCopyValue(person, kABPersonFirstNameProperty) {
            if let lastName = ABRecordCopyValue(person, kABPersonLastNameProperty) {
                let ln:String = (lastName.takeRetainedValue() as? String) ?? ""
                let fn:String = (firstName.takeRetainedValue() as? String) ?? ""
                println("\(ln) - \(fn)")
            }
        }
    }
}

}