如何仅获取设备上每个联系人的第一个 phone 号码?
How do I get only the first phone number from every contact on a device?
我有一个 table 视图,显示设备上所有联系人的姓名。这些名称来自名为 contactsArray
的数组。对于每个 contact
对象,我得到 phoneNumbers
对象并将数字拉入另一个名为 phoneNumberArray
的数组中。当我将它们放入我的 table 视图时,它会显示每个联系人及其相应的号码……但只显示这么长时间。当我找到几十行时,数字不再与正确的联系人匹配,因为一些 contact
对象包含一个具有多个 phone 数字的 phoneNumbers
对象。我怎样才能只获得每个对象的第一个 phone 号码,以便我有相等数量的联系人和 phone 号码?
这是我的代码:
@property (nonatomic, strong) NSMutableArray *contactsArray;
@property (nonatomic, strong) NSMutableArray *phoneNumberArray;
@end
@implementation Contacts
- (void)viewDidLoad
{
[super viewDidLoad];
self.phoneNumberArray = [[NSMutableArray alloc]init];
self.contactsArray = [[NSMutableArray alloc]init];
[self fetchContactsandAuthorization];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.contactsArray.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellId = @"contactCell";
ContactCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
CNContact *contact = self.contactsArray[indexPath.row];
NSString *phone = self.phoneNumberArray[indexPath.row];
NSString *contactName = [NSString stringWithFormat:@"%@ %@",contact.givenName,contact.familyName];
NSString *contactNumber = phone;
cell.name.text = contactName;
cell.number.text = contactNumber;
[cell.inviteBtn addTarget:self action:@selector(openMessagesForContact:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 72;
}
-(void)fetchContactsandAuthorization
{
// Request authorization to Contacts
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted == YES)
{
CNContactStore *addressBook = [[CNContactStore alloc]init];
NSArray *keysToFetch =@[CNContactFamilyNameKey,
CNContactGivenNameKey,
CNContactPhoneNumbersKey];
CNContactFetchRequest *fetchRequest = [[CNContactFetchRequest alloc]initWithKeysToFetch:keysToFetch];
[addressBook enumerateContactsWithFetchRequest:fetchRequest error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
[self.contactsArray addObject:contact];
NSString *phone;
for (CNLabeledValue *label in contact.phoneNumbers) {
phone = [label.value stringValue];
if ([phone length] > 0) {
[self.phoneNumberArray addObject:phone];
}
}
}];
dispatch_async(dispatch_get_main_queue(), ^{
[self.contactsTableView reloadData];
});
}
}];
}
@end
您的方法的问题是您正在创建一个 phone 数字的全局数组,然后将所有 phone 数字添加到此。相反,您只想添加第一个 phone 号码。
我会修改以下代码:
for (CNLabeledValue *label in contact.phoneNumbers) {
phone = [label.value stringValue];
if ([phone length] > 0) {
[self.phoneNumberArray addObject:phone];
break;
}
}
if (contact.phoneNumbers.count == 0) {
[self.phoneNumberArray addObject: @""];
}
逻辑现在已经改变:
- 我们将每个用户添加到一个数组中
- 在phone数字数组中我们只添加他们对应的第一个数字
- 现在我们的两个数组直接链接了。最后值得检查的是 phone 数字数组始终与用户数组
具有相同的计数
- 我们调用break退出
有了这个新功能 - 并在 3 中进行了介绍。我们需要添加更多检查。例如,如果用户没有任何 phone 号码怎么办 - 在这种情况下,我们需要添加一个空白 phone 号码以确保号码适合联系人。
if ([label isEqualTo: contact.phoneNumbers.lastValue]) {
[self.phoneNumberArray addObject: @""];
}
上面还有另一个潜在的检查 - 如果我们遍历所有 phone 数字并且不添加数字,那么我们无论如何都会添加一个空白数字。您需要查看您的数据并查看您可能遇到的不同场景。
备选方案:
上述解决方案是让您的代码正常工作的快速解决方案 - 虽然我个人不是这种方法的忠实拥护者 - 如果您想为每个代码使用多个数字怎么办?如果你想点击一个用户查看所有号码怎么办?在构建代码时,值得考虑如何确保以后可以更轻松地重构代码。
不会有什么不同(核心数据和对象等)我更愿意为每个联系人提供一组字典。该数组将存储他们的详细信息(姓名、phone 号码等),并且可以在每个单元格中轻松访问。
[addressBook enumerateContactsWithFetchRequest:fetchRequest error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
NSMutableArray * phoneNumbersTemp = [NSMutableArray new];
for (CNLabeledValue *label in contact.phoneNumbers) {
phone = [label.value stringValue];
if ([phone length] > 0) {
[phoneNumbersTemp addObject:phone];
}
}
NSDictionary * contactDict = @{name: contact.name,
phoneNumbers: phoneNumbersTemp}
[self.contactsArray addObject:contactDict];
}];
注意:这是sudo代码,没有测试过-是为了高亮方法
这种代码将允许您访问每个单元格中的第一个 phone 号码(只需获取每个用户的联系人 phone 字典并获取第一个条目),但也允许您为高级功能构建联系人对象。
我有一个 table 视图,显示设备上所有联系人的姓名。这些名称来自名为 contactsArray
的数组。对于每个 contact
对象,我得到 phoneNumbers
对象并将数字拉入另一个名为 phoneNumberArray
的数组中。当我将它们放入我的 table 视图时,它会显示每个联系人及其相应的号码……但只显示这么长时间。当我找到几十行时,数字不再与正确的联系人匹配,因为一些 contact
对象包含一个具有多个 phone 数字的 phoneNumbers
对象。我怎样才能只获得每个对象的第一个 phone 号码,以便我有相等数量的联系人和 phone 号码?
这是我的代码:
@property (nonatomic, strong) NSMutableArray *contactsArray;
@property (nonatomic, strong) NSMutableArray *phoneNumberArray;
@end
@implementation Contacts
- (void)viewDidLoad
{
[super viewDidLoad];
self.phoneNumberArray = [[NSMutableArray alloc]init];
self.contactsArray = [[NSMutableArray alloc]init];
[self fetchContactsandAuthorization];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.contactsArray.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellId = @"contactCell";
ContactCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
CNContact *contact = self.contactsArray[indexPath.row];
NSString *phone = self.phoneNumberArray[indexPath.row];
NSString *contactName = [NSString stringWithFormat:@"%@ %@",contact.givenName,contact.familyName];
NSString *contactNumber = phone;
cell.name.text = contactName;
cell.number.text = contactNumber;
[cell.inviteBtn addTarget:self action:@selector(openMessagesForContact:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 72;
}
-(void)fetchContactsandAuthorization
{
// Request authorization to Contacts
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted == YES)
{
CNContactStore *addressBook = [[CNContactStore alloc]init];
NSArray *keysToFetch =@[CNContactFamilyNameKey,
CNContactGivenNameKey,
CNContactPhoneNumbersKey];
CNContactFetchRequest *fetchRequest = [[CNContactFetchRequest alloc]initWithKeysToFetch:keysToFetch];
[addressBook enumerateContactsWithFetchRequest:fetchRequest error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
[self.contactsArray addObject:contact];
NSString *phone;
for (CNLabeledValue *label in contact.phoneNumbers) {
phone = [label.value stringValue];
if ([phone length] > 0) {
[self.phoneNumberArray addObject:phone];
}
}
}];
dispatch_async(dispatch_get_main_queue(), ^{
[self.contactsTableView reloadData];
});
}
}];
}
@end
您的方法的问题是您正在创建一个 phone 数字的全局数组,然后将所有 phone 数字添加到此。相反,您只想添加第一个 phone 号码。
我会修改以下代码:
for (CNLabeledValue *label in contact.phoneNumbers) {
phone = [label.value stringValue];
if ([phone length] > 0) {
[self.phoneNumberArray addObject:phone];
break;
}
}
if (contact.phoneNumbers.count == 0) {
[self.phoneNumberArray addObject: @""];
}
逻辑现在已经改变:
- 我们将每个用户添加到一个数组中
- 在phone数字数组中我们只添加他们对应的第一个数字
- 现在我们的两个数组直接链接了。最后值得检查的是 phone 数字数组始终与用户数组 具有相同的计数
- 我们调用break退出
有了这个新功能 - 并在 3 中进行了介绍。我们需要添加更多检查。例如,如果用户没有任何 phone 号码怎么办 - 在这种情况下,我们需要添加一个空白 phone 号码以确保号码适合联系人。
if ([label isEqualTo: contact.phoneNumbers.lastValue]) {
[self.phoneNumberArray addObject: @""];
}
上面还有另一个潜在的检查 - 如果我们遍历所有 phone 数字并且不添加数字,那么我们无论如何都会添加一个空白数字。您需要查看您的数据并查看您可能遇到的不同场景。
备选方案:
上述解决方案是让您的代码正常工作的快速解决方案 - 虽然我个人不是这种方法的忠实拥护者 - 如果您想为每个代码使用多个数字怎么办?如果你想点击一个用户查看所有号码怎么办?在构建代码时,值得考虑如何确保以后可以更轻松地重构代码。
不会有什么不同(核心数据和对象等)我更愿意为每个联系人提供一组字典。该数组将存储他们的详细信息(姓名、phone 号码等),并且可以在每个单元格中轻松访问。
[addressBook enumerateContactsWithFetchRequest:fetchRequest error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
NSMutableArray * phoneNumbersTemp = [NSMutableArray new];
for (CNLabeledValue *label in contact.phoneNumbers) {
phone = [label.value stringValue];
if ([phone length] > 0) {
[phoneNumbersTemp addObject:phone];
}
}
NSDictionary * contactDict = @{name: contact.name,
phoneNumbers: phoneNumbersTemp}
[self.contactsArray addObject:contactDict];
}];
注意:这是sudo代码,没有测试过-是为了高亮方法
这种代码将允许您访问每个单元格中的第一个 phone 号码(只需获取每个用户的联系人 phone 字典并获取第一个条目),但也允许您为高级功能构建联系人对象。