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 namelast nameaddress 信息的示例。

假定字典 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_Labels,并且它还没有采用电子邮件地址的标签。

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 部分有用的内容。