Jak ładować własne UITableViewCells z plików Xib?

Pytanie jest proste: jak ładować własne UITableViewCell z plików Xib? Pozwala to na użycie Kreatora interfejsów do projektowania komórek. Odpowiedź najwyraźniej nie jest prosta ze względu na problemy z zarządzaniem pamięcią. ten wątek wspomina o problemie i sugeruje rozwiązanie, ale jest przed wydaniem NDA i brakuje kodu. Oto długi wątek , który omawia problem bez udzielania ostatecznej odpowiedzi.

Oto jakiś 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, Nowa podklasa UITableViewCell i dodaj IBOutlets Dla komponentów, które chcesz. Następnie utwórz nowy plik "Empty XIB". Otwórz plik Xib w IB, Dodaj obiekt UITableViewCell, ustaw jego identyfikator na "MyCellIdentifier" , ustaw jego klasę na MyCell i dodaj komponenty. Na koniec podłącz IBOutlets do komponentów. Zauważ, że nie ustawiliśmy właściciela pliku w IB.

Inne metody zalecają ustawienie właściciela pliku i ostrzegają przed wyciekami pamięci, jeśli Xib nie zostanie załadowany przez dodatkową klasę fabryczną. I przetestowałem powyższe pod instrumentami / przeciekami i nie widziałem wycieków pamięci.

Więc jaki jest kanoniczny sposób na ładowanie ogniw z Xibs? Ustawiamy właściciela pliku? Czy potrzebujemy fabryki? Jeśli tak, to jak wygląda kod do fabryki? Jeśli istnieje wiele rozwiązań, wyjaśnijmy zalety i wady każdego z nich...

Author: Pramod More, 2009-02-12

22 answers

Oto dwie metody, które oryginalny autor twierdzi został zalecony przez inżyniera IB .

Zobacz faktyczny post, aby uzyskać więcej szczegółów. Wolę metodę # 2, ponieważ wydaje się prostsza.

Metoda #1:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BDCustomCell"];
    if (cell == nil) {
        // Create a temporary UIViewController to instantiate the custom cell.
        UIViewController *temporaryController = [[UIViewController alloc] initWithNibName:@"BDCustomCell" bundle:nil];
        // Grab a pointer to the custom cell.
        cell = (BDCustomCell *)temporaryController.view;
        [[cell retain] autorelease];
        // Release the temporary UIViewController.
        [temporaryController release];
    }

    return cell;
}

Metoda #2:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BDCustomCell"];
    if (cell == nil) {
        // Load the top-level objects from the custom cell XIB.
        NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"BDCustomCell" owner:self options:nil];
        // Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).
        cell = [topLevelObjects objectAtIndex:0];
    }

    return cell;
}

Aktualizacja (2014): Metoda # 2 jest nadal ważna, ale nie ma już dla niej dokumentacji. Kiedyś był w oficjalnych dokumentach , ale teraz został usunięty na rzecz storyboardów.

I posted a przykład pracy na Githubie:
https://github.com/bentford/NibTableCellExample

 284
Author: bentford,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-23 20:36:58

Właściwe rozwiązanie jest takie:

- (void)viewDidLoad
{
 [super viewDidLoad];
 UINib *nib = [UINib nibWithNibName:@"ItemCell" bundle:nil];
 [[self tableView] registerNib:nib forCellReuseIdentifier:@"ItemCell"];
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   // Create an instance of ItemCell
   PointsItemCell *cell =  [tableView dequeueReusableCellWithIdentifier:@"ItemCell"];

return cell;
}
 295
Author: giuseppe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-08 11:49:17

Rejestr

Po iOS 7 proces ten został uproszczony do (swift 3.0):
// For registering nib files
tableView.register(UINib(nibName: "MyCell", bundle: Bundle.main), forCellReuseIdentifier: "cell")

// For registering classes
tableView.register(MyCellClass.self, forCellReuseIdentifier: "cell")

(Uwaga ) jest to również możliwe poprzez utworzenie komórek w plikach .xib lub .stroyboard, jako komórek prototypowych. Jeśli chcesz dołączyć do nich klasę, możesz wybrać prototyp komórki i dodać odpowiednią klasę (oczywiście musi być potomkiem UITableViewCell).

Dequeue

I Później, dequeued za pomocą ( swift 3.0):

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    let cell : UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)

    cell.textLabel?.text = "Hello"

    return cell
}

Różnica polega na tym, że ta nowa metoda nie tylko dekuuje komórkę, ale również tworzy, jeśli nie istnieje (co oznacza, że nie musisz robić if (cell == nil) żartów), a komórka jest gotowa do użycia, tak jak w powyższym przykładzie.

(Ostrzeżenie) tableView.dequeueReusableCell(withIdentifier:for:) ma nowe zachowanie, jeśli wywołasz drugie (bez indexPath:), otrzymasz stare zachowanie, w którym musisz sprawdzić, czy nil i wystosować je samodzielnie, zwróć UITableViewCell? wartość.

if let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? MyCellClass
{
    // Cell be casted properly
    cell.myCustomProperty = true
}
else
{
    // Wrong type? Wrong identifier?
}

I oczywiście, Typ powiązanej klasy komórki jest ten, który zdefiniowałeś w .plik xib dla podklasy UITableViewCell, lub alternatywnie, przy użyciu innej metody rejestru.

Konfiguracja

Idealnie, twoje komórki zostały już skonfigurowane pod względem wyglądu i pozycjonowania treści (jak etykiety i widoki obrazów) w momencie ich rejestracji, a w metodzie cellForRowAtIndexPath po prostu je wypełniasz.

Wszystkie razem

class MyCell : UITableViewCell
{
    // Can be either created manually, or loaded from a nib with prototypes
    @IBOutlet weak var labelSomething : UILabel? = nil
}

class MasterViewController: UITableViewController 
{
    var data = ["Hello", "World", "Kinda", "Cliche", "Though"]

    // Register
    override func viewDidLoad()
    {
        super.viewDidLoad()

        tableView.register(MyCell.self, forCellReuseIdentifier: "mycell")
        // or the nib alternative
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    {
        return data.count
    }

    // Dequeue
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
    {
        let cell = tableView.dequeueReusableCell(withIdentifier: "mycell", for: indexPath) as! MyCell

        cell.labelSomething?.text = data[indexPath.row]

        return cell
    }
}

I oczywiście wszystko to jest dostępne w ObjC o tych samych nazwach.

 36
Author: Can,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-16 00:42:09

Wziął odpowiedź Shawna Cravera i trochę ją wyczyścił.

BBCell.h:

#import <UIKit/UIKit.h>

@interface BBCell : UITableViewCell {
}

+ (BBCell *)cellFromNibNamed:(NSString *)nibName;

@end

BBCell.m:

#import "BBCell.h"

@implementation BBCell

+ (BBCell *)cellFromNibNamed:(NSString *)nibName {
    NSArray *nibContents = [[NSBundle mainBundle] loadNibNamed:nibName owner:self options:NULL];
    NSEnumerator *nibEnumerator = [nibContents objectEnumerator];
    BBCell *customCell = nil;
    NSObject* nibItem = nil;
    while ((nibItem = [nibEnumerator nextObject]) != nil) {
        if ([nibItem isKindOfClass:[BBCell class]]) {
            customCell = (BBCell *)nibItem;
            break; // we have a winner
        }
    }
    return customCell;
}

@end

Robię wszystkie podklasy Uitableviewcell z BBCell, a następnie zamieniam standard

cell = [[[BBDetailCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"BBDetailCell"] autorelease];

Z:

cell = (BBDetailCell *)[BBDetailCell cellFromNibNamed:@"BBDetailCell"];
 32
Author: vilcsak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-22 02:15:10

Użyłem metody bentforda #2:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BDCustomCell"];
    if (cell == nil) {
        // Load the top-level objects from the custom cell XIB.
        NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"BDCustomCell" owner:self options:nil];
        // Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).
        cell = [topLevelObjects objectAtIndex:0];
    }

    return cell;
}

To działa, ale uważaj na połączenia do właściciela pliku w niestandardowym UITableViewCell .plik xib.

Przekazując owner:self w instrukcji loadNibNamed, ustawiasz {[5] } jako właściciela pliku UITableViewCell.

Jeśli przeciągniesz i upuścisz do pliku nagłówkowego w IB, aby skonfigurować akcje i wyjścia, domyślnie ustawia je jako właściciela pliku.

W kodzie loadNibNamed:owner:options Apple spróbuje ustawić właściwości na Twoim UITableViewController, ponieważ to właściciel. Ale nie masz tam zdefiniowanych tych właściwości, więc pojawia się błąd o byciu zgodnym z kodowaniem wartości klucza :

*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason:     '[<MyUITableViewController 0x6a383b0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key myLabel.'

Jeśli zdarzenie zostanie wywołane, otrzymasz wyjątek NSInvalidArgumentException:

-[MyUITableViewController switchValueDidChange:]: unrecognized selector sent to instance 0x8e9acd0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MyUITableViewController switchValueDidChange:]: unrecognized selector sent to instance 0x8e9acd0'
*** First throw call stack:
(0x1903052 0x15eed0a 0x1904ced 0x1869f00 0x1869ce2 0x1904ec9 0x5885c2 0x58855a 0x62db76 0x62e03f 0x77fa6c 0x24e86d 0x18d7966 0x18d7407 0x183a7c0 0x1839db4 0x1839ccb 0x1f8b879 0x1f8b93e 0x585a9b 0xb904d 0x2c75)
terminate called throwing an exceptionCurrent language:  auto; currently objective-c

Proste obejście problemu polega na skierowaniu połączeń Kreatora interfejsów na UITableViewCell zamiast na właściciela pliku:

  1. kliknij prawym przyciskiem myszy na właścicielu pliku, aby wyświetlić listę połączeń
  2. Take a screen capture with Command-Shift-4 (przeciągnij, aby wybrać obszar do przechwycenia)
  3. x out połączeń od właściciela pliku
  4. Kliknij prawym przyciskiem myszy na UITableCell w hierarchii obiektów i ponownie dodaj połączenia.
 15
Author: funroll,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-19 21:41:43

Postanowiłem pisać, ponieważ nie lubię żadnej z tych odpowiedzi - rzeczy zawsze mogą być prostsze i jest to zdecydowanie najbardziej zwięzły sposób, jaki znalazłem.

1. Zbuduj swój Xib w Interface Builder jak chcesz

  • Ustaw właściciela pliku na klasę NSObject
  • Dodaj UITableViewCell i ustaw jego klasę na MyTableViewCellSubclass -- jeśli twój IB ulegnie awarii (dzieje się w Xcode > 4 od tego zapisu), po prostu użyj UIView do interfejsu w Xcode 4, jeśli nadal go masz układanie wokół
  • Układ podglądów wewnątrz tej komórki i podłącz połączenia IBOutlet do interfejsu @w .h lub .m (.m to moje preferencje)

2. W podklasie UIViewController lub UITableViewController

@implementation ViewController

static NSString *cellIdentifier = @"MyCellIdentier";

- (void) viewDidLoad {

    ...
    [self.tableView registerNib:[UINib nibWithNibName:@"MyTableViewCellSubclass" bundle:nil] forCellReuseIdentifier:cellIdentifier];
}

- (UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    MyTableViewCellSubclass *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    ...

    return cell;
}

3. In your MyTableViewCellSubclass

- (id) initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder:aDecoder]) {
        ...
    }

    return self;
}
 12
Author: webstersx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-26 08:18:23

Jeśli używasz Kreatora interfejsów do tworzenia komórek, sprawdź, czy Ustawiłeś identyfikator w Inspektorze. Następnie sprawdź, czy jest tak samo podczas wywoływania dequeueReusableCellWithIdentifier.

Przez przypadek zapomniałem ustawić jakieś identyfikatory w projekcie o dużej zawartości tabeli, a zmiana wydajności była jak noc i dzień.

 8
Author: Alex R. Young,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-28 10:55:12

Wczytywanie UITableViewCells z XIBs zapisuje dużo kodu, ale zwykle skutkuje straszną prędkością przewijania (w rzeczywistości to nie XIB, ale nadmierne używanie UIViews powoduje to).

Proponuję rzucić okiem na to: Link reference

 7
Author: Can Berk Güder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-05 10:16:04

Oto metoda klasy, której używam do tworzenia niestandardowych komórek z XIBs:

+ (CustomCell*) createNewCustomCellFromNib {

    NSArray* nibContents = [[NSBundle mainBundle]
                            loadNibNamed:@"CustomCell" owner:self options:NULL];

    NSEnumerator *nibEnumerator = [nibContents objectEnumerator];
    CustomCell *customCell= nil;
    NSObject* nibItem = nil;

    while ( (nibItem = [nibEnumerator nextObject]) != nil) {

        if ( [nibItem isKindOfClass: [CustomCell class]]) {
            customCell = (CustomCell*) nibItem;

            if ([customCell.reuseIdentifier isEqualToString: @"CustomCell"]) {
                break; // we have a winner
            }
            else
                fuelEntryCell = nil;
        }
    }
    return customCell;
}

Następnie, w XIB, ustawiam nazwę klasy i ponownie używam identyfikatora. Po tym mogę po prostu wywołać tę metodę w moim kontrolerze widoku zamiast

[[UITableViewCell] alloc] initWithFrame:]
Jest wystarczająco szybki i używany w dwóch moich aplikacjach wysyłkowych. Jest bardziej niezawodny niż wywołanie [nib objectAtIndex:0], a przynajmniej moim zdaniem bardziej niezawodny niż przykład Stephana Burlota, ponieważ masz gwarancję, że tylko uchwycisz widok z XIB, który jest właściwym typem.
 5
Author: Shawn Craver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-15 14:16:45

Poprawne rozwiązanie to

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.tableView registerNib:[UINib nibWithNibName:@"CustomCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"CustomCell"];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell  *cell = [tableView dequeueReusableCellWithIdentifier:@"CustomCell"];
    return cell; 
    }
 4
Author: Hamiz Ahmed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-07 08:33:20

Przeładowanie stalówki jest drogie. Lepiej załadować go raz, a następnie utworzyć instancję obiektów, gdy potrzebujesz komórki. Zauważ, że możesz dodać UIImageViews etc do nib, nawet wiele komórek, używając tej metody ("Registernib" Apple iOS5 pozwala tylko na jeden obiekt najwyższego poziomu-Bug 10580062 "iOS5 tableView registerNib: overly restrictional"

Więc mój kod jest poniżej-czytasz w stalówce raz (w initialize jak ja lub w viewDidLoad-cokolwiek. Od tego momentu tworzysz stalówkę w obiekty, a następnie wybierz ten, którego potrzebujesz. Jest to o wiele bardziej wydajne niż wielokrotne ładowanie stalówki.

static UINib *cellNib;

+ (void)initialize
{
    if(self == [ImageManager class]) {
        cellNib = [UINib nibWithNibName:@"ImageManagerCell" bundle:nil];
        assert(cellNib);
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellID = @"TheCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
    if(cell == nil) {
        NSArray *topLevelItems = [cellNib instantiateWithOwner:nil options:nil];
        NSUInteger idx = [topLevelItems indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop)
                            {
                                UITableViewCell *cell = (UITableViewCell *)obj;
                                return [cell isKindOfClass:[UITableViewCell class]] && [cell.reuseIdentifier isEqualToString:cellID];
                            } ];
        assert(idx != NSNotFound);
        cell = [topLevelItems objectAtIndex:idx];
    }
    cell.textLabel.text = [NSString stringWithFormat:@"Howdie %d", indexPath.row];

    return cell;
}
 3
Author: David H,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-14 19:01:17

Sprawdź to - http://eppz.eu/blog/custom-uitableview-cell/ - bardzo wygodny sposób użycia małej klasy, która kończy się jedną linią w implementacji kontrolera:

-(UITableViewCell*)tableView:(UITableView*) tableView cellForRowAtIndexPath:(NSIndexPath*) indexPath
{
    return [TCItemCell cellForTableView:tableView
                          atIndexPath:indexPath
                      withModelSource:self];
}

Tutaj wpisz opis obrazka

 3
Author: Geri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-09 09:18:23

Poprawnym sposobem jest utworzenie implementacji podklasy uitableviewcell, nagłówka i XIB. W XIB usuń wszystkie widoki i po prostu dodaj komórkę tabeli. Ustaw klasę jako nazwę podklasy UITableViewCell. Dla właściciela pliku, niech będzie nazwą klasy podklasy UITableViewController. Podłącz właściciela pliku do komórki za pomocą gniazda tableViewCell.

W pliku nagłówkowym:

UITableViewCell *_tableViewCell;
@property (assign) IBOutlet UITableViewCell *tableViewCell;

W pliku implementacji:

@synthesize tableViewCell = _tableViewCell;

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *kCellIdentifier = @"reusableCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
    if (cell == nil) {
        [[NSBundle mainBundle] loadNibNamed:kCellIdentifier owner:self options:nil];
        cell = _tableViewCell;
        self.tableViewCell = nil;
    }

    return cell;
}
 2
Author: Cameron Lowell Palmer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-28 21:57:26

To, co robię, to deklarowanie IBOutlet UITableViewCell *cell w klasie kontrolerów. Następnie wywołaj metodę klasy NSBundle loadNibNamed, która dostarczy UITableViewCell do komórki zadeklarowanej powyżej.

Dla xib wytworzę pusty xib i dodam UITableViewCell obiekt w IB, gdzie można go ustawić w razie potrzeby. Widok ten jest następnie podłączony do komórki IBOutlet w klasie kontrolera.

- (UITableViewCell *)tableView:(UITableView *)table
         cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"%@ loading RTEditableCell.xib", [self description] );

    static NSString *MyIdentifier = @"editableCellIdentifier";
    cell = [table dequeueReusableCellWithIdentifier:MyIdentifier];

    if(cell == nil) {
        [[NSBundle mainBundle] loadNibNamed:@"RTEditableCell"
                                      owner:self
                                    options:nil];
    }

    return cell;
}

Nsbundle dodatki loadNibNamed (ADC login)

Cocoawithlove.com artykuł, z którego zaczerpnąłem pojęcie (Pobierz przykładowa aplikacja numerów telefonów)

 2
Author: Ryan Townshend,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-15 14:17:46

Najpierw zaimportuj swój własny plik komórki #import "CustomCell.h", a następnie zmień metodę delegata, jak wspomniano poniżej:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *simpleTableIdentifier = @"CustomCell";

CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
    cell = [nib objectAtIndex:0];

    [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}         

     return cell;
}
 2
Author: Mohit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-03 04:21:07
  1. Utwórz własną podklasę klasy AbcViewCell z UITableViewCell (Upewnij się, że nazwa pliku klasy i nazwa pliku nib są takie same)

  2. Utwórz tę metodę klasy extension.

    extension UITableViewCell {
        class func fromNib<T : UITableViewCell>() -> T {
            return Bundle.main.loadNibNamed(String(describing: T.self), owner: nil, options: nil)?[0] as! T
        }
    }
    
  3. Użyj go.

    let cell: AbcViewCell = UITableViewCell.fromNib()

 1
Author: William Hu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-07 04:07:19

Nie wiem, czy istnieje sposób kanoniczny, ale oto moja metoda:

  • Tworzenie xib dla Viewcontrollera
  • Ustaw klasę właściciela pliku na UIViewController
  • Usuń widok i dodaj UITableViewCell
  • Ustaw klasę UITableViewCell na klasę niestandardową
  • ustaw identyfikator UITableViewCell
  • Ustaw wyjście widoku kontrolera widoku na UITableViewCell

I użyj tego kodu:

MyCustomViewCell *cell = (MyCustomViewCell *)[_tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
  UIViewController* c = [[UIViewController alloc] initWithNibName:CellIdentifier bundle:nil];
  cell = (MyCustomViewCell *)c.view;
  [c release];
}

W Twoim przykład, używając

[nib objectAtIndex:0]

Może się zepsuć, jeśli Apple zmieni kolejność elementów w xib.

 0
Author: Stephan Burlot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-12 09:03:16

Oto moja metoda na to: Ładowanie własnych komórek UITableViewCells z plików XIB... Yet Another Method

Chodzi o to, aby utworzyć podklasę SampleCell UITableViewCell z właściwością IBOutlet UIView *content i właściwością dla każdego niestandardowego subview, który musisz skonfigurować z kodu. Następnie utworzyć SampleCell.plik xib. W tym pliku nib Zmień właściciela pliku na SampleCell. Dodaj zawartość UIView dostosowaną do Twoich potrzeb. Dodaj i skonfiguruj wszystkie podglądy (etykiety, widoki obrazów, przyciski itp.), które chcesz. Na koniec połącz Widok zawartości i podglądy z właścicielem pliku.

 0
Author: MonsieurDart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-24 11:51:19
 NSString *CellIdentifier = [NSString stringWithFormat:@"cell %ld %ld",(long)indexPath.row,(long)indexPath.section];


    NewsFeedCell *cell = (NewsFeedCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    cell=nil;

    if (cell == nil)
    {
        NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"NewsFeedCell" owner:nil options:nil];

        for(id currentObject in topLevelObjects)
        {
            if([currentObject isKindOfClass:[NewsFeedCell class]])
            {
                cell = (NewsFeedCell *)currentObject;
                break;
            }
        }
}
return cell;
 0
Author: 2014,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-11 06:38:13

To rozszerzenie wymaga xcode7 beta6

extension NSBundle {
    enum LoadViewError: ErrorType {
        case ExpectedXibToExistButGotNil
        case ExpectedXibToContainJustOneButGotDifferentNumberOfObjects
        case XibReturnedWrongType
    }

    func loadView<T>(name: String) throws -> T {
        let topLevelObjects: [AnyObject]! = loadNibNamed(name, owner: self, options: nil)
        if topLevelObjects == nil {
            throw LoadViewError.ExpectedXibToExistButGotNil
        }
        if topLevelObjects.count != 1 {
            throw LoadViewError.ExpectedXibToContainJustOneButGotDifferentNumberOfObjects
        }
        let firstObject: AnyObject! = topLevelObjects.first
        guard let result = firstObject as? T else {
            throw LoadViewError.XibReturnedWrongType
        }
        return result
    }
}

Utwórz plik Xib, który zawiera tylko 1 Niestandardowy UITableViewCell.

Załaduj.
let cell: BacteriaCell = try NSBundle.mainBundle().loadView("BacteriaCell")
 0
Author: neoneye,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-28 19:44:58

Oto uniwersalne podejście do rejestracji komórek w UITableView:

protocol Reusable {
    static var reuseID: String { get }
}

extension Reusable {
    static var reuseID: String {
        return String(describing: self)
    }
}

extension UITableViewCell: Reusable { }

extension UITableView {

func register<T: UITableViewCell>(cellClass: T.Type = T.self) {
    let bundle = Bundle(for: cellClass.self)
    if bundle.path(forResource: cellClass.reuseID, ofType: "nib") != nil {
        let nib = UINib(nibName: cellClass.reuseID, bundle: bundle)
        register(nib, forCellReuseIdentifier: cellClass.reuseID)
    } else {
        register(cellClass.self, forCellReuseIdentifier: cellClass.reuseID)
    }
}

Wyjaśnienie:

  1. Reusable protokół generuje ID komórki z nazwy swojej klasy. Upewnij się, że przestrzegasz konwencji: cell ID == class name == nib name.
  2. UITableViewCell jest zgodny z Reusable protokołem.
  3. UITableView rozszerzenie usuwa różnicę w rejestracji komórek za pomocą nib lub klasy.

Przykład użycia:

override func viewDidLoad() {
    super.viewDidLoad()
    let tableView = UITableView()
    let cellClasses: [UITableViewCell.Type] = [PostCell.self, ProfileCell.self, CommentCell.self]
    cellClasses.forEach(tableView.register)
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: PostCell.self.reuseID) as? PostCell
    ...
    return cell
}
 0
Author: Vadim Bulavin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-14 13:51:13
 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

            let cellReuseIdentifier = "collabCell"
            var cell:collabCell! = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as? collabCell
            if cell == nil {
                tableView.register(UINib(nibName: "collabCell", bundle: nil), forCellReuseIdentifier: cellReuseIdentifier)
                cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! collabCell!
            }


            return cell

}
 0
Author: Hitesh Chauhan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-18 11:17:25