Come si fa a caricare UITableViewCells personalizzati da file XIB?

voti
278

La domanda è semplice: come si fa a caricare personalizzati UITableViewCelldai file XIB? In questo modo consente di utilizzare Interface Builder per progettare le vostre cellule. La risposta a quanto pare non è semplice a causa di problemi di memoria managment. Questo thread menziona il problema e propone una soluzione, ma è pre NDA-release e manca codice. Ecco un lungo filo che discute la questione senza fornire una risposta definitiva.

Ecco un po 'di codice che ho usato:

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

Per utilizzare questo codice, creare MyCell.m / .h, una nuova sottoclasse di UITableViewCelle aggiungere IBOutletsper i componenti desiderati. Quindi creare un nuovo file Empty XIB. Aprire il file Xib in IB, aggiungere un UITableViewCelloggetto, impostare il suo identificativo per MyCellIdentifier, e impostare questa categoria per MyCell e aggiungere i componenti. Infine, collegare il IBOutletsai componenti. Si noti che non abbiamo impostato proprietario del file in IB.

Altri metodi sostengono l'impostazione del proprietario del file e mettere in guardia di perdite di memoria se il Xib non viene caricato tramite una classe di fabbrica aggiuntivo. Ho testato il sopra in Strumenti / Perdite e ho visto nessun perdite di memoria.

Allora qual è il modo canonico di celle di carico da Xibs? Non abbiamo fissato proprietario del file? Abbiamo bisogno di una fabbrica? Se è così, qual è il codice per la fabbrica di simile? Se ci sono più soluzioni, cerchiamo di chiarire i pro ei contro di ciascuna di esse ...

È pubblicato 12/02/2009 alle 08:27
fonte dall'utente
In altre lingue...                            


23 risposte

voti
292

La soluzione giusta è questo:

- (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;
}
Risposto il 29/11/2012 a 16:57
fonte dall'utente

voti
282

Qui ci sono due metodi che gli Stati autore originale è stato consigliato da un ingegnere IB .

Vedere il post vero e proprio per maggiori dettagli. Io preferisco il metodo # 2 come sembra più semplice.

Metodo # 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;
}

Metodo # 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): Metodo # 2 è ancora valida, ma non v'è alcuna documentazione per più. Ha usato per essere nei documenti ufficiali , ma è stato rimosso in favore di storyboard.

Ho pubblicato un esempio di lavoro su Github:
https://github.com/bentford/NibTableCellExample

Risposto il 21/12/2009 a 11:19
fonte dall'utente

voti
33

Registrare

Dopo iOS 7, questo processo è stato semplificato fino a ( 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")

( Nota ) Questo è anche realizzabile mediante la creazione delle cellule nei .xibo .stroyboardfile, come cellule prototipo. Se è necessario collegare una classe a loro, è possibile selezionare il prototipo di cella e aggiungere la corrispondente classe (deve essere un discendente di UITableViewCell, ovviamente).

dequeue

E più tardi, rimosse dalla coda utilizzando ( 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
}

La differenza è che questo nuovo metodo non solo Ritiri dalla coda della cellula, ma crea anche se inesistente (che significa che non c'è bisogno di fare if (cell == nil)imbrogli), e la cella è pronto per l'uso come nell'esempio di cui sopra.

( Attenzione ) tableView.dequeueReusableCell(withIdentifier:for:)ha il nuovo comportamento, se si chiama l'altra (senza indexPath:) si ottiene il vecchio comportamento, in cui è necessario verificare la presenza nile l'istanza da soli, si noti il UITableViewCell?valore di ritorno.

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

E, naturalmente, il tipo della classe associata della cella è quella definita nel file .xib per la UITableViewCellsottoclasse, o, in alternativa, utilizzando l'altro metodo registro.

Configurazione

Idealmente, le cellule sono state già configurate in termini di aspetto e posizionamento dei contenuti (come le etichette e punti di vista di immagine) con il tempo che li registrato e sul cellForRowAtIndexPathmetodo che semplicemente compilare.

Tutti insieme

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

E, naturalmente, tutto questo è disponibile in objC con gli stessi nomi.

Risposto il 21/05/2015 a 01:47
fonte dall'utente

voti
32

Ha preso la risposta di Shawn Craver e ripulito tutto un po '.

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

Faccio tutte le sottoclassi di mio UITableViewCell di BBCell, e quindi sostituire lo standard

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

con:

cell = (BBDetailCell *)[BBDetailCell cellFromNibNamed:@"BBDetailCell"];
Risposto il 22/06/2010 a 03:15
fonte dall'utente

voti
15

Ho usato di bentford Metodo # 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;
}

Funziona, ma attenzione per i collegamenti con proprietario del file nel file personalizzato UITableViewCell .xib.

Passando owner:selfnella vostra loadNibNameddichiarazione, si imposta il UITableViewControllercome proprietario del file della vostra UITableViewCell.

Se si trascina il file di intestazione in IB per impostare le azioni e le prese, che li impostato come proprietario del file di default.

In loadNibNamed:owner:options, il codice di Apple cercherà di impostare le proprietà sul vostro UITableViewController, dato che è il proprietario. Ma non si dispone di queste proprietà definite lì, in modo da ottenere un errore di essere il valore della chiave di codifica-compliant :

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

Se un evento viene attivato, invece, si otterrà un 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

Una soluzione semplice è quello di indicare le connessioni Interface Builder al UITableViewCellproprietario anziché di file:

  1. Fare clic destro sul file del proprietario per tirare su l'elenco delle connessioni
  2. Prendete un cattura schermo con Command-Shift-4 (trascinare per selezionare l'area da catturare)
  3. x le connessioni dal proprietario del file
  4. Fare clic destro sul UITableCell nella gerarchia di oggetti e aggiungere nuovamente i collegamenti.
Risposto il 19/03/2012 a 22:41
fonte dall'utente

voti
12

Ho deciso di postare dato che non mi piace nessuna di queste risposte - cose possono sempre essere più semplice e questo è di gran lunga il modo più conciso che ho trovato.

1. Costruisci la tua Xib in Interface Builder come piace a te

  • Impostare proprietario del file di classe NSObject
  • Aggiungi un UITableViewCell e impostare questa categoria per MyTableViewCellSubclass - in caso di blocco IB (accade in Xcode> 4 stesura di questo documento), basta usare un UIView di fare l'interfaccia in Xcode 4, se l'hai ancora, che in giro
  • Disposizione tuoi subviews dentro questa cella e attaccano le connessioni IBOutlet al @interface nel .h o .m (.m è la mia preferenza)

2. Nel UIViewController o UITableViewController sottoclasse

@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. Nelle vostre MyTableViewCellSubclass

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

    return self;
}
Risposto il 26/08/2013 a 09:18
fonte dall'utente

voti
8

Se stai usando Interface Builder per fare le cellule, controllare di aver impostato l'identificatore nella finestra di ispezione. Poi controllare che è lo stesso quando si chiama dequeueReusableCellWithIdentifier.

Ho dimenticato accidentalmente di impostare alcuni identificatori in un progetto tavolo pesante, e il cambiamento performance è stata come la notte e il giorno.

Risposto il 28/04/2010 a 11:55
fonte dall'utente

voti
7

Caricamento UITableViewCells da XIBs risparmiare un sacco di codice, ma di solito si traduce in velocità di scorrimento orribile (in realtà, non è la XIB ma l'uso eccessivo di UIViews che causano questo).

Vi suggerisco di dare un'occhiata a questo: di riferimento di collegamento

Risposto il 12/02/2009 a 15:19
fonte dall'utente

voti
5

Ecco il metodo di classe che ho usato per la creazione di cellule personalizzate fuori 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;
}

Poi, nel XIB, ho impostato il nome della classe, e l'identificatore riutilizzo. Dopo di che, posso solo chiamare quel metodo a mio controller di vista invece della

[[UITableViewCell] alloc] initWithFrame:]

E 'un sacco abbastanza veloce, e di essere utilizzato in due delle mie applicazioni di spedizione. E 'più affidabile di chiamare [nib objectAtIndex:0], e nella mia mente, almeno, più affidabile di esempio di Stephan Burlot perché avrete la garanzia di solo afferrare una vista fuori di un XIB che è il tipo giusto.

Risposto il 12/02/2009 a 14:47
fonte dall'utente

voti
4

Soluzione corretta è questa

- (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; 
    }
Risposto il 07/09/2016 a 08:33
fonte dall'utente

voti
3

Controllare questo - http://eppz.eu/blog/custom-uitableview-cell/ - modo davvero conveniente utilizzando una piccola classe che finisce una riga per l'attuazione del controller:

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

entrare descrizione dell'immagine qui

Risposto il 09/07/2013 a 10:18
fonte dall'utente

voti
3

Ricaricare la NIB è costoso. Meglio per caricare una volta, poi istanziare gli oggetti quando si ha bisogno di una cella. Si noti che è possibile aggiungere UIImageViews ecc per il pennino, anche più celle, utilizzando questo metodo (di Apple "registerNIB" iOS5 consente solo un oggetto di alto livello - Bug 10.580.062 "iOS5 tableView registerNib: troppo restrittiva"

Quindi il mio codice è qui sotto - si legge nel NIB una volta (in inizializzazione come ho fatto io o in viewDidLoad -.. Qualunque Da allora in poi, si crea un'istanza il pennino in oggetti poi scegliere quello che vi serve Questo è molto più efficiente di caricare il pennino ancora ed ancora.

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;
}
Risposto il 14/12/2011 a 20:01
fonte dall'utente

voti
2

In primo luogo importare il file cellulare personalizzato #import "CustomCell.h"e quindi modificare il metodo delegato come di seguito riportato:

- (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;
}
Risposto il 26/02/2014 a 07:48
fonte dall'utente

voti
2

Il modo corretto per farlo è creare un'implementazione sottoclasse UITableViewCell, intestazione e XIB. Nel XIB eliminare visualizzazioni e basta aggiungere una cella di tabella. Impostare la classe come il nome della sottoclasse UITableViewCell. Per il proprietario del file, ne fanno l'UITableViewController nome della classe sottoclasse. Collegare il proprietario del file alla cella utilizzando la presa di tableViewCell.

Nel file di intestazione:

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

Nel file di implementazione:

@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;
}
Risposto il 28/06/2012 a 22:57
fonte dall'utente

voti
2

Quello che faccio per questo è dichiarare un IBOutlet UITableViewCell *cellnella classe controller. Poi richiamare il NSBundle loadNibNamedmetodo della classe, che alimenterà il UITableViewCellalla cella dichiarato sopra.

Per la XIb Creerò un xib vuoto e aggiungere l' UITableViewCelloggetto in IB dove può essere configurato come necessario. Questo punto di vista è poi collegato alla cella IBOutletnella classe controller.

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

aggiunte NSBundle loadNibNamed (ADC login)

articolo cocoawithlove.com Ho proviene il concetto da (ottenere l'applicazione numeri di telefono del campione)

Risposto il 12/02/2009 a 19:01
fonte dall'utente

voti
1

In Swift 4.2 e 10 Xcode

Ho tre file di cellule XIB

in viewDidLoad registrare i file XIB come questo ...

Questo è il primo approccio

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")

Secondo approccio registrare direttamente i file XIB nel cellForRowAt indexPath:

Questo è il mio funzioni Tableview delegato

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

}
Risposto il 12/10/2018 a 07:02
fonte dall'utente

voti
1
  1. Creare la propria classe personalizzata AbcViewCellsottoclasse da UITableViewCell(Assicurarsi che il nome del file di classe e il nome del file pennino sono gli stessi)

  2. Creare questo metodo di classe di estensione.

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

    let cell: AbcViewCell = UITableViewCell.fromNib()

Risposto il 07/09/2017 a 04:07
fonte dall'utente

voti
1

Non so se c'è un modo canonico, ma qui è il mio metodo:

  • Creare una xib per un ViewController
  • Impostare la classe di file proprietario per UIViewController
  • Eliminare la vista e aggiungere un UITableViewCell
  • Impostare la classe del vostro UITableViewCell per la classe personalizzata
  • Impostare l'identificatore del vostro UITableViewCell
  • Impostare l'uscita della vostra vista vista controller al UITableViewCell

E di questo codice:

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

Nel tuo esempio, utilizzando

[nib objectAtIndex:0]

possono rompersi se Apple cambia l'ordine degli elementi nella XI ter.

Risposto il 12/02/2009 a 10:03
fonte dall'utente

voti
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

}
Risposto il 18/05/2018 a 11:17
fonte dall'utente

voti
0

Ecco un approccio universale per la registrazione di celle 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)
    }
}

Spiegazione:

  1. Reusableprotocollo genera ID cella dal suo nome di classe. Assicuratevi di seguire la convenzione: cell ID == class name == nib name.
  2. UITableViewCellsi conforma al Reusableprotocollo.
  3. UITableView estensione astrae la differenza nella registrazione cellule tramite pennino o classe.

Esempio di utilizzo:

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
}
Risposto il 18/08/2017 a 08:08
fonte dall'utente

voti
0

Questa estensione richiede 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
    }
}

Creare un file Xib che contiene solo 1 personalizzato UITableViewCell.

Caricarla.

let cell: BacteriaCell = try NSBundle.mainBundle().loadView("BacteriaCell")
Risposto il 28/08/2015 a 19:44
fonte dall'utente

voti
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;
Risposto il 11/06/2014 a 07:38
fonte dall'utente

voti
0

Qui è il mio metodo per questo: Loading UITableViewCells da XIB Files ... ancora un altro metodo

L'idea è quella di creare una sottoclasse SampleCell della UITableViewCellcon una IBOutlet UIView *contentproprietà e una proprietà per ogni visualizzazione secondaria personalizzata è necessario configurare dal codice. Quindi per creare un file SampleCell.xib. In questo file pennino, cambiare il proprietario del file per SampleCell. Aggiungere un contenuto UIViewdi dimensioni per soddisfare le vostre esigenze. Aggiungere e configurare tutte le subviews (etichetta, vista di immagine, pulsanti, ecc) che si desidera. Infine, collegare la vista contenuto e le subviews al proprietario del file.

Risposto il 24/03/2011 a 12:51
fonte dall'utente

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