How to make a table view partitioned by letter as an application for contacts

I am trying to copy the contact table view in my application. Therefore, I have a list of contacts displayed in the table view, but I would like the table view to be divided into all letters of the alphabet and the names of the contacts that should be placed in the section associated with the letter-sheet with their name, Like this

enter image description here

How do I get this view? That's all I have done so far.

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [displayNames count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *simpleTableIdentifier = @"ContactsCell"; /*ContactCell *cell = (ContactCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier]; if (cell == nil) { NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"ContactCell" owner:self options:nil]; cell = [nib objectAtIndex:0]; }*/ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier]; } // cell.name.text = [displayNames // objectAtIndex:indexPath.row]; UILabel *namer = (UILabel *)[cell viewWithTag:101]; namer.text=[displayNames objectAtIndex:indexPath.row]; /* Get the picture urls from the picture array and then I loop through the array and initialize all the urls with a NSUrl and place the loaded urls in anouther nsmutable array */ urls = [[NSMutableArray alloc] init]; for (id object in pictures) { //NSDictionary *names = res[@"image"]; NSString *name = object; NSURL *url=[[NSURL alloc] initWithString:name]; [urls addObject:url]; } // cell.profile.image= [UIImage imageWithData:[NSData dataWithContentsOfURL: [urls objectAtIndex:indexPath.row]]]; UIImageView *profiler = (UIImageView *)[cell viewWithTag:100]; profiler.image= [UIImage imageWithData:[NSData dataWithContentsOfURL: [urls objectAtIndex:indexPath.row]]]; return cell; } 
+4
source share
1 answer

Here is a simple solution using the third-party TLIndexPathTools data model class TLIndexPathDataModel . It is specifically designed to work with indexes and sections, so you can accomplish what you need with minimal complexity. And here is a complete working demonstration .

First define a class to represent the contact. This gives you the ability to define firstName , lastName , displayName and sectionName :

 @interface Contact : NSObject @property (strong, nonatomic, readonly) NSString *firstName; @property (strong, nonatomic, readonly) NSString *lastName; @property (strong, nonatomic, readonly) NSString *displayName; @property (strong, nonatomic, readonly) NSString *sectionName; - (instancetype)initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName; @end 

The sectionName property simply returns the first character firstName . Then, if subclasses of the TLTableViewController table, the implementation will look something like this:

 @implementation ContactsTableViewController - (void)viewDidLoad { [super viewDidLoad]; NSMutableArray *contacts = [NSMutableArray array]; //get actual list of contacts here... [contacts addObject:[[Contact alloc] initWithFirstName:@"John" lastName:@"Doe"]]; [contacts addObject:[[Contact alloc] initWithFirstName:@"Sally" lastName:@"Smith"]]; [contacts addObject:[[Contact alloc] initWithFirstName:@"Bob" lastName:@"Marley"]]; [contacts addObject:[[Contact alloc] initWithFirstName:@"Tim" lastName:@"Cook"]]; [contacts addObject:[[Contact alloc] initWithFirstName:@"Jony" lastName:@"Ives"]]; [contacts addObject:[[Contact alloc] initWithFirstName:@"Henry" lastName:@"Ford"]]; //sort by section name [contacts sortUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"sectionName" ascending:YES]]]; //set the data model self.indexPathController.dataModel = [[TLIndexPathDataModel alloc] initWithItems:contacts sectionNameKeyPath:@"sectionName" identifierKeyPath:nil]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath]; //get contact for index path from data model and configure cell Contact *contact = [self.indexPathController.dataModel itemAtIndexPath:indexPath]; cell.textLabel.text = contact.displayName; return cell; } - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { return self.indexPathController.dataModel.sectionNames; } - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index { return index; } @end 

The main thing is that TLIndexPathDataModel automatically organizes your data into sections using the sectionNameKeyPath set to @ "sectionName". Then, in your opinion, the logic of the controller, you can easily access the contact for a given index path by calling:

 Contact *contact = [self.indexPathController.dataModel itemAtIndexPath:indexPath]; 

Update

In fact, you want to do second-level sorting on the display name:

 [contacts sortUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"sectionName" ascending:YES], [NSSortDescriptor sortDescriptorWithKey:@"displayName" ascending:YES]]]; 

update # 2

There is a new block-based initializer for TLIndexPathDataModel that makes this a lot easier if you don't want to define a custom data object just to add the sectionNameKeyPath property. For example, you can use the new initializer to organize the list of strings, as shown in the "Blocks" sample project :

 - (void)viewDidLoad { [super viewDidLoad]; NSArray *items = [@[ @"Fredricksburg", @"Jelly Bean", ... @"Metadata", @"Fundamental", @"Cellar Door"] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; //generate section names by taking the first letter of each item self.indexPathController.dataModel = [[TLIndexPathDataModel alloc] initWithItems:items sectionNameBlock:^NSString *(id item) { return [((NSString *)item) substringToIndex:1]; } identifierBlock:nil]; } 
+3
source

Source: https://habr.com/ru/post/1500183/


All Articles