Wie Sie benutzerdefinierte UITableViewCells aus Xib Dateien laden?

stimmen
278

Die Frage ist einfach: Wie Sie benutzerdefiniertes laden UITableViewCellvon Xib Dateien? Dadurch können Sie Interface Builder verwenden , um Ihre Zellen zu entwerfen. Die Antwort ist offensichtlich nicht einfach aufgrund Speicherverwaltung Fragen. Dieser Thread erwähnt das Problem und schlägt eine Lösung vor , sondern ist vor NDA-Release und es fehlt Code. Hier ist ein langer Faden , der das Problem diskutiert , ohne eine definitive Antwort zu geben.

Hier einige Code, den ich verwendet habe:

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];
}

Um diesen Code zu verwenden, erstellen MyCell.m / .h, eine neue Unterklasse von UITableViewCellund fügen Sie IBOutletsfür die Komponenten , die Sie wollen. Dann erstellen Sie eine neue „Empty XIB“ -Datei. Öffnen Sie die Datei in Xib IB, fügen Sie ein UITableViewCellObjekt, legen Sie die Kennung „MyCellIdentifier“, und legen Sie seine Klasse MyCell und fügen Sie Ihre Komponenten. Schließlich verbindet die IBOutletszu den Komponenten. Beachten Sie, dass wir die Datei Besitzer in IB nicht festgelegt haben.

Andere Methoden befürworten die Datei Besitzer Einstellung und warnen vor Speicherlecks, wenn der Xib nicht über eine zusätzliche Fabrik Klasse geladen wird. Getestet habe ich die oben unter Instrumenten / Leaks und sah keine Speicherlecks.

Also, was ist der üblicher Weg, Zellen aus Xibs zu laden? Setzen wir Datei-Besitzer? Haben wir eine Fabrik benötigen? Wenn ja, was ist der Code für die wie Fabrik aussehen? Wenn es mehrere Lösungen gibt, lassen Sie uns die Vor- und Nachteile eines jeden von ihnen klären ...

Veröffentlicht am 12/02/2009 um 08:27
quelle vom benutzer
In anderen Sprachen...                            


23 antworten

stimmen
292

Die richtige Lösung ist folgende:

- (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;
}
Beantwortet am 29/11/2012 um 16:57
quelle vom benutzer

stimmen
282

Hier sind zwei Methoden , die die ursprüngliche Autor Staaten von einem IB - Ingenieure empfohlen wurden .

Sehen Sie sich die tatsächliche Post für weitere Details. Ich ziehe Methode # 2, da es einfacher zu sein scheint.

Methode 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;
}

Methode 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;
}

Update (2014): Methode 2 ist immer noch gültig , aber es gibt keine Dokumentation für sie mehr. Früher ist es in den seine offiziellen Dokumenten aber jetzt für Storyboards entfernt wird.

Ich stellte ein funktionsfähiges Beispiel auf Github:
https://github.com/bentford/NibTableCellExample

Beantwortet am 21/12/2009 um 11:19
quelle vom benutzer

stimmen
33

Registrieren

Nach iOS 7 hat sich dieses Verfahren auf (vereinfacht unten worden 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")

( Hinweis ) Diese auch erreichbar ist , indem die Zellen in den Erstellen .xiboder .stroyboardDateien, als Prototyp Zellen. Wenn Sie eine Klasse , um sie befestigen müssen, können Sie die Zelle Prototyp auswählen und die entsprechende Klasse hinzufügen (muss ein Nachkomme sein UITableViewCell, natürlich).

dequeue

Und später, aus der Warteschlange entfernt mit ( 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
}

Der Unterschied besteht darin , dass diese neue Methode nicht nur die Zelle aus der Warteschlange entfernt, schafft es auch , wenn nicht existierend (das bedeutet , dass Sie nicht zu tun haben if (cell == nil)Spielereien) und die Zelle ist oben wie im Beispiel verwenden.

( Warnung ) tableView.dequeueReusableCell(withIdentifier:for:)hat das neue Verhalten, wenn Sie die andere nennen (ohne indexPath:) Sie das alte Verhalten bekommen, in dem Sie benötigen , zu prüfen nilund die Instanz es sich, beachten Sie den UITableViewCell?Rückgabewert.

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

Und natürlich ist die Art der zugehörigen Klasse der Zelle diejenige , die Sie für die in der Datei definierten .xib UITableViewCellUnterklasse oder alternativ die anderen Registerverfahren.

Aufbau

Im Idealfall sind in Bezug auf Aussehen und Inhalt Positionierung konfiguriert, Ihre Zellen bereits (wie Etiketten und Bildansichten) von der Zeit , die Sie registriert und auf der cellForRowAtIndexPathMethode füllen Sie sie einfach in.

Alle zusammen

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
    }
}

Und natürlich ist das alles in ObjC mit dem gleichen Namen.

Beantwortet am 21/05/2015 um 01:47
quelle vom benutzer

stimmen
32

Nahm Shawn Craver Antwort und reinigte ihn ein wenig.

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

Ich mache alle meine UITableViewCell die Subklassen von BBCell und dann den Standard ersetzen

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

mit:

cell = (BBDetailCell *)[BBDetailCell cellFromNibNamed:@"BBDetailCell"];
Beantwortet am 22/06/2010 um 03:15
quelle vom benutzer

stimmen
15

Ich benutzte bentford der Methode # 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;
}

Es funktioniert, aber achten Sie auf Verbindungen zu Datei - Besitzer in Ihrer benutzerdefinierten UITableViewCell .xib Datei.

Durch die Übergabe owner:selfin Ihrer loadNibNamedAussage, stellen Sie den UITableViewControllerals Datei - Besitzer Ihres UITableViewCell.

Wenn Sie in die Header-Datei in IB ziehen einzurichten Aktionen und Auslässen, wird es sie als Datei Besitzer standardmäßig eingerichtet.

In dem loadNibNamed:owner:optionsCode Apple wird versuchen , Eigenschaften auf Ihrem einzustellen UITableViewController, da , dass der Eigentümer ist. Aber Sie haben nicht diese Eigenschaften dort definiert, so erhalten Sie einen Fehler über seinen Schlüsselwert Codierung-konform :

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

Wenn ein Ereignis statt ausgelöst wird, erhalten Sie eine NSInvalidArgumentException erhalten:

-[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

Eine einfache Abhilfe ist Ihr Interface Builder Verbindungen an den Punkt UITableViewCellstatt Datei - Besitzer:

  1. Rechtsklick auf Datei-Besitzer die Liste der Verbindungen zu ziehen
  2. Nehmen Sie einen Screenshot mit Befehl-Umschalt-4 (drag den Bereich auszuwählen, werden erfasst)
  3. x aus den Verbindungen von Datei-Besitzer
  4. Rechtsklick auf der UITableCell in der Objekthierarchie und erneut hinzufügen, die Verbindungen.
Beantwortet am 19/03/2012 um 22:41
quelle vom benutzer

stimmen
12

Ich habe beschlossen, posten, da ich eine dieser Antworten nicht mögen - Dinge können immer einfacher sein, und dies ist bei weitem der knappste Art, wie ich gefunden habe.

1. Erstellen Sie Ihre Xib im Interface Builder, wie es Ihnen gefällt

  • Set File Besitzer Klasse NSObject
  • Fügen Sie eine UITableViewCell und legen Sie seine Klasse MyTableViewCellSubclass - wenn Ihr IB Abstürze (geschieht in Xcode> 4 als dies geschrieben wurde), benutzen Sie einfach eine UIView von tun, um die Schnittstelle in Xcode 4, falls Sie es noch herumliegen
  • Layout Ihre Subviews innerhalb dieser Zelle und legen Sie Ihre IBOutlet Verbindungen zu Ihrem @interface in der .h oder .m (.m ist meine Präferenz)

2. In Ihrem UIViewController oder UITableViewController Unterklasse

@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. Geben Sie in Ihrem MyTableViewCellSubclass

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

    return self;
}
Beantwortet am 26/08/2013 um 09:18
quelle vom benutzer

stimmen
8

Wenn Sie Interface Builder verwenden Zellen zu machen, überprüfen Sie, dass Sie den Identifier im Inspektor festgelegt haben. Dann prüfen Sie, ob es das gleiche, wenn dequeueReusableCellWithIdentifier Aufruf.

Ich habe vergessen, versehentlich einige Kennungen in einer Tabelle schwerer Projekt festgelegt und die Leistungsänderung war wie Tag und Nacht.

Beantwortet am 28/04/2010 um 11:55
quelle vom benutzer

stimmen
7

Laden UITableViewCells von XIBs spart eine Menge Code, sondern führt in der Regel schrecklich Scroll-Geschwindigkeit (eigentlich ist es nicht der XIB aber die übermäßige Verwendung von UIViews, die dies verursachen).

Ich schlage vor , Sie nehmen einen Blick auf diese: Link - Verweis

Beantwortet am 12/02/2009 um 15:19
quelle vom benutzer

stimmen
5

Hier ist die Klassenmethode, die ich habe für das Erstellen von benutzerdefinierten Zellen aus XIBs mit:

+ (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;
}

Dann wird in der XIB, habe ich die Klassennamen und Wiederverwendung Bezeichner. Danach kann ich diese Methode in meiner Ansicht-Controller rufen Sie einfach anstelle der

[[UITableViewCell] alloc] initWithFrame:]

Es ist viel schnell genug, und in zwei meiner Versandanwendungen verwendet wird. Es ist zuverlässiger als Aufruf [nib objectAtIndex:0], und in meinem Kopf zumindest zuverlässiger als Stephan Burlot des Beispiel , weil Sie garantiert sind , um nur einen Blick aus einem XIB zu ergreifen , die die richtige Art ist.

Beantwortet am 12/02/2009 um 14:47
quelle vom benutzer

stimmen
4

Die richtige Lösung ist dies

- (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; 
    }
Beantwortet am 07/09/2016 um 08:33
quelle vom benutzer

stimmen
3

Sehen Sie sich diese - http://eppz.eu/blog/custom-uitableview-cell/ - wirklich bequeme Möglichkeit , eine kleine Klasse verwenden , die eine Zeile in Controller - Implementierung endet:

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

Geben Sie hier image description

Beantwortet am 09/07/2013 um 10:18
quelle vom benutzer

stimmen
3

die NIB Nachladen ist teuer. Besser einmal zu laden, dann die Objekte instanziiert, wenn Sie eine Zelle benötigen. Beachten Sie, dass Sie UIImageViews usw. an die Spitze, auch mehrere Zellen hinzufügen können, mit dieser Methode (Apples „registerNIB“ iOS5 erlaubt nur eine Top-Level-Objekt - Bug 10580062 „iOS5 Tableview registerNib: zu restriktiv“

Also mein Code unten ist - Sie in der NIB einmal gelesen (in initialize wie ich es tat oder in viewDidLoad -.., Was von da an instanziert die Spitze in Objekte dann derjenige holen Sie brauchen Dies ist viel effizienter als die Spitze Laden über und über.

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;
}
Beantwortet am 14/12/2011 um 20:01
quelle vom benutzer

stimmen
2

Zuerst Ihre benutzerdefinierte Zelle Datei importieren #import "CustomCell.h"und dann die Methode Delegaten ändern , wie unten erwähnt:

- (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;
}
Beantwortet am 26/02/2014 um 07:48
quelle vom benutzer

stimmen
2

Der richtige Weg, es zu tun ist, einen UITableViewCell Unterklasse Implementierung, Kopf- und XIB zu erstellen. In der XIB alle Ansichten entfernen und nur eine Tabellenzelle hinzufügen. Stellen Sie die Klasse, wie der Name der UITableViewCell-Unterklasse. Für Dateieigentümer, machen die Unterklasse Klassenname UITableViewController es. Schließen Sie den Dateieigentümer an die Zelle die tableViewCell Steckdose.

In der Header-Datei:

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

In der Implementierungsdatei:

@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;
}
Beantwortet am 28/06/2012 um 22:57
quelle vom benutzer

stimmen
2

Was ich dafür tun , ist ein erklären IBOutlet UITableViewCell *cellin Ihrem Controller - Klasse. Dann rufen Sie die NSBundle loadNibNamedKlassenmethode, die das Futter wird UITableViewCellin die Zelle oben erklärt.

Für die xib werde ich eine leere xib und fügen Sie das schaffen UITableViewCellObjekt in IB , wo es Setup nach Bedarf sein kann. Diese Ansicht wird dann mit der Zelle verbunden IBOutletin der Controller - Klasse.

- (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 Ergänzungen loadNibNamed (ADC Login)

cocoawithlove.com Artikel sourced ich das Konzept von (Holen Sie sich die Telefonnummern Probe app)

Beantwortet am 12/02/2009 um 19:01
quelle vom benutzer

stimmen
1

In Swift 4.2 und Xcode 10

Ich habe drei XIB Zelle Dateien

in ViewDidLoad registrieren Ihre XIB Dateien wie diese ...

Dies ist die erste Ansatz

tableView.register(UINib.init(nibName: "XIBCell", bundle: nil), forCellReuseIdentifier: "cell1")
tableView.register(UINib.init(nibName: "XIBCell2", bundle: nil), forCellReuseIdentifier: "cell2")
//tableView.register(UINib.init(nibName: "XIBCell3", bundle: nil), forCellReuseIdentifier: "cell3")

Zweiter Ansatz direkt XIB Dateien im Register cellForRowAt indexPath:

Das ist meine Tableview delegieren Funktionen

//MARK: - Tableview delegates
override func numberOfSections(in tableView: UITableView) -> Int {

    return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return 6
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    //This is first approach
    if indexPath.row == 0 {//Load first XIB cell
        let placeCell = tableView.dequeueReusableCell(withIdentifier: "cell1") as! XIBCell
        return placeCell
    //Second approach
    } else if indexPath.row == 5 {//Load XIB cell3
        var cell = tableView.dequeueReusableCell(withIdentifier:"cell3") as? XIBCell3
        if cell == nil{
            let arrNib:Array = Bundle.main.loadNibNamed("XIBCell3",owner: self, options: nil)!
            cell = arrNib.first as? XIBCell3
        }

        //ADD action to XIB cell button
        cell?.btn.tag = indexPath.row//Add tag to button
        cell?.btn.addTarget(self, action: #selector(self.bookbtn1(_:)), for: .touchUpInside);//selector

        return cell!
    //This is first approach
    } else {//Load XIB cell2
        let placeCell = tableView.dequeueReusableCell(withIdentifier: "cell2") as! XIBCell2

        return placeCell
    }

}
Beantwortet am 12/10/2018 um 07:02
quelle vom benutzer

stimmen
1
  1. Erstellen Sie Ihre eigene benutzerdefinierte Klasse AbcViewCellUnterklasse von UITableViewCell(Stellen Sie sicher , Ihre Klassendateinamen und nib Dateinamen identisch sind)

  2. Erstellen Sie diese Erweiterung Klassenmethode.

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

    let cell: AbcViewCell = UITableViewCell.fromNib()

Beantwortet am 07/09/2017 um 04:07
quelle vom benutzer

stimmen
1

Ich weiß nicht, ob es ein üblicher Weg ist, aber hier ist meine Methode:

  • Erstellen Sie eine xib für einen Viewcontroller
  • Stellen Sie die Datei-Besitzer Klasse UIViewController
  • Löschen Sie die Ansicht und fügen Sie ein UITableViewCell
  • Stellen Sie die Klasse Ihres UITableViewCell zu Ihrer benutzerdefinierten Klasse
  • Stellen Sie die Kennung Ihres UITableViewCell
  • Stellen Sie den Ausgang Ihrer View-Controller im Hinblick auf Ihre UITableViewCell

Und verwenden Sie diesen Code:

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

In Ihrem Beispiel mit

[nib objectAtIndex:0]

kann brechen, wenn Apple die Reihenfolge der Elemente in der xib ändert.

Beantwortet am 12/02/2009 um 10:03
quelle vom benutzer

stimmen
0
 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

}
Beantwortet am 18/05/2018 um 11:17
quelle vom benutzer

stimmen
0

Hier ist ein universeller Ansatz für die Registrierung von Zellen in 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)
    }
}

Erläuterung:

  1. ReusableProtokoll erzeugt Zellen - ID von seinem Klassennamen. Stellen Sie sicher , dass Sie die Konvention folgen: cell ID == class name == nib name.
  2. UITableViewCellentspricht ReusableProtokoll.
  3. UITableView Erweiterung abstrahiert die Differenz bei der Registrierung von Zellen über nib oder Klasse entfernt.

Anwendungsbeispiel:

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
}
Beantwortet am 18/08/2017 um 08:08
quelle vom benutzer

stimmen
0

Diese Erweiterung erfordert 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
    }
}

Erstellen Sie eine Xib-Datei, die nur 1 benutzerdefinierte UITableViewCell enthält.

Lade es.

let cell: BacteriaCell = try NSBundle.mainBundle().loadView("BacteriaCell")
Beantwortet am 28/08/2015 um 19:44
quelle vom benutzer

stimmen
0
 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;
Beantwortet am 11/06/2014 um 07:38
quelle vom benutzer

stimmen
0

Hier ist meine Methode für das: Laden Individuelle UITableViewCells von XIB Dateien ... Noch ein anderes Verfahren

Die Idee ist es, eine SampleCell- Unterklasse der erstellen UITableViewCellmit einer IBOutlet UIView *contentEigenschaft und eine Eigenschaft für jede benutzerdefinierte subview Sie aus dem Code zu konfigurieren. Dann eine SampleCell.xib Datei zu erstellen. In dieser Nib - Datei, ändern Sie die Datei Besitzer SampleCell-. Fügen Sie einen Inhalt UIViewGröße an Ihre Bedürfnisse anzupassen. Hinzufügen und konfigurieren Sie alle Subviews (Label, Bildansichten, Knöpfe, etc.) Sie wollen. Schließlich verbinden die Inhaltsansicht und die Subviews den Eigentümer der Datei.

Beantwortet am 24/03/2011 um 12:51
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more