2

プロトコルの一部であり、ユーザーが のアイテムをクリックするたびに呼び出されるfunc personViewController(personViewController: ABPersonViewController!, shouldPerformDefaultActionForPerson person: ABRecord!, property property: ABPropertyID, identifier valueIdentifier: ABMultiValueIdentifier) -> Bool関数を実装しようとしています。これにより、ユーザーが選択した情報がディクショナリにコピーされ、プロパティ名がキーになります。プロパティ値: 、たとえば。ABPersonViewControllerDelegateABPersonViewController[String : String][..."kABPersonFirstNameProperty" : "Alexander"...]

また、プロパティがこれであるかどうかをテストするスイッチや条件の長いリストも避けたいと思います。できる限り一般的に処理したいと思います。ここでは、プロパティが単一値または複数値の場合の 2 つの異なるケースのみを扱います。複数値の場合は、利用可能なすべての情報をコピーしたいと思います。

たとえば、ユーザーがアドレスをクリックすると、結果は次のようになります[..."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の評判があります)。

4

2 に答える 2

2

vadian の回答を出発点として使用して、次のようにまとめました。これにより、ユーザーが選択できるほぼすべての情報 (およびユーザーがクリックできない一部の情報 (名、姓、組織) を収集して辞書にコピーします) -自動的)。

これは進行中の作業であり、より多くのプロパティのサポートを追加し続けると更新されますが、現時点では、名、姓、電子メール、電話番号、住所、およびいくつかのソーシャル プロファイルで機能します。

kAB_Label場合によっては、間接的な方法を使用する必要がありました。たとえば、sとして指定されたキーをラベルに持たない電話番号を保存し、まだ電子メール アドレスのラベルを取得していません。

stype の時点で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
}

どなたでも、参考になる部分の一部または全部を自由にコピーしてください。

于 2015-08-06T21:37:42.383 に答える
0

残念ながら、AddressBook から情報を取得するための一般的な方法はありません。コレクションとプロパティの種類が多すぎるためです。

これは、ユーザーが住所フィールドをタップしたときに情報first namelast 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

于 2015-08-06T11:16:18.500 に答える