2017-12-13 1 views
2

장치의 모든 연락처 이름을 표시하는 테이블보기가 있습니다. 이 이름은 contactsArray이라는 배열에서옵니다. 각 contact 객체에 대해 phoneNumbers 객체를 얻고 숫자를 phoneNumberArray이라는 다른 배열로 가져옵니다. 나는 그것들을 내 테이블 뷰에 넣을 때 각각의 접촉을 해당 번호와 함께 표시합니다 ... 그러나 오랫동안 만. 몇개의 행이 내려 갔을 때, 일부 contact 개체에 복수 전화 번호가있는 phoneNumbers 개체가 있었기 때문에 더 이상 올바른 연락처와 일치하지 않습니다. 연락처와 전화 번호가 같아 지도록 각 객체의 첫 번째 전화 번호 만 가져올 수 있습니까?기기의 모든 연락처에서 첫 번째 전화 번호 만 가져 오는 방법은 무엇입니까?

@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 [email protected][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 
+0

답이 대답을 –

+0

@simon_smiley 감사로 받아 들일 수 있도록 귀하의 질문을 해결했는지 잊지 마십시오. Simon. 나는 이번 주 결승을 끝내고 있기 때문에 아직 시도하지 않았다. 내 질문에 대한 훌륭한 대답 인 것 같습니다. –

답변

2

당신의 접근 방식의 문제는 당신이 전화 번호의 글로벌 배열을 만든 다음 여기에 전화 번호를 모두 추가하는 것입니다 :

여기 내 코드입니다. 대신 첫 번째 전화 번호 만 추가하려고합니다. 우리는 우리가 그들의 상응하는 추가 전화 번호 배열에서 배열

  • 각 사용자를 추가

    1. :

      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: @""]; 
      } 
      

      이 논리는 이제 변경 :

      나는 다음과 같은 코드를 수정할 것 첫 번째 숫자

    2. 이제 두 개의 배열이 직접 연결됩니다. 휴식이 새로운 기능으로

    를 종료하려면 전화 번호 배열이 항상

  • 우리는 전화 사용자 배열과 같은 수를 가지고 마지막에 확인 가치가있다 - 그리고 우리는 추가 할 필요가 3 년에 감동 좀 더 확인해 봐. 예를 들어 사용자에게 전화 번호가없는 경우 어떻게해야합니까?이 경우 전화 번호가 연락처에 적절하게 유지되도록 빈 전화 번호를 추가해야합니다.

    if ([label isEqualTo: contact.phoneNumbers.lastValue]) { 
        [self.phoneNumberArray addObject: @""]; 
    } 
    

    또한 위의 또 다른 잠재적 인 검사입니다 - 우리는 어쨌든 빈 번호를 추가 우리는 모든 전화 번호를 통해 루프 번호를 추가하지 않는 경우. 데이터를보고 발생할 수있는 여러 가지 시나리오를 확인해야합니다.

    대체 솔루션 :

    위의 솔루션은 코드의 작업을 얻을 수있는 빠른 수정입니다 - 개인적으로 내가 그 접근 방식의 큰 팬이 아니다 불구하고 - 당신이 각각 두 개 이상의 전화 번호를 사용하려면 어떻게 ? 모든 수를보기 위해 사용자를 클릭하려면 어떻게해야합니까? 코드를 만들 때 나중에 쉽게 리팩토링 될 수있는 방법을 생각해 볼 필요가 있습니다.

    다른 (Coredata 및 개체 등)에 가지 않을 것입니다. 나는 각 연락처에 대해 사전 배열을 선호합니다. 이 배열은 세부 정보 (이름, 전화 번호 등)를 저장하며 각 셀에서 쉽게 액세스 할 수 있습니다.

    [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는 코드와 테스트되지 않았습니다 - 그것은 다음 각 셀의 첫 번째 전화 번호를 액세스 할 수 있도록 허용하는 방법을

    코드의이 종류를 강조하는 것입니다 (막 각 사용자에 대한 연락 가능한 전화 사전을 가져 와서 첫 번째 항목을 얻음) 또한 고급 기능을위한 연락처 개체를 만들 수 있습니다.

  • 관련 문제