Cómo crear un índice UITableView para grandes conjuntos de datos

I have gone down the rabbit hole of indexed, sectioned, tableviews and have been taken on a ride that has made me want to damage alot of valuable objects in my room... I am hoping with one last clear concise question that someone will be able to help me solve this on going struggle.

Im going to start from the beginning so as not to confuse anyeon that offers their help, I think its easier that way and hopefully someone can post some fairly decent examples for me to read/use, as in previous questions I think I have supplied to much detail and confused everyone where the request is actually simple.. its just the implementation is drawn out and dependant on what data you have coming in and how.

Okay here we go.

I have a UITableView which when opened queries my database for a list of car manufactures, I parse the XML that comes in and am left with a unsorted list of car manufactures, I then pass this NSArray over to a custom method that then sortes it A-Z.

- (IBAction)startSortingTheArray:(NSMutableArray *)arrayData
{
    //Sort incoming array alphabetically
    [self setSortedArray:[arrayData sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]];

From here I would like to know how to make a Indexed UITableview for Index Scrolling of a large database.. <<---- Esta es mi pregunta

Heres what I know, From this point I need to create an array of letters that represent the letters of the alphabet thats found in my data (i.e.) first letter of each value in my sorted array. I also need to create an NSDictionary with my sorted arrays split into sections withing this dictionary.

From there I need to update some of my UItableview delegate methods so that they can handle the NSDictionary and sections etc.. From there I need to pass the values in my NSDictionary over to my UItableviewcell labels...

In all previous attempts I have gotten to the point where I have everything but actually being able to display the data into the tableview cells, but because its been put together by reading several different tutorials its just not working. So I figured now that I actually kinda know what needs to happen maybe someone will be kind enough to share their code of a similar problem that I will be able to learn from and hopefully learn how to actually do this...

I would like to thank anyone that has helped me so far and anyone who is about to help me in the future :P I will be sure to post my final solution with comments to hopefully prevent this from happening to anyone else in the future! I cannot help but feel a slight amount of hatred towards apple for this pickle of an implementation.

Honda,
    Honda,
    Honda,
    Honda,
    Honda,
    Honda,
    Honda,
    Mazda,
    Mazda,
    Mitsubishi,
    Mitsubishi,
    Mitsubishi,
    Mitsubishi,
    Mitsubishi,
    Mitsubishi,
    Nissan,
    Nissan,
    Nissan,
    Nissan,
    Nissan,
    Nissan,
    Nissan,
    Toyota,
    Toyota,
    Toyota

preguntado el 20 de septiembre de 11 a las 04:09

1 Respuestas

From reading your question, it sounds like you want to have a sectioned UITableView based on a large database. How many sections are you thinking? It can handle as many as you want, but there are some features which you will not be able to use, like the index-ing may not be great if you have 100+ sections. (In fact, I think there might be a limit on this, but I'm not sure.)

The easiest thing to do in this case would be to have an array of arrays. The array would hold an array for each section. So it would be something like:

@interface myTableView: UITableViewController {
  NSMutableArray * arrayOfSection;
  NSMutableArray * sectionHeaders;
}

@implementation myTableView

// Note I will assume that arrayData contains only NSStrings.
- (void)sortSectionsWithArray:(NSMutableArray *)arrayData; {
  NSMutableArray * alphabet = [[NSMutableArray alloc] initWithObjects:@"A", @"B", ..., @"Y", @"Z", nil];
  NSString * firstLetter;
  for(NSString * string in arrayData){
    firstLetter = [string substringToIndex:1];
    for(NSString * sectionString in alphabet){
      if([firstLetter isEqualToString:sectionString]){
        [alphabet removeObject:sectionString];
        break;
      }
    }
  }
  // Note that whatever is left over are the letters of the alphabet that are NOT section headers, as we removed the section headers strings.
  // Therefore, if we remove the letters stored in the alphabet array, we have the remaining section headers!
  if(sectionHeaders){
    [sectionHeaders release];
  }
  sectionHeaders = [[NSMutableArray alloc] initWithObjects:@"A", @"B", ..., @"Y", @"Z", nil];
  for(NSString * string in sectionHeaders){
    for(NSString * sectionString in alphabet){
      if([string isEqualToString:sectionString]){
        [sectionHeaders removeObject:string];
        break;
      }
    }
  }
}

// Assume that the array below is your input array:
// NSArray * arrayData = [[NSArray alloc] initWithObjects:@"Honda", @"Honda", @"Mazda", @"Mazda", @"Mitsubishi", @"Mitsubishi", @"Nissan", @"Nissan", @"Toyota", @"Toyota", nil];
- (void)startSortingTheArray:(NSMutableArray *)arrayData; {
  if(arrayOfSection){
    [arrayOfSection release];
  }
  arrayOfSection = [[NSMutableArray alloc] initWithCapacity:[sectionHeaders count]];
  NSMutableArray * section;
  for(NSString * string in sectionHeaders){
    section = [[NSMutableArray alloc] init];
    for(NSString * dataString in arrayData){
      if([string isEqualToString:[dataString substringToIndex:1]]){
        [section addObject:dataString];
      }
    }
    [arrayOfSection addObject:section];
    [section release];
  }
}

Entonces, en tu UITableViewDelegate methods, use:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; {
  return [arrayOfSection count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; {
  return [[arrayOfSection objectAtIndex:section] count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; {
  static NSString * CellIdentifier = @"TableViewCell";
  UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  if (cell == nil) {
    [[NSBundle mainBundle] loadNibNamed:CellIdentifier owner:self options:nil];
  }
  // Set model saved in arrayOfSection by using: [[arrayOfSection objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
  return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath; {
  // What you want the view controller to do when a row is selected.
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; {
  return [sectionHeaders objectAtIndex:section];
}

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView; {
  return sectionHeaders;
}

- (void)dealloc; {
  [arrayOfSection release];
  [sectionHeaders release];
  [super dealloc];
}

¡Espero que ayude!

Respondido el 21 de Septiembre de 11 a las 07:09

I'm going to give your code a good reading over.. But just to reply to your first question.. Obviously I didnt explaine it very well again. but I am taking the first character of each word in my database and checking what it is, if its inside A-Z range, then that letter becomes a section... if their are multiple letters of the same section only one section will be made.. Basicly Im only having alphabatized sections that appear in my data. - C.Johns

If you are going to have only A-Z as your section headers, then this is even easier. I'll post a method to do that too, just hang on a sec. - msgambel

yes but not all letters will be represented, only those that are used in my dataset :P .. looking forward to your solution - C.Johns

Man I have been trying to work though this but I am pretty lost to be honest. I gave it a tick because I am sure its right but I just cannot get it to work my end... I am feeling so down about this whole bloody affair. - C.Johns

Why don't you post some of your data set, and I'll look into it some more? - msgambel

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.