Swift: 复制用户在ABPersonViewController中选择的信息到字典
Swift: Copy Information Selected by User in ABPersonViewController to Dictionary
我正在尝试实现 func personViewController(personViewController: ABPersonViewController!,
shouldPerformDefaultActionForPerson person: ABRecord!,
property property: ABPropertyID,
identifier valueIdentifier: ABMultiValueIdentifier) -> Bool
函数,它是 ABPersonViewControllerDelegate
协议的一部分,每当用户单击 ABPersonViewController
中的项目时调用,这样用户选择的任何信息都将被复制到 [String : String]
字典中,这样 属性 名称将成为 属性 值的键:比方说 [..."kABPersonFirstNameProperty" : "Alexander"...]
。
我还想避免切换或一长串条件测试 属性 是这个还是那个;我宁愿尽可能一般地处理它——我只尝试两种不同的情况:如果 属性 是单个值或多个值。如果它是一个多值,我想复制所有可用的信息。
例如,如果用户点击地址,结果可能是这样的:[..."kABPersonAddressStreetKey" : "1 Infinite Loop", "kABPersonAddressCityKey" : "Cupertino" , "kABPersonAddressStateKey", "California (or CA?)"...]
。
经过数小时搜索 Apple Developer Library 和相关的 SO 问题(我知道这很可悲),这就是我的全部:
func personViewController(personViewController: ABPersonViewController!,
shouldPerformDefaultActionForPerson person: ABRecord!,
property property: ABPropertyID,
identifier valueIdentifier: ABMultiValueIdentifier) -> Bool {
s["kABPersonFirstNameProperty"] = ABRecordCopyValue(person, kABPersonFirstNameProperty) as! String //the name can't actually be selected by the user, but I want to capture it anyway
s["kABPersonLastNameProperty"] = ABRecordCopyValue(person, kABPersonLastNameProperty) as! String
if valueIdentifier == 0 { //property is a single property, not a multivalue property
let record = ABRecordCopyValue(person, property)
s[property as! String!] = record as! String
} else { //property is an ABMultiValue
let multiRecord = ABRecordCopyValue(person, property) as! ABMultiValueRef
s[property as! String] = ABMultiValueGetIndexForIdentifier(multiRecord, valueIdentifier)
}
return false
}
我看得出来少了很多东西——有没有可能把它浓缩成一本字典?
提前致谢(并向提供完整、正确答案的人提供 100 点声望)。
恐怕没有通用的方法可以从 AddressBook 中检索信息,因为有太多不同的集合和 属性 类型。
这是一个在用户点击地址字段时获取 first name
、last name
和 address
信息的示例。
假定字典 s
被声明为
var s = Dictionary<String, AnyObject>()
func personViewController(personViewController: ABPersonViewController!, shouldPerformDefaultActionForPerson person: ABRecord!, property: ABPropertyID, identifier: ABMultiValueIdentifier) -> Bool {
addPropertyForKey("FirstName", person : person, property: kABPersonFirstNameProperty)
addPropertyForKey("LastName", person : person, property: kABPersonLastNameProperty)
if (property == kABPersonAddressProperty) {
let multiRecord : ABMultiValueRef = ABRecordCopyValue(person, property).takeUnretainedValue()
let index = ABMultiValueGetIndexForIdentifier(multiRecord, identifier)
let addressRecord :AnyObject = ABMultiValueCopyValueAtIndex(multiRecord, index).takeUnretainedValue()
addValuesFromRecord(addressRecord, forKeys:["Street", "City", "State", "ZIP", "Country", "CountryCode"])
println(s)
}
return false
}
func addPropertyForKey(key : String, person: ABRecord, property : ABPropertyID)
{
let value : AnyObject = ABRecordCopyValue(person, property).takeUnretainedValue()
s[key] = value
}
func addValuesFromRecord(record : AnyObject, forKeys keys : [String])
{
for key in keys {
if let value : AnyObject = record[key] {
s[key] = value
}
}
}
为了尽可能通用,所有值都声明为 AnyObject
以vadian的回答为起点,我编译了以下内容,它将收集并复制用户可以select的几乎所有信息(以及一些用户无法点击的信息) on—名字、姓氏、组织—自动)。
这是一项正在进行的工作,我会在继续添加对更多属性的支持时对其进行更新,但目前它适用于名字、姓氏、电子邮件、phone 号码、地址和一些社交资料。
在某些情况下我不得不使用间接方法:例如,将标签没有指定键的 phone 个数字存储为 kAB_Label
s,并且它还没有采用电子邮件地址的标签。
s
类型为 Dictionary<String, AnyObject>
,这里是:
func personViewController(personViewController: ABPersonViewController!, shouldPerformDefaultActionForPerson person: ABRecord!, property: ABPropertyID, identifier: ABMultiValueIdentifier) -> Bool {
addPropertyForKey("kABPersonFirstNameProperty", person : person, property: kABPersonFirstNameProperty)
addPropertyForKey("kABPersonLastNameProperty", person : person, property: kABPersonLastNameProperty)
addPropertyForKey("kABPersonOrganizationProperty", person: person, property: kABPersonOrganizationProperty)
if (property == kABPersonAddressProperty) {
let multiRecord : ABMultiValueRef = ABRecordCopyValue(person, property).takeUnretainedValue()
let index = ABMultiValueGetIndexForIdentifier(multiRecord, identifier)
let addressRecord :AnyObject = ABMultiValueCopyValueAtIndex(multiRecord, index).takeUnretainedValue()
addValuesFromRecord(addressRecord, forKeys:["Street", "City", "State", "ZIP", "Country", "CountryCode"])
}
if (property == kABPersonEmailProperty) {
let multiRecord: ABMultiValueRef = ABRecordCopyValue(person, property).takeUnretainedValue()
let index = ABMultiValueGetIndexForIdentifier(multiRecord, identifier)
let email = ABMultiValueCopyValueAtIndex(multiRecord, index).takeUnretainedValue() as! String
if (s["kABPersonEmailProperty(1)"] == nil) {
s["kABPersonEmailProperty(1)"] = email
} else {
s["kABPersonEmailProperty(2)"] = email
}
}
if (property == kABPersonSocialProfileProperty) {
let multiRecord: ABMultiValueRef = ABRecordCopyValue(person, property).takeUnretainedValue()
let index = ABMultiValueGetIndexForIdentifier(multiRecord, identifier)
let profile = ABMultiValueCopyValueAtIndex(multiRecord, index).takeUnretainedValue()
let profileType = profile["service"] as! String
let profileName = profile["username"] as! String
switch profileType {
case "facebook" : s["kABPersonSocialProfileServiceFacebook"] = profileName
case "twitter" : s["kABPersonSocialProfileServiceTwitter"] = profileName
case "sinaweibo": s["kABPersonSocialProfileServiceSinaWeibo"] = profileName
default: break
}
}
if (property == kABPersonPhoneProperty) {
let multiRecord : ABMultiValueRef = ABRecordCopyValue(person, property).takeUnretainedValue()
let index = ABMultiValueGetIndexForIdentifier(multiRecord, identifier)
let number = ABMultiValueCopyValueAtIndex(multiRecord, index).takeUnretainedValue() as! String
let locLabel: CFStringRef = (ABMultiValueCopyLabelAtIndex(multiRecord, index) != nil) ? ABMultiValueCopyLabelAtIndex(multiRecord, index).takeUnretainedValue() as CFStringRef : ""
let customLabel = String (stringInterpolationSegment: ABAddressBookCopyLocalizedLabel(locLabel))
var cfStr:CFTypeRef = locLabel
var nsTypeString = cfStr as! NSString
var a:String = nsTypeString as String
var b = a
if (a.rangeOfString("_$!<") != nil) {
b = a.substringFromIndex(a.rangeOfString("_$!<")!.endIndex)
b = b.substringToIndex(b.rangeOfString(">!$_")!.startIndex)
}
switch b {
case "Mobile" : s["kABPersonPhoneMobileLabel"] = number
case "iPhone" : s["kABPersonPhoneIPhoneLabel"] = number
case "Main" : s["kABPersonPhoneMainLabel"] = number
case "Home" : s["kABHomeLabel"] = number
case "Work" : s["kABWorkLabel"] = number
case "Other" : s["kABOtherLabel"] = number
default: break
}
}
println(s)
return false
}
拜托,任何人都可以随意复制any/all 部分有用的内容。
我正在尝试实现 func personViewController(personViewController: ABPersonViewController!,
shouldPerformDefaultActionForPerson person: ABRecord!,
property property: ABPropertyID,
identifier valueIdentifier: ABMultiValueIdentifier) -> Bool
函数,它是 ABPersonViewControllerDelegate
协议的一部分,每当用户单击 ABPersonViewController
中的项目时调用,这样用户选择的任何信息都将被复制到 [String : String]
字典中,这样 属性 名称将成为 属性 值的键:比方说 [..."kABPersonFirstNameProperty" : "Alexander"...]
。
我还想避免切换或一长串条件测试 属性 是这个还是那个;我宁愿尽可能一般地处理它——我只尝试两种不同的情况:如果 属性 是单个值或多个值。如果它是一个多值,我想复制所有可用的信息。
例如,如果用户点击地址,结果可能是这样的:[..."kABPersonAddressStreetKey" : "1 Infinite Loop", "kABPersonAddressCityKey" : "Cupertino" , "kABPersonAddressStateKey", "California (or CA?)"...]
。
经过数小时搜索 Apple Developer Library 和相关的 SO 问题(我知道这很可悲),这就是我的全部:
func personViewController(personViewController: ABPersonViewController!,
shouldPerformDefaultActionForPerson person: ABRecord!,
property property: ABPropertyID,
identifier valueIdentifier: ABMultiValueIdentifier) -> Bool {
s["kABPersonFirstNameProperty"] = ABRecordCopyValue(person, kABPersonFirstNameProperty) as! String //the name can't actually be selected by the user, but I want to capture it anyway
s["kABPersonLastNameProperty"] = ABRecordCopyValue(person, kABPersonLastNameProperty) as! String
if valueIdentifier == 0 { //property is a single property, not a multivalue property
let record = ABRecordCopyValue(person, property)
s[property as! String!] = record as! String
} else { //property is an ABMultiValue
let multiRecord = ABRecordCopyValue(person, property) as! ABMultiValueRef
s[property as! String] = ABMultiValueGetIndexForIdentifier(multiRecord, valueIdentifier)
}
return false
}
我看得出来少了很多东西——有没有可能把它浓缩成一本字典?
提前致谢(并向提供完整、正确答案的人提供 100 点声望)。
恐怕没有通用的方法可以从 AddressBook 中检索信息,因为有太多不同的集合和 属性 类型。
这是一个在用户点击地址字段时获取 first name
、last name
和 address
信息的示例。
假定字典 s
被声明为
var s = Dictionary<String, AnyObject>()
func personViewController(personViewController: ABPersonViewController!, shouldPerformDefaultActionForPerson person: ABRecord!, property: ABPropertyID, identifier: ABMultiValueIdentifier) -> Bool {
addPropertyForKey("FirstName", person : person, property: kABPersonFirstNameProperty)
addPropertyForKey("LastName", person : person, property: kABPersonLastNameProperty)
if (property == kABPersonAddressProperty) {
let multiRecord : ABMultiValueRef = ABRecordCopyValue(person, property).takeUnretainedValue()
let index = ABMultiValueGetIndexForIdentifier(multiRecord, identifier)
let addressRecord :AnyObject = ABMultiValueCopyValueAtIndex(multiRecord, index).takeUnretainedValue()
addValuesFromRecord(addressRecord, forKeys:["Street", "City", "State", "ZIP", "Country", "CountryCode"])
println(s)
}
return false
}
func addPropertyForKey(key : String, person: ABRecord, property : ABPropertyID)
{
let value : AnyObject = ABRecordCopyValue(person, property).takeUnretainedValue()
s[key] = value
}
func addValuesFromRecord(record : AnyObject, forKeys keys : [String])
{
for key in keys {
if let value : AnyObject = record[key] {
s[key] = value
}
}
}
为了尽可能通用,所有值都声明为 AnyObject
以vadian的回答为起点,我编译了以下内容,它将收集并复制用户可以select的几乎所有信息(以及一些用户无法点击的信息) on—名字、姓氏、组织—自动)。
这是一项正在进行的工作,我会在继续添加对更多属性的支持时对其进行更新,但目前它适用于名字、姓氏、电子邮件、phone 号码、地址和一些社交资料。
在某些情况下我不得不使用间接方法:例如,将标签没有指定键的 phone 个数字存储为 kAB_Label
s,并且它还没有采用电子邮件地址的标签。
s
类型为 Dictionary<String, AnyObject>
,这里是:
func personViewController(personViewController: ABPersonViewController!, shouldPerformDefaultActionForPerson person: ABRecord!, property: ABPropertyID, identifier: ABMultiValueIdentifier) -> Bool {
addPropertyForKey("kABPersonFirstNameProperty", person : person, property: kABPersonFirstNameProperty)
addPropertyForKey("kABPersonLastNameProperty", person : person, property: kABPersonLastNameProperty)
addPropertyForKey("kABPersonOrganizationProperty", person: person, property: kABPersonOrganizationProperty)
if (property == kABPersonAddressProperty) {
let multiRecord : ABMultiValueRef = ABRecordCopyValue(person, property).takeUnretainedValue()
let index = ABMultiValueGetIndexForIdentifier(multiRecord, identifier)
let addressRecord :AnyObject = ABMultiValueCopyValueAtIndex(multiRecord, index).takeUnretainedValue()
addValuesFromRecord(addressRecord, forKeys:["Street", "City", "State", "ZIP", "Country", "CountryCode"])
}
if (property == kABPersonEmailProperty) {
let multiRecord: ABMultiValueRef = ABRecordCopyValue(person, property).takeUnretainedValue()
let index = ABMultiValueGetIndexForIdentifier(multiRecord, identifier)
let email = ABMultiValueCopyValueAtIndex(multiRecord, index).takeUnretainedValue() as! String
if (s["kABPersonEmailProperty(1)"] == nil) {
s["kABPersonEmailProperty(1)"] = email
} else {
s["kABPersonEmailProperty(2)"] = email
}
}
if (property == kABPersonSocialProfileProperty) {
let multiRecord: ABMultiValueRef = ABRecordCopyValue(person, property).takeUnretainedValue()
let index = ABMultiValueGetIndexForIdentifier(multiRecord, identifier)
let profile = ABMultiValueCopyValueAtIndex(multiRecord, index).takeUnretainedValue()
let profileType = profile["service"] as! String
let profileName = profile["username"] as! String
switch profileType {
case "facebook" : s["kABPersonSocialProfileServiceFacebook"] = profileName
case "twitter" : s["kABPersonSocialProfileServiceTwitter"] = profileName
case "sinaweibo": s["kABPersonSocialProfileServiceSinaWeibo"] = profileName
default: break
}
}
if (property == kABPersonPhoneProperty) {
let multiRecord : ABMultiValueRef = ABRecordCopyValue(person, property).takeUnretainedValue()
let index = ABMultiValueGetIndexForIdentifier(multiRecord, identifier)
let number = ABMultiValueCopyValueAtIndex(multiRecord, index).takeUnretainedValue() as! String
let locLabel: CFStringRef = (ABMultiValueCopyLabelAtIndex(multiRecord, index) != nil) ? ABMultiValueCopyLabelAtIndex(multiRecord, index).takeUnretainedValue() as CFStringRef : ""
let customLabel = String (stringInterpolationSegment: ABAddressBookCopyLocalizedLabel(locLabel))
var cfStr:CFTypeRef = locLabel
var nsTypeString = cfStr as! NSString
var a:String = nsTypeString as String
var b = a
if (a.rangeOfString("_$!<") != nil) {
b = a.substringFromIndex(a.rangeOfString("_$!<")!.endIndex)
b = b.substringToIndex(b.rangeOfString(">!$_")!.startIndex)
}
switch b {
case "Mobile" : s["kABPersonPhoneMobileLabel"] = number
case "iPhone" : s["kABPersonPhoneIPhoneLabel"] = number
case "Main" : s["kABPersonPhoneMainLabel"] = number
case "Home" : s["kABHomeLabel"] = number
case "Work" : s["kABWorkLabel"] = number
case "Other" : s["kABOtherLabel"] = number
default: break
}
}
println(s)
return false
}
拜托,任何人都可以随意复制any/all 部分有用的内容。