Ios Square的CardCase应用程序如何从通讯簿中自动填充用户的详细信息?

Ios Square的CardCase应用程序如何从通讯簿中自动填充用户的详细信息?,ios,abaddressbook,square,Ios,Abaddressbook,Square,Square的新卡盒iOS应用程序具有创建帐户功能。点击它,它会显示一个表单,其中预填充了地址簿中的用户条目 这怎么可能?有人知道吗?我认为这样获取用户信息是不可能的。这不是iOS 5.0,afaict。不,你可以 我知道它有4.X版本;不仅仅是一个5.0功能。。。我不确定它是否在早些时候可用。我能想到的唯一解决方案是使用设备名称,然后在通讯簿中搜索匹配项。这假设有人会使用特定的命名约定。例如,我使用‘Nik的iPhone’作为我的设备名。我也是我的通讯录中唯一的Nik,所以在我的场景中,使用’

Square的新卡盒iOS应用程序具有创建帐户功能。点击它,它会显示一个表单,其中预填充了地址簿中的用户条目

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

不,你可以


我知道它有4.X版本;不仅仅是一个5.0功能。。。我不确定它是否在早些时候可用。

我能想到的唯一解决方案是使用设备名称,然后在通讯簿中搜索匹配项。这假设有人会使用特定的命名约定。例如,我使用‘Nik的iPhone’作为我的设备名。我也是我的通讯录中唯一的Nik,所以在我的场景中,使用’s之前的文本作为所有者名称效果很好

它使用了Erica Sadun的非常方便的地址簿包装。 我保留了枚举代码,而不是在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];

    }
}

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

我下载了Square钱包,它是原始问题中Square卡案例参考的后续版本,不再预先填充注册表格。Path还用于执行设备名通讯簿技巧,但它也不再预先填充注册表单


使用上述方法,您仍然可以在之后预填充注册表单,但它会丢失所需的魔法体验

由于我不喜欢使用设备名,所以我选择使用与我对应的通讯簿的第一条记录

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

我也有同样的问题,但是在Swift中,我使用了Nik Burns的建议,并写了一篇关于它的博客文章:

这基本上是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())
    }

}

还是没看到。在文档中的什么地方可以获取用户的帐户信息?您仍然需要查询它,在Mac OS X上没有像.me这样的方法。我看到有人提示输入,即弹出人员选取器,允许他们选择自己而不是存储ID。或者其他人已经获取了电话号码,然后在通讯簿中查询该电话号码,等等。是的,Square应用程序不是这样做的。仍然困惑不解。我想他只是说这会让你通过编程访问用户的通讯录。至于Square确定你是谁的具体算法,我不确定。我知道你可以把自己分配给siri,让她知道你是谁,所以我不确定是否有api可以直接访问你是谁,或者Square是否正在交叉关联多个数据源以确定你通讯簿中的联系信息。嗯,我把手机扔到macbook上的一个代理后面,他们所做的只是在启动时发送给Flurry。如果我改变了我的照片,它会立刻把它捡起来。所以他们肯定是在查询ABAddressBook,但据我所知,这是被禁止的。我想在我的应用程序中这样做,但我认为这是我会被拒绝的原因。我可以确认他们似乎就是这样做的。如果您将设备名称更改为通讯簿中不存在的名称,则Card Case会显示从设备名称派生的新名称。它现在仍然有效吗?手机不会要求地址簿权限吗?请原谅我的无知,但是-所有者的电话号码总是在地址簿中吗?不总是。可能最好尝试根据设备名称确定匹配项,或者提供匹配选项供选择,或者使用回退捕获字段优雅地失败。获取所有者详细信息的好主意奇怪的是,我自己的电话号码不在联系人列表中。在较新的iOS版本中,这是一个新的变化吗?我必须手动添加还是自动添加?