Pytanie jest proste: jak ładować niestandardowe UITableViewCell
pliki Xib? Pozwala to na użycie Konstruktora interfejsów do zaprojektowania komórek. Odpowiedź najwyraźniej nie jest prosta ze względu na problemy z zarządzaniem pamięcią. Wątek wspomina o tym problemie i sugeruje rozwiązanie, ale jest wydany przed wydaniem NDA i nie zawiera kodu. Oto długi wątek, który omawia ten problem bez ostatecznej odpowiedzi.
Oto kod, którego użyłem:
static NSString *CellIdentifier = @"MyCellIdentifier";
MyCell *cell = (MyCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellIdentifier owner:self options:nil];
cell = (MyCell *)[nib objectAtIndex:0];
}
Aby użyć tego kodu, utwórz MyCell.m / .h, nową podklasę UITableViewCell
i dodaj IBOutlets
odpowiednie komponenty. Następnie utwórz nowy plik „Pusty XIB”. Otwórz plik Xib w IB, dodaj UITableViewCell
obiekt, ustaw jego identyfikator na „MyCellIdentifier”, ustaw klasę na MyCell i dodaj swoje komponenty. Na koniec podłącz IBOutlets
do komponentów. Pamiętaj, że nie ustawiliśmy właściciela pliku w IB.
Inne metody zalecają ustawienie właściciela pliku i ostrzeżenie przed wyciekiem pamięci, jeśli Xib nie zostanie załadowany przez dodatkową klasę fabryczną. Testowałem powyższe pod Instruments / Leaks i nie zauważyłem wycieków pamięci.
Więc jaki jest kanoniczny sposób ładowania komórek z Xib? Czy ustawiamy właściciela pliku? Czy potrzebujemy fabryki? Jeśli tak, to jak wygląda kod dla fabryki? Jeśli istnieje wiele rozwiązań, wyjaśnijmy zalety i wady każdego z nich ...
źródło
Odpowiedzi:
Oto dwie metody, które według oryginalnego autora były zalecane przez inżyniera IB .
Zobacz rzeczywisty post, aby uzyskać więcej informacji. Wolę metodę nr 2, ponieważ wydaje się to prostsze.
Metoda nr 1:
Metoda nr 2:
Aktualizacja (2014): Metoda nr 2 jest nadal aktualna, ale nie ma już jej dokumentacji. Kiedyś był w oficjalnych dokumentach, ale teraz został usunięty na rzecz scenariuszy.
Opublikowałem działający przykład na Github:
https://github.com/bentford/NibTableCellExample
edycja dla Swift 4.2
źródło
Właściwe rozwiązanie to:
źródło
Zarejestrować
Po iOS 7 proces ten został uproszczony do ( Swift 3.0 ):
Dequeue
A później odkażone przy użyciu ( swift 3.0 ):
Różnica polega na tym, że ta nowa metoda nie tylko usuwa z komórki kolejkę, ale tworzy ją również, jeśli nie istnieje (co oznacza, że nie musisz wykonywać
if (cell == nil)
shenaniganów), a komórka jest gotowa do użycia, tak jak w powyższym przykładzie.I oczywiście typ powiązanej klasy komórki to ta, którą zdefiniowałeś w pliku .xib dla
UITableViewCell
podklasy lub alternatywnie przy użyciu innej metody register.Konfiguracja
Idealnie byłoby, gdyby Twoje komórki były już skonfigurowane pod względem wyglądu i pozycjonowania treści (takich jak etykiety i widoki obrazów) do czasu ich zarejestrowania, i
cellForRowAtIndexPath
metodą, którą po prostu wypełniasz.Wszyscy razem
Oczywiście wszystko to jest dostępne w ObjC o tych samych nazwach.
źródło
[self.tableView registerNib:[UINib nibWithNibName:@"BlaBlaTableViewCell" bundle:nil] forCellReuseIdentifier:kCellIdentifier];
Wziął odpowiedź Shawna Cravera i trochę ją oczyścił.
BBCell.h:
BBCell.m:
Tworzę wszystkie podklasy BBCell mojej UITableViewCell, a następnie zastępuję standard
z:
źródło
Użyłem metody bentforda # 2 :
Działa, ale uważaj na połączenia z właścicielem pliku w niestandardowym pliku .xib UITableViewCell.
Przekazując
owner:self
swojeloadNibNamed
oświadczenie, ustawiaszUITableViewController
właściciela pliku jako swojegoUITableViewCell
.Przeciągnięcie i upuszczenie pliku nagłówka w IB w celu skonfigurowania akcji i ujść spowoduje, że domyślnie skonfiguruje je jako Właściciel pliku.
W
loadNibNamed:owner:options
kod Apple spróbuje ustawić właściwości na twoimUITableViewController
, ponieważ to jest właściciel. Ale nie masz tam zdefiniowanych właściwości, więc pojawia się błąd dotyczący zgodności kodowania wartości klucza :Jeśli zamiast tego zostanie wywołane zdarzenie, otrzymasz wyjątek NSInvalidArgumentException:
Łatwym obejściem jest skierowanie połączeń Konstruktora interfejsów
UITableViewCell
na właściciela pliku:źródło
Zdecydowałem się opublikować, ponieważ nie podoba mi się żadna z tych odpowiedzi - wszystko może być zawsze prostsze i jest to najbardziej zwięzły sposób, jaki znalazłem.
1. Zbuduj swój Xib w Konstruktorze interfejsów, jak chcesz
2. W podklasie UIViewController lub UITableViewController
3. W twojej MyTableViewCellSubclass
źródło
Jeśli używasz Konstruktora interfejsów do tworzenia komórek, sprawdź, czy ustawiłeś Identyfikator w Inspektorze. Następnie sprawdź, czy to samo podczas wywoływania dequeueReusableCellWithIdentifier.
Przypadkowo zapomniałem ustawić niektóre identyfikatory w dużym projekcie, a zmiana wydajności była jak noc i dzień.
źródło
Ładowanie UITableViewCells z XIBs oszczędza dużo kodu, ale zwykle skutkuje okropną prędkością przewijania (tak naprawdę to nie XIB, ale nadmierne użycie UIViews powoduje to).
Proponuję spojrzeć na to: Odnośnik do linku
źródło
Oto metoda klasy, której używałem do tworzenia niestandardowych komórek z XIB:
Następnie w XIB ustawiam nazwę klasy i ponownie używam identyfikatora. Następnie mogę po prostu wywołać tę metodę w moim kontrolerze widoku zamiast
Jest wystarczająco szybki i jest używany w dwóch moich aplikacjach wysyłkowych. Jest bardziej niezawodny niż dzwonienie
[nib objectAtIndex:0]
, a przynajmniej moim zdaniem bardziej niezawodny niż przykład Stephana Burlota, ponieważ masz gwarancję, że złapiesz tylko widok z XIB, który jest odpowiedniego typu.źródło
Prawidłowe rozwiązanie jest to
źródło
Ponowne załadowanie NIB jest kosztowne. Lepiej go załaduj raz, a następnie utwórz instancję obiektów, gdy potrzebujesz komórki. Pamiętaj, że możesz dodać UIImageViews itp. Do stalówki, nawet wielu komórek, używając tej metody (Apple „registerNIB” iOS5 pozwala tylko na jeden obiekt najwyższego poziomu - Bug 10580062 „Tabela iOS5 registerNib: nadmiernie restrykcyjny”
Więc mój kod jest poniżej - czytasz raz w NIB (inicjuj tak jak ja lub w viewDidload - cokolwiek. Od tego momentu tworzysz stalówkę w obiektach, a następnie wybierasz ten, którego potrzebujesz. Jest to o wiele bardziej wydajne niż ładowanie stalówki raz po raz.
źródło
Sprawdź to - http://eppz.eu/blog/custom-uitableview-cell/ - naprawdę wygodny sposób za pomocą małej klasy, która kończy się jedną linią w implementacji kontrolera:
źródło
Prawidłowym sposobem na to jest utworzenie implementacji podklasy UITableViewCell, nagłówka i XIB. W XIB usuń wszelkie widoki i po prostu dodaj komórkę tabeli. Ustaw klasę jako nazwę podklasy UITableViewCell. Dla właściciela pliku nadaj mu nazwę klasy podklasy UITableViewController. Podłącz właściciela pliku do komórki za pomocą gniazdka tableViewCell.
W pliku nagłówkowym:
W pliku implementacyjnym:
źródło
To, co robię, to zadeklarowanie
IBOutlet UITableViewCell *cell
w klasie kontrolera. Następnie wywołajNSBundle loadNibNamed
metodę klasy, która nakarmiUITableViewCell
komórkę zadeklarowaną powyżej.Dla xib utworzę pusty xib i dodam
UITableViewCell
obiekt w IB, gdzie można go skonfigurować w razie potrzeby. Ten widok jest następnie połączony z komórkąIBOutlet
w klasie kontrolera.Dodatki NSBundle loadNibNamed (logowanie ADC)
Artykuł cocoawithlove.com, z którego zacząłem czerpać pojęcie
źródło
Utwórz własną niestandardową
AbcViewCell
podklasę klasy zUITableViewCell
(Upewnij się, że nazwa pliku klasy i nazwa pliku stalówki są takie same)Utwórz tę metodę klasy rozszerzeń.
Użyj tego.
let cell: AbcViewCell = UITableViewCell.fromNib()
źródło
Najpierw zaimportuj niestandardowy plik komórki,
#import "CustomCell.h"
a następnie zmień metodę delegowania, jak wspomniano poniżej:źródło
W Swift 4.2 i Xcode 10
Mam trzy pliki komórek XIB
w ViewDidLoad zarejestruj swoje pliki XIB w ten sposób ...
To jest pierwsze podejście
Drugie podejście bezpośrednio rejestruje pliki XIB w cellForRowAt indexPath:
To są moje funkcje delegowania widoku tabeli
źródło
Oto moja metoda: ładowanie niestandardowych komórek UITableViewCell z plików XIB… Jeszcze inna metoda
Chodzi o to, aby utworzyć podklasę SampleCell
UITableViewCell
zIBOutlet UIView *content
właściwością i właściwością dla każdego niestandardowego podview, który należy skonfigurować z kodu. Następnie, aby utworzyć plik SampleCell.xib. W tym pliku stalówki zmień właściciela pliku na SampleCell. Dodaj treśćUIView
dostosowaną do twoich potrzeb. Dodaj i skonfiguruj wszystkie widoki podrzędne (etykiety, widoki obrazów, przyciski itp.), Które chcesz. Na koniec połącz widok zawartości i widoki podrzędne z właścicielem pliku.źródło
Oto uniwersalne podejście do rejestrowania komórek w
UITableView
:Wyjaśnienie:
Reusable
protokół generuje identyfikator komórki na podstawie nazwy klasy. Upewnij się, że zgodnie z konwencją:cell ID == class name == nib name
.UITableViewCell
jest zgodny zReusable
protokołem.UITableView
rozszerzenie abstrahuje różnicę w rejestrowaniu komórek za pomocą stalówki lub klasy.Przykład użycia:
źródło
Nie wiem, czy istnieje sposób kanoniczny, ale oto moja metoda:
I użyj tego kodu:
W twoim przykładzie za pomocą
może się zepsuć, jeśli Apple zmieni kolejność elementów w Xib.
źródło
źródło
To rozszerzenie wymaga Xcode7 beta6
Utwórz plik Xib, który zawiera tylko 1 niestandardową UITableViewCell.
Załaduj To.
źródło
źródło