2016-05-23 20 views
-2

私の配列はアルファベット順でソートされています。私は各セクション(A、B、Cなど)の上に適切なヘッダーを持つセクションに分割したいと思います。ソートされた配列を持つUITableViewにアルファベット順のヘッダを追加する

は、ここで私は以下試したものです:

// Here is where I refresh the data and sort it based on last name 
- (void)refreshData { 
    [[PCMSSessionManager sharedSession] refreshPCMSDataWithCompletion:^(BOOL success, NSString *errorMessage, id resultObject) { 
     if (success) { 
      NSLog(@"yay!"); 
      self.membersArray = [[PCMSSessionManager sharedSession] memberArr]; 

      // Let's sort the array 
      self.sortedArray = [self.membersArray sortedArrayUsingComparator:^NSComparisonResult(id a, id b) { 
       NSString *first = [(PCMSMember*)a lastName]; 
       NSString *second = [(PCMSMember*)b lastName]; 
       return [first compare:second]; 
      }]; 

      [self.tableView reloadData]; 

     } else { 
      NSLog(@"boooo!!!!"); 
     } 
    }]; 
} 

- (NSDictionary *)indexedMembers 
{ 
    NSMutableDictionary *indexedContacts = [NSMutableDictionary new]; 

    for (PCMSMember *member in self.sortedArray) 
    { 
     NSString *sortString = member.lastName; 

     NSString *sortLetter = [sortString substringToIndex:1]; 

     /* see if that letter already exists as an index */ 

     BOOL foundKey = NO; 

     for (NSString *key in [indexedContacts allKeys]) 
     { 
      if ([key isEqualToString:sortLetter]) 
      { 
       foundKey = YES; 
      } 
     } 

     NSMutableArray *valueArray; 
     if (foundKey) 
     { 
      valueArray = [((NSArray *)indexedContacts[sortLetter]) mutableCopy]; 
     } 
     else 
     { 
      valueArray = [NSMutableArray new]; 
     } 

     [valueArray addObject:member]; 

     indexedContacts[sortLetter] = [valueArray copy]; 
    } 

    return [indexedContacts copy]; 
} 

// Here's my table data 
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 
    return [[[self indexedMembers] allKeys] count]; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    NSDictionary *indexedContacts = [self indexedMembers]; 
    NSArray *myKeys = [indexedContacts allKeys]; 
    NSString *key = myKeys[section]; 

    return [((NSArray *)[self indexedMembers][key]) count]; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    static NSString *cellIdentifier = @"cellIdentifier"; 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; 

    // Configure the cell... 
    if (!cell) { 
     cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; 
     cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 
    } 

    if (self.isPhysician == YES) { 
     NSString *key = [[self indexedMembers] allKeys][indexPath.section]; 
     PCMSMember *currentMember = ((NSArray *)[self indexedMembers][key])[indexPath.row]; 
     cell.textLabel.text = [NSString stringWithFormat:@"%@ %@", currentMember.firstName, currentMember.lastName]; 
    } 

    return cell; 
} 

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { 
    return [[self indexedMembers] allKeys][section]; 
} 

UPDATE:

これは近い私が欲しいものを私になっています。

データがロードされていて、正しくグループ化されており、ヘッダーが表示されています。

アルファベット順ではありません。

アルファベット順にこのコードを改善するにはどうすればよいですか?

私のコンソールにはアルファベット順に表示されていますが、アプリには表示されません。

+0

「ちょうどクラッシュする」:コンソールにエラーメッセージがありますか? 'tableView:numberOfRowsInSection:'には何がありますか? – Larme

+0

今は何もありません。それはnumberOfSectionsInTableView:?と一致するはずですか? –

+0

これを追加するとコンソールに同じエラーが表示されます –

答えて

0

NSMutableDictionaryは、定義によって順序付けられていません。格納されたオブジェクトの順序に頼るのは当然の選択ではありません。代わりにNSMutableArrayを使うことをお勧めします。各セクションのテーブルビューのデータを保存するには、

このミニクラスを使用することができます
@interface MembersWithSameInitial : NSObject 

@property (strong) NSString* initial; 
@property (strong) NSMutableArray<PCMSMember*>* members; 

@end 


@implementation MembersWithSameInitial 

@end 

メンバーをソートした後、テーブルビューのすべてのデータがのtableViewリロードする前にこれを製造することができます。

NSMutableArray<MembersWithSameInitial*>* groupedMembers = [[NSMutableArray alloc] init]; 

for (PCMSMember* member in sortedArray) { 
    NSString* inicial = [member.lastName substringToIndex:1]; 
    MembersWithSameInitial* last = [groupedMembers lastObject]; 
    if (last && [last.initial isEqualToString:inicial]) { 
     [last.members addObject:member]; 
    } else { 
     MembersWithSameInitial* newGroup = [[MembersWithSameInitial alloc] init]; 
     newGroup.initial = inicial; 
     newGroup.members = [[NSMutableArray alloc] initWithObjects:member, nil]; 
     [groupedMembers addObject:newGroup]; 
    } 
} 

groupedMembersの構造がグループ化のtableViewにフィットするので、データソースの方法は簡単な実装を有することになります。あなたがプロパティにgroupedMembersを格納していると仮定します。

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 
    return self.groupedMembers.count; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    return self.groupedMembers[section].members.count; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    //... 
    PCMSMember *currentMember = self.groupedMembers[indexPath.section].members[indexPath.row]; 
    //... 

} 

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { 
    return groupedMembers[section].initial; 
} 
+0

変更すると、すべてのヘッダーが表示されますが、データは各セクションに読み込まれません。 –

+0

上記のコードが更新されました。私が試している新しいコードを見てください。 –

0

提案:

データソースを作成するメソッドを呼び出して、メインスレッドのテーブルビューをリロードrefreshData方法で二つの特性

@property NSMutableArray *keys; // for the letters in alphabetical order 
@property NSMutableDictionary *indexedContacts; // same as your implementation. 

を作成します。

実際には、プロパティmemberArraysortedArrayはもう必要ありません。ソートされた配列がメソッドに渡され、データソースが作成されます。

- (void)refreshData { 
    [[PCMSSessionManager sharedSession] refreshPCMSDataWithCompletion:^(BOOL success, NSString *errorMessage, id resultObject) { 
     if (success) { 
      NSLog(@"yay!"); 
      self.membersArray = [[PCMSSessionManager sharedSession] memberArr]; 

      // Let's sort the array 
      NSArray *sortedArray = [self.membersArray sortedArrayUsingComparator:^NSComparisonResult(id a, id b) { 
       NSString *first = [(PCMSMember*)a lastName]; 
       NSString *second = [(PCMSMember*)b lastName]; 
       return [first compare:second]; 
      }]; 

      [self indexMembers:sortedArray]; 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       [self.tableView reloadData]; 
      }); 

     } else { 
      NSLog(@"boooo!!!!"); 
     } 
    }]; 
} 

特性keysindexedContactsを初期化し、データ・ソースを作成indexMembers方法。

- (void)indexMembers:(NSArray *)sortedMembers 
{ 
    self.keys = [[NSMutableArray alloc] init]; 
    self.indexedContacts = [[NSMutableDictionary alloc] init]; 

    for (PCMSMember *member in sortedMembers) 
    { 
     NSString *sortString = member.lastName; 
     NSString *sortLetter = [sortString substringToIndex:1]; 

     /* see if that letter already exists as an index */ 

     NSArray *keyArray = self.indexedContacts[sortLetter]; 
     NSMutableArray *valueArray; 
     if (keyArray) { 
      // array for key exists, use it 
      valueArray = [keyArray mutableCopy]; 
     } else { 
      // array for key does not exist, create a new one 
      valueArray = [NSMutableArray new]; 
      // and add the letter to keys 
      [self.keys addObject:sortLetter]; 
     } 
     [valueArray addObject:member]; 
     self.indexedContacts[sortLetter] = [valueArray copy]; 
    } 
} 

numberOfSectionsInTableViewキー

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 
    return self.keys.count; 
} 

numberOfRowsInSectionの数が所与のセクションのために適切な配列を取得し、アイテムの数を返します。 cellForRowAtIndexPath

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    NSString *letter = self.keys[section]; 
    NSArray *memberArray = self.indexedContacts[letter]; 
    return memberArray.count; 
} 

常に有効なセルを取得する方法dequeueReusableCellWithIdentifier: forIndexPath:を使用します。次に、numberOfRowsInSectionのように、実際のメンバー配列を取得し、ラベルを設定します。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    static NSString *cellIdentifier = @"cellIdentifier"; 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath]; 

    // Configure the cell... 
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 
    if (self.isPhysician == YES) { 
     NSString *letter = self.keys[indexPath.section]; 
     NSArray *memberArray = self.indexedContacts[letter]; 
     PCMSMember *currentMember = memberArray[indexPath.row]; 
     cell.textLabel.text = [NSString stringWithFormat:@"%@ %@", currentMember.firstName, currentMember.lastName]; 
    } 

    return cell; 
} 

titleForHeaderInSection単にあなたがあまりにも多くのindexedMembersを呼び出している部分

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { 
    return self.keys[section]; 
} 

のための文字を返します。これは非常に高価です。

コードをテストできませんでした。おそらくselfなどがありませんが、ワークフローの印象を受けるかもしれません。

関連する問題