21

Square 的新名片盒 iOS 应用程序具有“创建帐户”功能。点击它,它会显示一个表格,其中包含用户在地址簿中的条目。

这怎么可能?有人知道吗?我认为这是不可能的,以这种方式获取用户的信息。这不是 iOS 5.0 的东西,afaict。

4

5 回答 5

56

我能想出的唯一解决方案是使用设备名称,然后在地址簿中搜索匹配项。这假设有人会使用特定的命名约定。例如,我使用“Nik's iPhone”作为我的设备名称。我也是我的通讯录中唯一的 Nik,所以对于我的场景来说,使用's之前的文本作为所有者名称非常有效。

它利用了 ABContactHelper 的 Erica Sadun 为 ABAddressBook 提供的非常方便的包装。我将枚举代码保留在其中,而不是在 0 处使用数组索引,因为可能会返回少量匹配项,因此您可以扩展以向用户提供选择“他们的”详细信息的选项。虽然不完全匹配方形案例解决方案,但效果很好。恕我直言。

NSString *firstname;
NSString *lastname;

NSString *ownerName = [[UIDevice currentDevice] name];

NSRange t = [ownerName rangeOfString:@"'s"];
if (t.location != NSNotFound) {
    ownerName = [ownerName substringToIndex:t.location];
} 

NSArray *matches = [ABContactsHelper contactsMatchingName:ownerName];
if(matches.count == 1){ 
    for (ABContact *contact in matches){
        firstname = [contact firstname];
        lastname = [contact lastname];

    }
}
于 2011-11-08T22:51:54.040 回答
23

由于需要应用程序请求访问地址簿的权限的更改,此方法不再有效。Nik Burns 的回答效果很好,但它需要访问地址簿。

我下载了 Square Wallet(它是原始问题中 Square Card Case 引用的继承者),它不再预先填充注册表单。Path 也用于执行设备名称地址簿技巧,但它也不再预先填充注册表单。

使用上述方法,您仍然可以在请求联系人访问权限 预先填充注册表单,但它会失去所需的“神奇”体验。

于 2013-04-24T21:40:46.517 回答
1

由于我不满意必须使用设备名称,因此我选择使用与“ME”相对应的地址簿的第一条记录

ABAddressBookRef addressBook = ABAddressBookCreate( );
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople( addressBook );
ABRecordRef ref = CFArrayGetValueAtIndex( allPeople, 0 );
ABContact * contact = [ABContact contactWithRecord:ref];
于 2016-01-14T23:00:49.890 回答
0

不,你可以

http://developer.apple.com/library/ios/#documentation/ContactData/Conceptual/AddressBookProgrammingGuideforiPhone/Introduction.html#//apple_ref/doc/uid/TP40007744

我知道它在 4.X 中可用;不只是 5.0 的功能......不确定它是否更早可用。

于 2011-11-03T19:53:14.100 回答
0

我有同样的问题,但在 Swift 中,并使用了 Nik Burns 的建议并写了一篇关于它的博客文章:http: //paulpeelen.com/2016/01/20/prefill-an-signup-form-in-ios-using -swift-and-cncontact/

这基本上是 Swift 的最终结果:

import Contacts

...

    @IBOutlet weak var nameFirst: UILabel!
    @IBOutlet weak var nameLast: UILabel!
    @IBOutlet weak var email: UILabel!
    @IBOutlet weak var phoneNo: UILabel!
    @IBOutlet weak var address: UILabel!

    /**
     Search the addressbook for the contact
     */
    private func getMe() {
        let ownerName = getOwnerName()
        let store = CNContactStore()

        do {
            // Ask permission from the addressbook and search for the user using the owners name
            let contacts = try store.unifiedContactsMatchingPredicate(CNContact.predicateForContactsMatchingName(ownerName), keysToFetch:[CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey, CNContactPostalAddressesKey, CNContactEmailAddressesKey])

            //assuming contain at least one contact
            if let contact = contacts.first {
                // Checking if phone number is available for the given contact.
                if (contact.isKeyAvailable(CNContactPhoneNumbersKey)) {
                    // Populate the fields
                    populateUsingContact(contact)
                } else {
                    //Refetch the keys
                    let keysToFetch = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey, CNContactPostalAddressesKey, CNContactEmailAddressesKey]
                    let refetchedContact = try store.unifiedContactWithIdentifier(contact.identifier, keysToFetch: keysToFetch)

                    // Populate the fields
                    populateUsingContact(refetchedContact)
                }
            }
        } catch let e as NSError {
            print(e.localizedDescription)
        }

    }

    /**
     Get the device owners name

     - returns: The owners name
     */
    private func getOwnerName() -> String {
        // Get the device owners name
        var ownerName = UIDevice.currentDevice().name.trimmedString.stringByReplacingOccurrencesOfString("'", withString: "")
        // Get the model of the device
        let model = UIDevice.currentDevice().model

        // Remove the device name from the owners name
        if let t = ownerName.rangeOfString("s \(model)") {
            ownerName = ownerName.substringToIndex(t.startIndex)
        }

        return ownerName.trimmedString
    }

    /**
     Populate the fields using a contact

     - parameter contact: The contact to use
     */
    private func populateUsingContact(contact: CNContact) {
        // Set the name fields
        nameFirst.text = contact.givenName
        nameLast.text = contact.familyName

        // Check if there is an address available, it might be empty
        if (contact.isKeyAvailable(CNContactPostalAddressesKey)) {
            if let
                addrv = contact.postalAddresses.first,
                addr = addrv.value as? CNPostalAddress where addrv.value is CNPostalAddress
            {
                let address = "\(addr.street)\n\(addr.postalCode) \(addr.city)\n\(addr.country)"
                self.address.text = address
            }
        }

        // Check if there is a phonenumber available, it might be empty
        if (contact.isKeyAvailable(CNContactPhoneNumbersKey)) {
            if let
                phonenumberValue = contact.phoneNumbers.first,
                pn = phonenumberValue.value as? CNPhoneNumber where phonenumberValue.value is CNPhoneNumber
            {
                phoneNo.text = pn.stringValue
            }
        }
    }

和扩展:

extension String {

    /// Trim a string
    var trimmedString: String {
        return stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
    }

}
于 2016-01-20T15:12:01.547 回答