2014-09-23 25 views
11
için yönetilmeyen adres defteri tek değerli özelliği kontrol ediliyor

iOS geliştirme ve hızlı bir şekilde göreceli olarak yeniyim. Ancak bu noktaya kadar her zaman, stackoverflow ve çeşitli dökümantasyon ve eğitimler üzerine bir araştırma yaparak kendime yardımcı olabiliyordum. Bununla birlikte, henüz bir çözüm bulamadığım bir sorun var.Swift - N12

Kullanıcı adres defterinden bazı veriler almak istiyorum (örneğin, tek değerli özellik kABPersonFirstNameProperty). .takeRetainedValue() işlevi, bu kişinin adres defterinde bir firstName değeri yoksa bir hata attığından, ABRecordCopyValue() işlevinin bir değer döndürdüğünden emin olmalıyım. Bir kapatma bu kontrol etmeye çalıştı:

let contactFirstName: String = { 
    if (ABRecordCopyValue(self.contactReference, kABPersonFirstNameProperty) != nil) { 
     return ABRecordCopyValue(self.contactReference, kABPersonFirstNameProperty).takeRetainedValue() as String 
    } else { 
     return "" 
    } 
}() 

contactReference tip ABRecordRef! Porte Adres temasın firstName değer sağlar

, her şey gayet iyi çalışıyor bir değişkendir. Ancak, firstName değilse, uygulama .takeRetainedValue() işlevi tarafından çöküyor. Görünüşe göre, if deyimi yardımcı olmadığından, ABRecordCopyValue() işlevinin yönetilmeyen döndürme değeri, hiç bir ad olmadığı halde sıfır değildir.

Umarım problemimi netleştirebildim. Birisi bana beyin dalgasıyla yardım ederse harika olurdu.

cevap

32

, kullandığım şu:

func rawValueFromABRecordRef<T>(recordRef: ABRecordRef, forProperty property: ABPropertyID) -> T? { 
    var returnObject: T? = nil 
    if let rawValue: Unmanaged<AnyObject>? = ABRecordCopyValue(recordRef, property) { 
     if let unwrappedValue: AnyObject = rawValue?.takeRetainedValue() { 
      println("Passed: \(property)") 
      returnObject = unwrappedValue as? T 
     } 
     else { 
      println("Failed: \(property)") 
     } 
    } 
    return returnObject 
} 

Böyle Mülkünüzde kullanabilirsiniz:

+0

İkinci versiyonunu beğendim. Bunun için teşekkür ederim! – Rob

+2

Birkaç gün sonra aradığım cevap THIS oldu! Paylaştığın için çok teşekkürler! – kev

+1

Seçenek 1 harikalar yaratıyor – Dean

1

Belki de sadece sorunuzu yanıtlamaktan çok daha fazlası var, ancak bu adres defteri ile nasıl başa çıkacağım.

Özel bir operatörü tanımladığınız

: Örneğin,

infix operator >>> { associativity left } 
func >>> <T, V> (lhs: T, rhs: T -> V) -> V { 
    return rhs(lhs) 
} 

daha okunabilir bir şekilde zincire fonksiyonları birden fazla çağrı izin:

funcA(funcB(param)) 

olur

param >>> funcB >>> funcA 

Sonra bu işlevi Unmanaged<T> bir hızlı türüne dönüştürmek için kullanıyorum:

func extractUnmanaged<T, V>(value: Unmanaged<T>?) -> V? { 
    if let value = value { 
     var innerValue: T? = value.takeRetainedValue() 
     if let innerValue: T = innerValue { 
      return innerValue as? V 
     } 
    } 
    return .None 
} 

ve CFArray ile çalışan bir meslektaşı:

func extractUnmanaged(value: Unmanaged<CFArray>?) -> [AnyObject]? { 
    if let value = value { 
     var innerValue: CFArray? = value.takeRetainedValue() 
     if let innerValue: CFArray = innerValue { 
      return innerValue.__conversion() 
     } 
    } 
    return .None 
} 

ve bu tüm kişileri, adres defteri açın almak için koddur, ve her biri için her zaman simülatörü firstName (ilk ad ve organizasyon okumak departman bunu yapmaz, bir değere sahiptir, bu nedenle) test için iyidir:

let addressBook: ABRecordRef? = ABAddressBookCreateWithOptions(nil, nil) >>> extractUnmanaged 
let results = ABAddressBookCopyArrayOfAllPeople(addressBook) >>> extractUnmanaged 
if let results = results { 
    for result in results { 
     let firstName: String? = (result, kABPersonFirstNameProperty) >>> ABRecordCopyValue >>> extractUnmanaged 
     let organization: String? = (result, kABPersonOrganizationProperty) >>> ABRecordCopyValue >>> extractUnmanaged 
     println("\(firstName) - \(organization)") 
    } 
} 

Not println açıklamada isteğe yazdırır olduğunu, konsolun 0 göreceğiniz bu yüzden Sadece David yerine. Tabi ki bu sadece gösteri amaçlıdır. Sorunuza cevap fonksiyonu opsiyonel yönetilmeyen sürer extractUnmanaged olduğu

, ambalajından , isteğe bağlı olarak tutulan değerini alır

, ambalajından ve sonunda için String olan hedef türü, bir döküm çalışır ilk özellik. Inferral tipi, T ve V'nin ne olduğunu bulmaya çalışır: T, Unmanaged'da sarılı olan tiptir, V, let firstName: String? = ... hedef değişkeni bildirilirken belirtildiği için bilinen geri dönüş türüdür.

Zaten kontrol etmek ve kullanıcının adres defterine erişim izni istemek için halledilmiş olduğunu varsayalım. Çeşitli özelliklere sahip ilişkili değerleri istiyorsanız

let contactFirstName: String = { 
    if let firstName: String = rawValueFromABRecordRef(recordRef, forProperty: kABPersonFirstNameProperty) { 
     return firstName 
    } 
    else { 
     return "" 
    } 
}() 
+0

detaylı cevap için size Antonio ederiz! Ayrıca, onunla başa çıkabileceğiniz esnek ve yeniden kullanılabilir yolu görmek harika. 'extractUnmanaged()' işlevinin (jeneriksiz) biraz değiştirilmiş bir sürümü sorunumu çözdü. – Rob

+0

Genel olmayan sürüm ilk taslağımdı, daha sonra bu tür genel çözüm ve diğer tüm öğelerle birlikte geldiğim farklı türleri dönüştürmek zorunda kaldım. Btw size yardımcı olduğuna sevindim – Antonio

5

Burada bu işlev sayesinde aldım sözdizimi:

let first = ABRecordCopyValue(person, kABPersonFirstNameProperty)?.takeRetainedValue() as? String 
let last = ABRecordCopyValue(person, kABPersonLastNameProperty)?.takeRetainedValue() as? String 

Yoksa isteğe bağlı bağlayıcı kullanabilirsiniz:

if let first = ABRecordCopyValue(person, kABPersonFirstNameProperty)?.takeRetainedValue() as? String { 
    // use `first` here 
} 
if let last = ABRecordCopyValue(person, kABPersonLastNameProperty)?.takeRetainedValue() as? String { 
    // use `last` here 
} 

Eğer gerçekten isteğe bağlı olmayan bir eksik değeri sıfır uzunlukta dize dönmek isterseniz, ?? operatörünü kullanabilirsiniz:

let first = ABRecordCopyValue(person, kABPersonFirstNameProperty)?.takeRetainedValue() as? String ?? "" 
let last = ABRecordCopyValue(person, kABPersonLastNameProperty)?.takeRetainedValue() as? String ?? "" 
+0

Neden aşağı oy? Yanlış olanı söylemezsen düzelemem. – Logan

+0

Cevabınız için teşekkür ederiz. Çok yardım görmek çok güzel! Bu arada, hiçbir şey oylamadım. Ne demek istiyorsun? – Rob

+0

@Rob - Senin olduğunu söylemeye çalışmıyordum, ama birisi benim cevabımı oyladı. Neden bunu kullandığımı bildiğimi ve benim için çalıştığını bilmek isterim. – Logan