2012-04-12 20 views
5

Mam NSDictionary że powiemy jest tak:Wiele różnych UITableViewCells w jednym Tableview

key:  value: 
name  Bookshelf 
movies  Array containing: (Movie 1, Movie 2, Movie 3) 
books  Array containing: (Book 1, Book 2, Book 3) 
music  Array containing: (Music 1, Music 2, Music 3) 

I tak dalej. Teraz staram się stworzyć tableView wyświetlający wszystkie te informacje, ale z różnymi typami komórek na podstawie tego, jaki jest klucz słownika. Na przykład filmy używają książek o numerach cellForMovies, które używają cellForBooks do używania muzyki cellForMusic, każdy ma własny układ.

Oczywiście upraszczam, ale mam nadzieję, że rozumiesz, co próbuję zrobić.

Jestem w stanie to zrobić, jeśli wykonuję sekcje i inny typ komórki dla każdej sekcji, ale nie chcę tego robić. Chcę, aby móc mieć tabeli tak, na przykład:

cellForBooks 
cellForMovies 
cellForMovies 
cellForMusic 
cellForBooks 

i tak dalej ... Wszelkie pomysły i zasoby można sobie powiedzieć do? Dbam tylko o wsparcie dla iOS 5 (storyboardy).

Edit roztworem:

Wielkie podziękowania dla wszystkich, którzy pomogli, zwłaszcza Atticus którzy włożyli końcowego kawałek razem.

W efekcie powstała zmiana struktury danych na tablice słowników, a następnie dodanie do każdego wpisu wartości Key: type Value: book/movie/music. Struktura danych teraz wygląda:

Array[0]: Dictionary: [Key: type Value: book], [Key: name Value: Physics]; 
Array[1]: Dictionary: [Key: type Value: music], [Key: name Value: Rock]; 

Następnie skonfigurować komórki Zrobiłem to:

NSString *CellIdentifier = @"Cell"; 
NSDictionary *object = [self.listOfStuff objectAtIndex:indexPath.row]; 
if ([[object objectForKey:@"type"] isEqualToString:@"book"]){ 
    CellIdentifier = @"BookCell"; 
}else if ([[object objectForKey:@"type"] isEqualToString:@"music"]){ 
    CellIdentifier = @"MusicCell"; 
}else if ([[object objectForKey:@"type"] isEqualToString:@"movie"]){ 
    CellIdentifier = @"MovieCell"; 
} 

każdy z nich miał inny tableviewcell w serii ujęć. Zorientowaliśmy się, jeśli chcesz korzystać z żadnej z wbudowanych funkcji komórkowych, jak cell.textLabel.text trzeba było to zrobić:

cell.textLabel.text = [object objectForKey:@"name"]; 
cell.textLabel.backgroundColor = [UIColor clearColor]; 
cell.textLabel.opaque = NO; 

Nadzieja to pomaga kogoś innego w przyszłości.

+0

Czy jest gdzieś scenopis? Nie widzę jednego w repozytorium. – atticus

+0

Został zlokalizowany z jakiegoś powodu. Jest w katalogu en.lprog. –

+1

Mam to. Wszystko w porządku, z wyjątkiem korzystania z wbudowanej właściwości textLabel w komórce niestandardowej. Po ustawieniu komórka un-ukrywa je, a kolor tła etykiety jest biały. Po wybraniu komórki tymczasowo powoduje, że tło jest jasne i można zobaczyć elementy za nim. Jeśli chcesz użyć wbudowanej textLabel, to dobrze, po prostu ustaw kolor tła, aby wyczyścić: \t 'cell.textLabel.backgroundColor = [UIColor clearColor]; cell.textLabel.opaque = NO; ' – atticus

Odpowiedz

6

Wielkie podziękowania dla wszystkich, którzy pomogli, zwłaszcza atticus, którzy złożyli ostatni kawałek.

W efekcie powstała zmiana struktury danych na tablice słowników, a następnie dodanie do każdego wpisu wartości Key: type Value: book/movie/music. Struktura danych teraz wygląda:

Array[0]: Dictionary: [Key: type Value: book], [Key: name Value: Physics]; 
Array[1]: Dictionary: [Key: type Value: music], [Key: name Value: Rock]; 

Następnie skonfigurować komórki Zrobiłem to:

NSString *CellIdentifier = @"Cell"; 
NSDictionary *object = [self.listOfStuff objectAtIndex:indexPath.row]; 
if ([[object objectForKey:@"type"] isEqualToString:@"book"]){ 
    CellIdentifier = @"BookCell"; 
}else if ([[object objectForKey:@"type"] isEqualToString:@"music"]){ 
    CellIdentifier = @"MusicCell"; 
}else if ([[object objectForKey:@"type"] isEqualToString:@"movie"]){ 
    CellIdentifier = @"MovieCell"; 
} 

każdy z nich miał inny tableviewcell w serii ujęć. Zorientowaliśmy się, jeśli chcesz korzystać z żadnej z wbudowanych funkcji komórkowych, jak cell.textLabel.text trzeba było to zrobić:

cell.textLabel.text = [object objectForKey:@"name"]; 
cell.textLabel.backgroundColor = [UIColor clearColor]; 
cell.textLabel.opaque = NO; 

Nadzieja to pomaga kogoś innego w przyszłości.

6

W swojej metodzie - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath można zwrócić wiele typów komórek zgodnie z indexPath.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    if (indexPath.row > 5) { // Your conditions here to choose between Books and Movies 
     BookCell *cell = [tableView dequeueReusableCellWithIdentifier:@"bookCell"]; 
     if (!cell) 
     { 
      cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault  reuseIdentifier:@"bookCell"]; 
     } 
     return cell; 
    } else { 
     MovieCell *cell = [tableView dequeueReusableCellWithIdentifier:@"movieCell"]; 
     if (!cell) 
     { 
      cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault  reuseIdentifier:@"movieCell"]; 
     } 
     return cell; 
    } 
return nil; 
} 
+2

W przypadku iOS 5 ze scenorysami nie trzeba już sprawdzać, czy w komórce zerowej nie ma już instancji. -dequeueReusableCellWithIdentifier: zadba o to za Ciebie. – atticus

+0

Jeśli zwrócisz zero z tableView: cellForRowAtIndexPath, twoja aplikacja ulegnie awarii. Powinieneś zwrócić coś na końcu. W twoim przypadku nigdy nie ominąć tego, czy/else, więc jest w porządku, ale coś, na co trzeba uważać. – atticus

+0

Możesz użyć niektórych opcji typowania, aby uniknąć zwracania 'nil'. Co do pierwszego komentarza, można użyć scenorysów, ale to nie znaczy, że nie można utworzyć instancji UITableView w kodzie lub podklasie UITableViewController. Więc sprawdzanie 'nil' po' dequeueReusableCellWithIdentifier' może być użyteczne, ponieważ 'dequeueReusableCellWithIdentifier' nadal może zwrócić' nil' – anticyclope

0

Uważam, że należy wdrożyć wszystkie typy komórek w jednej komórce. Co oznacza, że ​​powinieneś mieć jedną klasę UITableViewCell i .xib dla wszystkich z nich. Następnie w komórce cellForRowAtIndexPath utwórz komórkę, a następnie w zależności od aktualnego zapotrzebowania, pokaż/ukryj subviews, które tworzą książkę lub film.

W takim projekcie twoja komórka będzie nieco cięższa. Jednak nadal jest to lepsze niż używanie kilku klas komórek, ponieważ w ten sposób ponowne wykorzystanie komórek jest bardziej wydajne ([UITableView dequeueReusableCellWithIdentifier]).

Wierzę, że UITableView jest przeznaczony dla jednego typu komórki. Więc jeśli twój układ jest różny, nadal możesz umieścić je w jednym miejscu i użyć ramki lub pokaż/ukryj, aby kontrolować zachowanie komórki.

+0

Używając scenorysów, można tworzyć wiele typów komórek, dzięki czemu kod staje się bardziej czytelny. – atticus

+0

Zgadzam się z @atticus. Próbowałem tej metody i sprawia, że ​​przewijanie nieco opóźnione, ponieważ istnieje wiele recyklingu subviews. Skończyło się na odtwarzaniu moich zajęć. Posiadanie wielu klas recyklingu w cellForRowAtIndexPath sprawia, że ​​przewijanie tabeli staje się bardziej płynne i szybsze. –

3

W scenorysie ustaw tabelę, aby korzystać z dynamicznych prototypów. Następnie utwórz komórkę dla każdego rodzaju komórki, z której będziesz korzystać. Dostosuj je odpowiednio, a następnie nadaj każdemu unikalny identyfikator ponownego użycia w inspektorze (np. MovieCell).

Następnie w swojej tableview: cellForRowAtIndexPath: metoda, określ odpowiedni rodzaj komórki dla treści na tej ścieżce indeksu. Jeżeli komórka w indexPath powinny być komórką film, by utworzyć komórkę używając:

static NSString * MovieCellIdentifier = @"MovieCell"; // This must match the storyboard 
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MovieCellIdentifier]; 

które dadzą Ci komórkę określony jako „MovieCell” w serii ujęć. Jeśli chcesz go jeszcze bardziej dostosować, utwórz podklasę UITableViewCell i określ ją dla komórki w Storyboard. Następnie, można odwołać się do właściwości itp tutaj personalizacji oddając wracającą komórkę:

MovieTableViewCell *movieCell = (MovieTableViewCell *)cell; 
// customize 
+0

Jedno pytanie: na końcu funkcji cellForRowAtIndexPath, która komórka zostanie zwrócona? Ponieważ masz wiele dostosowanych Tableviewcell, np. MovieTableViewCell, BookTableViewCell ... W jaki sposób zwrócisz je na końcu? –

0

myślę, że u należy użyć następujących jako identyfikator komórki.

- (UITableViewCell *)tableView:(UITableView *)tmpTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 
NSString *cellIdentifier   = [NSString stringWithFormat:@"Cell%d%d",indexPath.section,indexPath.row]; 
UITableViewCell *cell    = [tmpTableView dequeueReusableCellWithIdentifier:cellIdentifier]; 
if (nil == cell) { 
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease]; 

// do ur stuff here 

} 
return cell; 
} 
Powiązane problemy