Square 的新名片盒 iOS 应用程序具有“创建帐户”功能。点击它,它会显示一个表格,其中包含用户在地址簿中的条目。
这怎么可能?有人知道吗?我认为这是不可能的,以这种方式获取用户的信息。这不是 iOS 5.0 的东西,afaict。
Square 的新名片盒 iOS 应用程序具有“创建帐户”功能。点击它,它会显示一个表格,其中包含用户在地址簿中的条目。
这怎么可能?有人知道吗?我认为这是不可能的,以这种方式获取用户的信息。这不是 iOS 5.0 的东西,afaict。
我能想出的唯一解决方案是使用设备名称,然后在地址簿中搜索匹配项。这假设有人会使用特定的命名约定。例如,我使用“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];
}
}
由于需要应用程序请求访问地址簿的权限的更改,此方法不再有效。Nik Burns 的回答效果很好,但它需要访问地址簿。
我下载了 Square Wallet(它是原始问题中 Square Card Case 引用的继承者),它不再预先填充注册表单。Path 也用于执行设备名称地址簿技巧,但它也不再预先填充注册表单。
使用上述方法,您仍然可以在请求联系人访问权限后 预先填充注册表单,但它会失去所需的“神奇”体验。
由于我不满意必须使用设备名称,因此我选择使用与“ME”相对应的地址簿的第一条记录
ABAddressBookRef addressBook = ABAddressBookCreate( );
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople( addressBook );
ABRecordRef ref = CFArrayGetValueAtIndex( allPeople, 0 );
ABContact * contact = [ABContact contactWithRecord:ref];
不,你可以
我知道它在 4.X 中可用;不只是 5.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())
}
}