Maybe这不仅仅是回答你的问题,而是我处理通讯录的方式。
我定义了一个自定义运算符:
infix operator >>> { associativity left }
func >>> <T, V> (lhs: T, rhs: T -> V) -> V {
return rhs(lhs)
}
允许以更易读的方式链接多个函数调用,例如:
funcA(funcB(param))
变成
param >>> funcB >>> funcA
然后我使用这个函数将
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始终有值,而department则没有,因此适用于测试):
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? = ...
时已知。
我假设您已经处理了检查并请求用户允许访问通讯录的事宜。