0

Мое требование: у меня есть это прямо вперед требование перечисления имен людей в алфавитном порядке в виде индексированного представления таблицы с заголовками индекса является начальной буквой алфавитов (дополнительно значок поиска вверху и #, чтобы отображать разные значения, начинающиеся с числа и других специальных символов).iPhone контакты приложение

То, что я сделал до сих пор: 1. Я использую основные данные для хранения и «last_name» моделируются как свойство Струнного в контактах объекте 2.I я с помощью NSFetchedResultsController для отображения отсортированных индексируется табличный вид.

Вопросы совершающие мои требования: 1. Во-первых, я не мог получить названия индексных раздел, чтобы быть первой буквой алфавита. Предложение Дейва в следующем посте помогло мне добиться того же: NSFetchedResultsController with sections created by first letter of a string

Единственная проблема, с которой я столкнулся с предложением Дейва, заключается в том, что я не мог получить разницу по имени, сгруппированную под индексом «#».

То, что я пробовал: 1. Я попытался добавить обычай сравнивать метод NSString (категории), чтобы проверить, как производится сравнение и раздел, но что пользовательский метод не дозвонились, когда это указано в селекторе NSSortDescriptor ,

Вот код:

@interface NSString (SortString) 

-(NSComparisonResult) customCompare: (NSString*) aStirng; 

@end 

@implementation NSString (SortString) 

-(NSComparisonResult) customCompare:(NSString *)aString 
{ 
NSLog(@"Custom compare called to compare : %@ and %@",self,aString); 
return [self caseInsensitiveCompare:aString]; 
} 

@end

код для извлечения данных:

NSArray *sortDescriptors = [NSArray arrayWithObject:[[[NSSortDescriptor alloc] initWithKey:@"last_name" 
       ascending:YES selector:@selector(customCompare:)] autorelease]]; 

    [fetchRequest setSortDescriptors:sortDescriptors]; 
     fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
      managedObjectContext:managedObjectContext sectionNameKeyPath:@"lastNameInitial" cacheName:@"MyCache"]; 

Можете ли вы дайте мне знать, что мне не хватает, и как требование может быть выполнено?

ответ

4

Это действительно неэффективный первый проход по этой проблеме, который я собираюсь переписать в конце концов. Но, надеюсь, это поможет вам.

Идея этого заключается в том, чтобы «гарантировать» получение реального индекса раздела таблицы назад при нажатии «стандартного» раздела индекса. В индексном представлении стандартного раздела должен быть значок увеличительной линзы для поиска, хеш-знак (#) для не-алфавитных разделов и буквы от A до Z для алфавитных разделов.

Этот стандартный вид представлен независимо от количества реальных разделов или от того, из чего они сделаны.

В конечном счете, этот код отображает индексы сечения сечения в существующие существующие пути имен алфавитных разделов в выбранном контроллере результатов или в существующие существующие неалфавитные (числовые) разделы или в поле поиска в заголовке таблицы.

Пользователь может лишь иногда воссоздать массив отображения индекса раздела (_idxArray) при каждом касании индекса раздела, но воссоздание массива при каждом касании явно неэффективно и может быть изменено для кэширования предварительно рассчитанных результатов.

Есть много мест, чтобы начать затягивать это: я мог бы, например, создать статическую строку sectionIndexTitleLetters, начиная с самого начала. Тем не менее, это достаточно быстро на телефоне 3GS, поэтому я не пересматривал это недавно.

В заголовке:

static NSString *sectionIndexTitleLetters = @"abcdefghijklmnopqrstuvwxyz"; 

В реализации источника данных таблицы:

- (NSArray *) sectionIndexTitlesForTableView:(UITableView *)tv { 
    if (tv != searchDisplayController.searchResultsTableView) { 
     NSMutableArray *_indexArray = [NSMutableArray arrayWithCapacity:([sectionIndexTitleLetters length]+2)]; 

     [_indexArray addObject:@"{search}"]; 
     [_indexArray addObject:@"#"]; 

     for (unsigned int _charIdx = 0; _charIdx < [sectionIndexTitleLetters length]; _charIdx++) { 
      char _indexChar[2] = { toupper([sectionIndexTitleLetters characterAtIndex:_charIdx]), '\0'}; 
      [_indexArray addObject:[NSString stringWithCString:_indexChar encoding:NSUTF8StringEncoding]]; 
     } 

     return _indexArray; 
    } 
    return nil; 
} 

- (NSInteger) tableView:(UITableView *)tv sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index { 
    if (tv != searchDisplayController.searchResultsTableView) { 
     if (index == 0) { 
      // 
      // This is the search bar "section" 
      // 
      [currentTableView scrollRectToVisible:[[currentTableView tableHeaderView] bounds] animated:YES]; 
      return -1; 
     } 
     else if (index == 1) { 
      // 
      // This is the "#" section, which covers non-alphabetic section headers (e.g. digits 0-9) 
      // 
      return 0; 
     } 
     else { 
      // 
      // This is a bit more involved because the section index array may contain indices that do not exist in the 
      // fetched results controller's sections->name info. 
      // 
      // What we are doing here is building a "fake-index" array that will return a real section index regardless of 
      // whether the section index title being touched exists or not. 
      // 
      // The fake array will be of length of the section index title array, and each index will contain an unsigned 
      // integer from 1 to {numOfRealSections}. 
      // 
      // The value this array returns will be "nearest" to the real section that is in the fetched results controller. 
      // 

      NSUInteger _alphabeticIndex = index-2; 

      unsigned int _idxArray[26]; 
      for (unsigned int _initIdx = 0; _initIdx < [sectionIndexTitleLetters length]; _initIdx++) { 
       _idxArray[_initIdx] = [[fetchedResultsController sections] count] - 1; 
      } 

      unsigned int _previousChunkIdx = 0; 
      NSNumberFormatter *_numberFormatter = [[NSNumberFormatter alloc] init]; 
      NSLocale *_enUSLocale = [[NSLocale alloc] initWithLocaleIdentifier: @"en_US"]; 
      [_numberFormatter setLocale:_enUSLocale]; 
      [_enUSLocale release]; 

      for (unsigned int _sectionIdx = 0; _sectionIdx < [[fetchedResultsController sections] count]; _sectionIdx++) { 
       NSString *_sectionTitle = [[[fetchedResultsController sections] objectAtIndex:_sectionIdx] name]; 
       if (![_numberFormatter numberFromString:_sectionTitle]) { 
        // what's the index of the _sectionTitle across sectionIndexTitleLetters? 
        for (unsigned int _titleCharIdx = 0; _titleCharIdx < [sectionIndexTitleLetters length]; _titleCharIdx++) { 
         NSString *_titleCharStr = [[sectionIndexTitleLetters substringWithRange:NSMakeRange(_titleCharIdx, 1)] uppercaseString]; 
         if ([_titleCharStr isEqualToString:_sectionTitle]) { 
          // put a chunk of _sectionIdx into _idxArray 
          unsigned int _currentChunkIdx; 
          for (_currentChunkIdx = _previousChunkIdx; _currentChunkIdx < _titleCharIdx; _currentChunkIdx++) { 
           _idxArray[_currentChunkIdx] = _sectionIdx - 1; 
          } 
          _previousChunkIdx = _currentChunkIdx; 
          break; 
         } 
        }    
       } 
      } 

      [_numberFormatter release]; 

      return (NSInteger)_idxArray[_alphabeticIndex]; 
     } 
    } 
    return 0; 
} 
+0

Hi Alex, Спасибо за вашу помощь. Вышеприведенный код действительно работает. Но выведенные контрольные секции не ожидали. Например, если было два значения фамилии, которые были прочитаны 111 и 222, в таблице было два раздела (один для 1, а другой для 2). Чтобы обойти эту проблему и сгруппировать ее под «#», я добавил # к именам, начинающимся с числа, сохраняя в основных данных. Если бы это имя начиналось с # в средстве рендеринга таблицы, нужно было бы удалить его. Я уверен, что это не простой способ сделать это. Есть ли лучший способ справиться с этим с помощью контроллера получаемых результатов? – KSH

+0

Кроме того, раздел # отображается вверху над «A» (из-за порядка сортировки, указанного для выбранного контроллера результатов). Но приложение контактов по умолчанию отображает # в нижней части, что тоже актуально. Можно ли добиться этого с помощью получаемого контроллера результатов? Или нам нужно передать всю логику управления различными массивами? Я предпочитаю выбранный контроллер результатов для управления памятью и простоты использования. – KSH

+0

Обновление: я добавил еще один числовой столбец, чтобы указать, начиналось ли последнее имя с помощью алфавита или нет, и сначала отсортировано по нему, а затем отсортировано снова в столбце с фамилией. то есть. два дескриптора сортировки, которые дали соответствующие результаты (я также нажал # в нижней части индекса). Пока работает нормально, но что, если приложение локализовано на каком-то другом языке? Как проверить, является ли данная начальная буква имени частью стандартной кодировки и доступна в индексе (при условии, что индекс локализован). – KSH

1

я мог бы быть наивным, но я не понимаю, почему эти решения так барокко. Я сделал это:

В моей модели я добавил метод:

-(NSString *)lastInitial { 
    return [self.lastname substringToIndex:1]; 
} 

И в моем tablecontroller я поставил fetchedresultscontroller использовать этот метод:

NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"lastInitial" cacheName:@"Master"]; 

похоже на работу - есть причина, что это плохая идея? Или я получаю пользу от новых возможностей в ios5 или что-то еще?

 Смежные вопросы

  • Нет связанных вопросов^_^