也许这不仅仅是回答你的问题,但这就是我处理通讯录的方式。
我定义了一个自定义运算符:
infix operator >>> { associativity left }
func >>> <T, V> (lhs: T, rhs: T -> V) -> V {
return rhs(lhs)
}
允许以更易读的方式链接多个函数调用,例如:
funcA(funcB(param))
变成
param >>> funcB >>> funcA
然后我使用此函数将 an 转换Unmanaged<T>
为 swift 类型:
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
}
和与之合作的同行CFArray
:
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
}
这是打开地址簿,检索所有联系人,并为每个人读取名字和组织的代码(在模拟器中 firstName 总是有一个值,而部门没有,所以它有利于测试):
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)")
}
}
请注意,该println
语句会打印可选内容,因此您将在控制台中看到,Optional("David")
而不仅仅是David
. 当然这只是为了演示。
回答您的问题的函数是extractUnmanaged
,它接受一个可选的非托管,解包,将保留的值检索为可选,解包,最后尝试转换为目标类型,即String
名字属性。类型推断负责弄清楚 T 和 V 是什么:T 是包装在 中的类型Unmanaged
,V 是返回类型,这是已知的,因为在声明目标变量时指定let firstName: String? = ...
。
我想您已经注意检查并要求用户允许访问地址簿。