【问题标题】:Swift: Copy Information Selected by User in ABPersonViewController to DictionarySwift:将用户在 ABPersonViewController 中选择的信息复制到字典
【发布时间】:2015-10-27 15:04:46
【问题描述】:

我正在尝试实现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?)"...]

这就是我所拥有的,经过几个小时的搜索苹果开发者库和相关的 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 声望提供完整、正确答案的人)。

【问题讨论】:

  • 正是我正在寻找的东西......当谈到 AB 世界时,Apple 资源似乎很稀少(和 Objective-C-y)。

标签: swift dictionary abaddressbook abpersonviewcontroller abrecord


【解决方案1】:

恐怕没有通用的方法可以从 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

【讨论】:

    【解决方案2】:

    以 vadian 的回答为起点,我编译了以下内容,它将收集用户可以选择的几乎所有信息并将其复制到字典中(以及一些用户无法点击的信息——名字、姓氏名称、组织——自动)。

    这是一项正在进行的工作,随着我继续添加对更多属性的支持,我将对其进行更新,但目前它适用于名字、姓氏、电子邮件、电话号码、地址和一些社交资料。

    在某些情况下,我不得不使用间接方法:例如,将标签没有指定键的电话号码存储为kAB_Labels,并且它还没有使用电子邮件地址的标签。

    s 的类型为 Dictionary&lt;String, AnyObject&gt;,这里是:

    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
    }
    

    请,任何人都可以随意复制它的任何/所有部分,这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2014-09-09
      • 1970-01-01
      • 1970-01-01
      • 2015-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-22
      相关资源
      最近更新 更多