아이폰 UITableView. 음악 앱과 같은 단일 문자 알파벳 목록을 어떻게 켜나요?


82

iPhone 음악 앱에서 아티스트, 노래 또는 앨범을 선택하면 UI 오른쪽에 단일 문자의 정점 목록이있는 tableView가 표시되어 빠르게 스크롤 할 수 있습니다. 내 앱에서이 기능을 어떻게 활성화합니까?

건배, 더그

답변:


133

고유 한 색인 문자를 제공하십시오.

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
    return[NSArray arrayWithObjects:@"a", @"e", @"i", @"m", @"p", nil];
}

그리고:

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString
    *)title atIndex:(NSInteger)index {
        return <yourSectionIndexForTheSectionForSectionIndexTitle >;
}

섹션이 필요합니다.


21
섹션없이 인덱스를 가질 수있는 방법이 있습니까 (플랫 목록의 경우)?
유용한

12
@ThEuSeFuL 섹션 헤더를 표시하지 않고 섹션을 가질 수 있습니다. 이것은 최종 사용자에게 단순한 목록처럼 보일 것입니다.
Jon Hull 2011

10
"yourSectionIndexForTheSectionForSectionIndexTitle"은 무엇을 의미합니까?
ravoorinandan

2
@ravoorinandan he는 본질적으로 titles 배열에서 title 변수의 인덱스를 반환하는 것을 의미합니다. 따라서 제목이 @ "a"이면 0을 반환해야합니다. 제목이 @ "i"이면 2를 반환해야합니다. 여기에 표시된 두 메서드 모두에서 배열을 사용할 수 있도록 만든 다음 두 번째 메서드에서 [array indexOfObject : title]을 호출하면됩니다. (UILocalizedIndexedCollation과 관련된) 아래의 대답이 아마도 더 낫다고 말할 수 있습니다.
Brian Sachetta 2015

누군가가 저와 같은 실수를했다면 스토리 보드에서 tableView를 선택하고 텍스트 색상을 원하는 색상으로 변경하세요. 제 경우에는 텍스트 색상이 자동으로 명확한 색상으로 선택되었으므로 색인이 나열되지 않았습니다. 나는 문제가 무엇인지 알아내는 데 많은 시간을 낭비했습니다.
Vincent Joy

35

고려해야 할 다른 사항은 각 언어에 대한 섹션을 현지화하는 것입니다. 약간의 파헤쳐 본 결과, 나는 UILocalizedIndexedCollation매우 유용하다는 것을 알았 습니다.

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

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
    return [[UILocalizedIndexedCollation currentCollation] sectionIndexTitles];
}

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
    return [[UILocalizedIndexedCollation currentCollation] sectionForSectionIndexTitleAtIndex:index];
}

https://developer.apple.com/documentation/uikit/uilocalizedindexedcollation


34

섹션을 사용하지 않고 단일 문자 알파벳 목록을 처리하는 다른 방법을 생각해 냈습니다. Zaph의 대답과 비슷하지만 새 인덱스를 반환하여 값을 얻는 대신 (항상 1 개의 섹션이 있기 때문에) 배열에서 특정 문자로 시작하는 첫 번째 항목의 위치에 대한 인덱스를 계산 한 다음 스크롤합니다. 그것에.

단점은 매번 배열을 검색해야한다는 것입니다 (이것이 절대적으로 끔찍합니까?).하지만 iOS 시뮬레이터 또는 iPhone 4S에서 지연이나 느린 동작을 발견하지 못했습니다.

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
  return[NSArray arrayWithObjects:@"A", @"B", @"C", @"D", @"E", @"F", @"G", @"H", @"I", @"J", @"K", @"L", @"M", @"N", @"O", @"P", @"Q", @"R", @"S", @"T", @"U", @"V", @"W", @"X", @"Y", @"Z", nil];
}

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {

  NSInteger newRow = [self indexForFirstChar:title inArray:self.yourStringArray];
  NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:newRow inSection:0];
  [tableView scrollToRowAtIndexPath:newIndexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];

  return index;
}

// Return the index for the location of the first item in an array that begins with a certain character
- (NSInteger)indexForFirstChar:(NSString *)character inArray:(NSArray *)array
{
  NSUInteger count = 0;
  for (NSString *str in array) {
    if ([str hasPrefix:character]) {
      return count;
    }
    count++;
  }
  return 0;
}

마지막으로 선택한 색인을 저장할 속성 추가

 @property (assign, nonatomic) NSInteger previousSearchIndex;

다음과 같이 매번이 속성을 저장합니다.

- (NSInteger)indexForFirstChar:(NSString *)character inArray:(NSArray *)array
{
    NSUInteger count = 0;
    for (NSString *str in array) {
        if ([str hasPrefix:character]) {
            self.previousSearchIndex = count;
            return count;
        }
        count++;
    }
    return self.previousSearchIndex;
}

다음과 scrollToRow같은 코드 업데이트 :

 [tableView scrollToRowAtIndexPath:newIndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];

이 방법을 더 잘하고 멋진 애니메이션으로 수행하십시오.


14
알파벳 배열을 입력 할 필요가 없다는 의미이기 때문에 upvoted!
Paul Cezanne 2013 년

1
헤. 그것은 또한 나쁜 해결책이 아닙니다 ... apple은 내 코드 샘플에서 이것을 사용하여 코코아 캠프에 나를 받아 들였습니다. 그것이 그들이 공식적으로 그것을지지하는 것을 의미하든 말든 ... 나는 모른다;).
Kyle Clegg 2013 년

@PaulCezanne 실제로, 더 깔끔하게 만들기 위해 문자열 배열을 반복하고 모든 문자열의 대문자 첫 글자를 잡아서 목록이 동적으로 표시되어 항목이 없으면 Q가 없습니다. 문자 Q로 시작합니다.이 내용을 표시하도록 코드를 업데이트하려면 알려주십시오.
Kyle Clegg

감사. 실제로 작업중인 다른 앱에서 그렇게했습니다. 실제로는 꽤 이상해 보였습니다. 측면의 AZ 어레이는 매우 설명 적입니다. 노래 수가 적거나 필터링을 많이했다면 글자가 몇 개 밖에 없을 때 옆에있는 글자의 목적이 이상해 보입니다.
Paul Cezanne

1
@Mingebag 호출 될 때마다 indexForFirstChar의 반환 값을 확인하여 디버깅을 시도하십시오. 매번 0에서 25 사이 여야합니다. 25보다 크면 알파벳이 아닌 문자 또는 너무 높은 값을 반환하는 다른 것이있을 수 있습니다.
Kyle Clegg

21

많은 사람들이 섹션없이 이것을 할 수 있는지 물었습니다. 나는 똑같은 것을 원했고 조금 어둡고 sectionForSectionIndexTitle에 값을 반환하지 않는 해결책을 찾았지만 모퉁이에 있고 알파벳의 모든 문자에 대해 섹션을 만들 필요가 없다면 확실한 수정입니다. 사전에 코드 나치에게 죄송합니다. :피

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
    if (thisTableDataIsShowing)
    {
        NSMutableArray *charactersForSort = [[NSMutableArray alloc] init];
        for (NSDictionary *item in d_itemsInTable)
        {
            if (![charactersForSort containsObject:[[item valueForKey:@"character_field_to_sort_by"] substringToIndex:1]])
            {
                [charactersForSort addObject:[[item valueForKey:@"character_field_to_sort_by"] substringToIndex:1]];
            }
        }
        return charactersForSort;
    }
    return nil;
}

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
    BOOL found = NO;
    NSInteger b = 0;
    for (NSDictionary *item in d_itemsInTable)
    {
        if ([[[item valueForKey:@"character_field_to_sort_by"] substringToIndex:1] isEqualToString:title])
            if (!found)
            {
                [d_yourTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:b inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
                found = YES;
            }
        b++;
    }
}

많은 양의 데이터를 얻고 섹션화하는 경우 많은 작업이 필요하면 훌륭하게 작동합니다. :) 제네릭 변수를 사용하여 내가 무엇을하는지 알았습니다. d_itemsInTable은 UITableView에 나열하는 NSDictionaries의 NSArray입니다.


1
재미있는 팩스 : -1을 반환하면 컴파일러 경고를 무시하고 sectionForSectionIndexTitle 메서드에서 해당 섹션으로 스크롤하지 않습니다
elimirks 2013

정말 굉장한 샘플 덕분에 펀드 후에 브레이크를 추가 할 수도 있습니다 = 예; 또한 나쁜 ^^되지 않을 것
Mingebag

3

다음은 문자열이없는 인덱스를 클릭하는 경우를 처리하는 Kyle 함수의 수정 된 버전입니다.

- (NSInteger)indexForFirstChar:(NSString *)character inArray:(NSArray *)array
{
    char testChar = [character characterAtIndex:0];
    __block int retIdx = 0;
    __block int lastIdx = 0;

    [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        char firstChar = [obj characterAtIndex:0];

        if (testChar == firstChar) {
            retIdx = idx;
            *stop = YES;
        }

        //if we overshot the target, just use whatever previous one was
        if (testChar < firstChar) {
            retIdx = lastIdx;
            *stop = YES;
        }

        lastIdx = idx;
    }];
    return retIdx;
}

3

을 사용하는 경우 다음을 NSFetchedResultsController수행 할 수 있습니다.

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
    return [frc sectionIndexTitles];
}

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
    return [frc sectionForSectionIndexTitle:title atIndex:index];
}


2

다음은 배열에 제목 헤더가 있다고 가정하는 Swift의 간단한 솔루션입니다. 제목을 찾을 수 없으면 배열의 이전 인덱스를 반환합니다.

func sectionIndexTitlesForTableView(tableView: UITableView) -> [String]? {
    return "ABCDEFGHIJKLMNOPQRSTUVWXYZ".characters.flatMap{String($0)}
}

func tableView(tableView: UITableView, sectionForSectionIndexTitle title: String, atIndex index: Int) -> Int {
    return self.headerTitles.filter{$0 <= title}.count - 1
}

return self.headerTitles.count - self.headerTitles.filter{$0 > title}.count주어진 색인 제목에 대한 마지막 일치 섹션보다 첫 번째 색인을 반환 하도록 두 번째 반환 줄을 변경하는 것이 바람직하다고 생각합니다 .
Chris C

클라이언트가 실제로 기대하는 바에 따라 다릅니다. 선택하는 기능이 원하는 기능과 반대 일 가능성이 있습니다. :)
Samah

0

MonoTouch를 사용하는 경우 UITableViewDataSource 클래스에서 SectionIndexTitles (UITableView) 메서드를 재정의합니다. 문자열 배열 만 반환하면 나머지는 하위 클래스가 처리합니다.

class TableViewDataSource : UITableViewDataSource
{
  public override string[] SectionIndexTitles(UITableView tableView) 
  { 
    return new string[] { /*your string values */};
  }
}

* C # 및 Mono (.NET)를 사용하여 iPhone 앱을 작성하는 사람들을위한 힌트입니다. :)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.