Cum vă încărcați UITableViewCells personalizate din fișiere de XIb?

voturi
278

Întrebarea este simplu: Cum încărcați personalizat UITableViewCellde fișiere XIb? Făcând astfel , vă permite să utilizați Interface Builder pentru a proiecta celule. Răspunsul se pare că nu este simplu din cauza problemelor Managment de memorie. Acest subiect menționează problema și propune o soluție, dar este pre-CND eliberare și lipsită de cod. Iată un fir lung , care discută problema fără a oferi un răspuns definitiv.

Iată un exemplu de cod l-am folosit:

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

Pentru a utiliza acest cod, crea MyCell.m / .h, o nouă subclasă a UITableViewCellși adăugați IBOutletspentru componentele pe care doriți. Apoi a crea un nou „XIB gol“ fișier. Deschideți fișierul XIb în IB, adăugați un UITableViewCellobiect, setați identificatorul său la „MyCellIdentifier“, și a stabilit clasa sa la MyCell și adăugați componente. În cele din urmă, conectați IBOutletsla componentele. Rețineți că nu am stabilit Proprietarul fișierului în IB.

Alte metode susțin setarea fișierului proprietar și avertizează cu privire la pierderi de memorie în cazul în care Xlb nu este încărcat printr-o clasă suplimentară din fabrică. Am testat cele de mai sus în cadrul instrumentelor / Scurgeri și am văzut nici un pierderi de memorie.

Deci, ce este modul canonic pentru a încărca celule de la Xibs? Nu am stabilit fișiere Proprietarul? Nu avem nevoie de o fabrica? Dacă da, care este codul pentru fabrica arata? Dacă există mai multe soluții, să clarifice argumentele pro și contra pentru fiecare dintre ele ...

Întrebat 12/02/2009 la 08:27
sursa de către utilizator
În alte limbi...                            


23 răspunsuri

voturi
292

Solutia corecta este aceasta:

- (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;
}
Publicat 29/11/2012 la 16:57
sursa de către utilizator

voturi
282

Aici sunt două metode pe care statele autorul original a fost propus de un inginer IB .

A se vedea postul real pentru mai multe detalii. Prefer metoda # 2 așa cum se pare mai simplu.

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

Actualizare (2014): Metoda # 2 este încă valabilă , dar nu există nici o documentație pentru ea mai. Este folosit pentru a fi în docs oficiale , dar acum este eliminat în favoarea storyboard.

Am postat un exemplu de lucru pe Github:
https://github.com/bentford/NibTableCellExample

Publicat 21/12/2009 la 11:19
sursa de către utilizator

voturi
33

Inregistreaza-te

După iOS 7, acest proces a fost simplificată până la ( rapidă 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")

( Notă ) Acest lucru este , de asemenea , realizabil prin crearea de celule în .xibsau .stroyboardfișiere, ca celule prototip. Dacă trebuie să atașați o clasă pentru ei, puteți selecta prototipul celulei și se adaugă clasa corespunzătoare (trebuie să fie un descendent al UITableViewCell, desigur).

Dequeue

Și mai târziu, folosind dequeued ( rapid 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
}

Diferența fiind că această nouă metodă nu numai dequeues celula, se creează , de asemenea , în cazul în care non-existant (ceea ce înseamnă că nu trebuie să faci if (cell == nil)situațiile comice), iar celula este gata de utilizare la fel ca în exemplul de mai sus.

( Avertizare ) tableView.dequeueReusableCell(withIdentifier:for:)are noul comportament, dacă apelați celălalt (fără indexPath:) veți obține vechiul comportament, în care aveți nevoie pentru a verifica nilși de exemplu acesta le observați UITableViewCell?valoarea de returnare.

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

Și, desigur, tipul clasei asociat celulei este cel definit în fișierul .xib pentru UITableViewCellsubclasa, sau în mod alternativ, utilizând altă metodă de registru.

configurație

În mod ideal, celulele au fost deja configurate în ceea ce privește aspectul și poziționarea conținutului (cum ar fi etichete și vizualizări ale imaginii) de momentul în care le înregistrat și pe cellForRowAtIndexPathmetoda pe care pur și simplu le completați.

Toti impreuna

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, desigur, acest lucru este toate disponibile în ObjC cu aceleași nume.

Publicat 21/05/2015 la 01:47
sursa de către utilizator

voturi
32

Am luat răspunsul Shawn Craver și curățat-l un pic.

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

Eu fac toate subclase de BBCell UITableViewCell meu, și apoi înlocuiți standardul

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

cu:

cell = (BBDetailCell *)[BBDetailCell cellFromNibNamed:@"BBDetailCell"];
Publicat 22/06/2010 la 03:15
sursa de către utilizator

voturi
15

Am folosit bentford lui 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;
}

Acesta funcționează, dar ai grija pentru conexiunile la fișier Proprietarul în fișierul dvs. personalizat UITableViewCell .xib.

Prin trecerea owner:selfîn dumneavoastră loadNibNameddeclarație, stabiliți UITableViewControllerca fișier proprietar al tău UITableViewCell.

Dacă glisați și să fixați la fișierul antet în IB pentru a configura acțiuni și puncte de vânzare, le va stabili ca File Proprietarul implicit.

În loadNibNamed:owner:options, codul Apple va încerca să setați proprietățile pe dvs. UITableViewController, deoarece aceasta este proprietarul. Dar nu au aceste proprietăți definite acolo, astfel încât să obțineți o eroare fiind valoarea cheii de codificare compatibil :

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

În cazul în care un eveniment devine declanșat în schimb, vei primi 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

O soluție simplă la punctul conexiunile Interface Builder la UITableViewCellproprietar în loc de fișier:

  1. Faceți clic dreapta pe fișier Proprietarul pentru a trage în sus lista de conexiuni
  2. Ia-o captură de ecran cu comandă-Shift-4 (trageți pentru a selecta zona care urmează să fie capturat)
  3. x racordurile de la proprietar fișierului
  4. click dreapta pe UITableCell în ierarhia obiect și adăugați conexiunile.
Publicat 19/03/2012 la 22:41
sursa de către utilizator

voturi
12

Am decis să posta, deoarece nu-mi place nici una din aceste răspunsuri - lucruri pot fi întotdeauna mai simplu și acest lucru este de departe cel mai concis l-am găsit.

1. Construiți XIb în Interface Builder așa cum vă place

  • Set de fișiere Proprietarul clasei NSObject
  • Adăugați un UITableViewCell și a stabilit clasa sa la MyTableViewCellSubclass - în cazul în care se blochează IB (se întâmplă în Xcode> 4 ca din acest scris), trebuie doar să utilizați un UIView de a face interfața Xcode 4 dacă încă îl ai în jurul valorii de stabilire
  • Dispunerea subviews dumneavoastră în interiorul această celulă și atașați conexiunile IBOutlet la @interface dumneavoastră în .h sau .m (.m este preferința mea)

2. În dvs. UIViewController sau UITableViewController subclasă

@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. În MyTableViewCellSubclass dvs.

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

    return self;
}
Publicat 26/08/2013 la 09:18
sursa de către utilizator

voturi
8

Dacă utilizați Interface Builder pentru a face celule, verificați dacă ați setat identificatorul în Inspector. Apoi, verificați că este același lucru atunci când apelați dequeueReusableCellWithIdentifier.

Am uitat din greșeală să se stabilească niște identificatori într-un proiect de masă grele, iar schimbarea de performanță a fost ca zi și noapte.

Publicat 28/04/2010 la 11:55
sursa de către utilizator

voturi
7

Se încarcă UITableViewCells de la XIBs salvează o mulțime de cod, dar de obicei duce la viteza de derulare oribil (de fapt, nu e XIb dar utilizarea excesivă a UIViews care cauzează acest lucru).

Vă sugerez să aruncăm o privire la aceasta: Link de referință

Publicat 12/02/2009 la 15:19
sursa de către utilizator

voturi
5

Iată metoda de clasa pe care l-am folosit pentru a crea celule personalizate din 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;
}

Apoi, în XIb, am stabilit numele clasei, și identificatorul de reutilizare. După aceea, eu pot apela doar că metoda în controler meu de vedere în loc de

[[UITableViewCell] alloc] initWithFrame:]

Este o multime destul de repede, și de a fi utilizate în două dintre aplicațiile mele de transport maritim. Este mult mai fiabile decât de asteptare [nib objectAtIndex:0], iar în mintea mea cel puțin, mai fiabile decât exemplul lui Stephan Burlot pentru că ești garantat de a apuca doar o imagine dintr - un XIB care este tipul corect.

Publicat 12/02/2009 la 14:47
sursa de către utilizator

voturi
4

Soluția corectă este aceasta

- (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; 
    }
Publicat 07/09/2016 la 08:33
sursa de către utilizator

voturi
3

Verificați acest lucru - http://eppz.eu/blog/custom-uitableview-cell/ - mod foarte convenabil folosind o clasă mică care se termină cu o linie mai în punerea în aplicare controler:

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

introduceți descrierea imaginii aici

Publicat 09/07/2013 la 10:18
sursa de către utilizator

voturi
3

Reîncărcarea BNI este scump. Mai bine să încărcați o dată, apoi instanțiați obiectele atunci când ai nevoie de o celulă. Rețineți că puteți adăuga UIImageViews etc la penița, chiar mai multe celule, folosind această metodă (Apple „registerNIB“ iOS5 permite doar un singur nivel de obiect de top - Bug 10580062 „iOS5 tableView registerNib: prea restrictivă“

Deci, codul meu este mai jos - ai citit în BNI o dată (în Inițializare cum am făcut-o sau în viewDidload -.. Oricare ar fi De atunci, vă instantiate penița în obiecte apoi alege pe cel care aveți nevoie Acest lucru este mult mai eficient decât încărcarea peniță peste si peste.

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;
}
Publicat 14/12/2011 la 20:01
sursa de către utilizator

voturi
2

Mai întâi importa fișierul mobil personalizat #import "CustomCell.h"și apoi modificați metoda de mai jos delegat menționat:

- (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;
}
Publicat 26/02/2014 la 07:48
sursa de către utilizator

voturi
2

Modul corect de a face acest lucru este de a crea o implementare UITableViewCell subclasă, antet, și XIb. În XIb elimina toate punctele de vedere și trebuie doar să adăugați o celulă de tabel. Setați clasa ca numele subclasa UITableViewCell. Pentru proprietar de fișier, este numele clasei subclasa UITableViewController face. Conectați proprietarul fișier la celula folosind priza tableViewCell.

În fișierul antet:

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

În dosarul de punere în aplicare:

@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;
}
Publicat 28/06/2012 la 22:57
sursa de către utilizator

voturi
2

Ceea ce fac eu pentru aceasta este o declare IBOutlet UITableViewCell *cellîn clasa controler. Apoi invoca NSBundle loadNibNamedmetoda de clasă, care va alimenta UITableViewCellla celula declarată de mai sus.

Pentru XIb voi crea un XIb gol și adăugați UITableViewCellobiectul în IB în cazul în care acesta poate fi instalat după cum este necesar. Acest punct de vedere este apoi conectat la celula IBOutletdin clasa 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;
}

adăugări NSBundle loadNibNamed (ADC autentificare)

Articolul cocoawithlove.com Am provenind conceptul de la (a obține app numere de telefon eșantion)

Publicat 12/02/2009 la 19:01
sursa de către utilizator

voturi
1

În Swift 4.2 și Xcode 10

Am trei fișiere de celule XIb

în ViewDidLoad înregistrați fișierele XIb ca aceasta ...

Aceasta este prima abordare

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

În al doilea rând abordare înregistra fișiere direct XIb în cellForRowAt indexPath:

Acest lucru este meu funcții tableview delegatul

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

}
Publicat 12/10/2018 la 07:02
sursa de către utilizator

voturi
1
  1. Creați propria clasă personalizate AbcViewCellsubclasă de la UITableViewCell(Asigurați - vă că numele fișierului de clasă și numele de fișier peniță sunt aceleași)

  2. Creați această metodă de clasă extensie.

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

    let cell: AbcViewCell = UITableViewCell.fromNib()

Publicat 07/09/2017 la 04:07
sursa de către utilizator

voturi
1

I dont știu dacă există o cale canonică, dar aici e metoda mea:

  • Creați un XIb pentru o ViewController
  • Setați clasa de fișiere proprietar la UIViewController
  • Ștergeți vizualizarea și adaugă un UITableViewCell
  • Setați clasa de UITableViewCell la clasa personalizat
  • Setați identificatorul UITableViewCell dvs.
  • Setați ieșirea de vedere de vedere controler pentru UITableViewCell dvs.

Utilizând acest cod:

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

În exemplul dvs., utilizând

[nib objectAtIndex:0]

se poate rupe în cazul în care Apple a schimba ordinea elementelor din XIb.

Publicat 12/02/2009 la 10:03
sursa de către utilizator

voturi
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

}
Publicat 18/05/2018 la 11:17
sursa de către utilizator

voturi
0

Aici este o abordare universală pentru înregistrarea celulelor din 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)
    }
}

Explicaţie:

  1. Reusableprotocol genereaza ID - ul celulei din numele clasei. Asigurați - vă că urmați convenția: cell ID == class name == nib name.
  2. UITableViewCelleste conform Reusableprotocolului.
  3. UITableView extensie abstrage departe diferența în înregistrarea celulelor prin peniță sau clasă.

Exemplu de utilizare:

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
}
Publicat 18/08/2017 la 08:08
sursa de către utilizator

voturi
0

Această extensie necesită 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
    }
}

Creați un fișier XIb care conține doar 1 personalizat UITableViewCell.

Încărcați-l.

let cell: BacteriaCell = try NSBundle.mainBundle().loadView("BacteriaCell")
Publicat 28/08/2015 la 19:44
sursa de către utilizator

voturi
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;
Publicat 11/06/2014 la 07:38
sursa de către utilizator

voturi
0

Aici este metoda mea pentru că: Încărcare personalizată UITableViewCells din XIB fișiere ... încă o altă metodă

Ideea este de a crea o subclasă SampleCell a UITableViewCellcu o IBOutlet UIView *contentproprietate și o proprietate pentru fiecare personalizat subview trebuie să configurați de la codul. Apoi , pentru a crea un fișier SampleCell.xib. În acest fișier peniță, schimbați proprietarul fișier la SampleCell. Adăugați un conținut de UIViewdimensiuni pentru a se potrivi nevoilor dumneavoastră. Adăugați și configurați toate subviews (eticheta, vizualizări de imagine, butoane, etc.) pe care le doriți. În cele din urmă, se leagă vizualizarea conținutului și subviews către proprietarul fișierului.

Publicat 24/03/2011 la 12:51
sursa de către utilizator

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