【问题标题】:How does Square's CardCase app automatically populate the user's details from the address book?Square 的 CardCase 应用程序如何自动从通讯录中填充用户的详细信息?
【发布时间】:2011-12-21 12:05:36
【问题描述】:

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

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

【问题讨论】:

    标签: ios abaddressbook square


    【解决方案1】:

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

    它利用了 Erica Sadun ABContactHelper 的 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];
    
        }
    }
    

    【讨论】:

    • 我可以确认他们似乎是这样做的。如果您将设备名称更改为通讯簿中不存在的名称,则 Card Case 会显示从设备名称派生的新名称。
    • 现在还能用吗?手机不会要求通讯录权限吗?
    • 请原谅我的无知,但是 - 所有者的电话号码总是在通讯录中吗?
    • 并非总是如此。可能最好尝试根据设备名称识别匹配项,并提供匹配选项以供选择,或者使用后备捕获字段优雅地失败。
    • 获取所有者详细信息的好主意
    【解决方案2】:

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

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

    使用上述方法,您仍然可以在之后 requesting Contacts access 预填充注册表单,但它会失去所需的“神奇”体验。

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        【讨论】:

        • 还是没看到。您可以在文档中的何处获取用户的帐户信息?
        • 你还是要查询,在Mac OS X上没有.me这样的方法。我看到有人提示它,即弹出人员选择器,让他们选择自己而不是存储标识。或者其他人已经得到了电话号码,然后在通讯录中查询该电话号码等。
        • 是的,Square 应用程序不是这样做的。还是一头雾水。
        • 我认为他只是说这将使您以编程方式访问用户的通讯录。至于 Square 确定谁是 you 的特定算法,我不确定。我确实知道您可以将 yourself 分配给 siri,以便她知道您是谁,所以我不确定是否有 api 可以直接访问您是谁,或者 Square 是否交叉关联多个数据源来确定您通讯录中的联系信息。
        • 好吧,我把手机放在我的 macbook 上的代理后面,他们所做的只是在启动时发布到 Flurry。如果我更改我的图片,它会立即将其拾取。所以他们肯定是在查询 ABAddressBook,但据我所知,这是被禁止的。我想在我的应用程序中执行此操作,但我认为这会被拒绝。
        【解决方案5】:

        我遇到了同样的问题,但在 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())
            }
        
        }
        

        【讨论】:

        • 奇怪的是我自己的电话号码不在联系人列表中。这是新 iOS 版本的新变化吗?我必须手动添加自己还是自动添加?
        猜你喜欢
        • 2022-01-09
        • 1970-01-01
        • 2016-06-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多