Как приложение Square CardCase автоматически заполняет данные пользователя из адресной книги?

Квадратное новое приложение для карт iOS имеет функцию "Создать учетную запись". Нажмите на нее, и она отобразит форму, ПРЕДПОЛОЖЕННАЯ с записью пользователя из адресной книги.

Как это возможно? Кто-нибудь знает? Я думал, что это невозможно, чтобы получить информацию о пользователе таким образом. Это не iOS 5.0, афайк.

Ответ 1

единственным решением, которое я мог придумать, было использование имени устройства, а затем поиск в адресной книге для соответствия. это предполагает, что кто-то будет использовать конкретное соглашение об именах. Например, я использую "Nik iPhone" в качестве своего имени устройства. Я также являюсь единственным Nik в моем адресном журнале, поэтому для моего сценария хорошо работает текст до , как имя владельца.

Он использует очень удобную обертку для ABAddressBook Эрика Садун, ABContactHelper. Я оставил код перечисления вместо использования индекса массива в 0, так как скорее всего будет возвращено небольшое количество совпадений, чтобы вы могли расширить его, чтобы дать пользователю возможность выбрать "их" детали. Который, хотя точно не соответствует решению квадратного случая, работает хорошо. IMHO.

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];

    }
}

Ответ 2

Поскольку изменения, требующие от приложений запрашивать разрешения на доступ к адресной книге, этот метод больше не работает. Ответ Ник Бернса отлично поработал, но ему нужен доступ к адресной книге.

Я загрузил квадратный кошелек (который является преемником ссылок на квадратную карточку в исходном вопросе), и он больше не заполняет форму регистрации. Путь также используется для трюка адресной книги имени устройства, но он также больше не заполняет форму регистрации.

Используя вышеуказанный метод, вы все равно можете предварительно заполнить форму регистрации после запроса доступа к контактам, но она теряет желаемую "магию" " опыт.

Ответ 3

Поскольку я не был доволен необходимостью использовать имя устройства, я решил использовать первую запись адресной книги, которая соответствует "ME"

ABAddressBookRef addressBook = ABAddressBookCreate( );
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople( addressBook );
ABRecordRef ref = CFArrayGetValueAtIndex( allPeople, 0 );
ABContact * contact = [ABContact contactWithRecord:ref];

Ответ 4

У меня была такая же проблема, но в Swift я использовал предложение Nik Burns и написал сообщение в блоге об этом: http://paulpeelen.com/2016/01/20/prefill-an-signup-form-in-ios-using-swift-and-cncontact/ p >

Это в основном конечный результат в 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())
    }

}