Jak si nahrát vlastní UITableViewCells z XIb soubory?

hlasů
278

Otázkou je jednoduchá: Jak si nahrát na zakázku UITableViewCellod XIb soubory? Přitom vám umožní používat Interface Builder navrhnout vaše buňky. Odpověď zřejmě není jednoduché kvůli problémům správa paměti. Toto vlákno se zmiňuje problém a navrhuje řešení, ale je pre NP uvolňování a postrádá kód. Zde je dlouhá nit , která se zabývá problematikou bez udání definitivní odpověď.

Zde je několik kód jsem použil:

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

Chcete-li použít tento kód, vytvářet MyCell.m / .h, nové podtřídy UITableViewCella přidat IBOutletspro komponenty, které chcete. Pak vytvořte nový soubor „Empty XIb“. Otevřete soubor XIb v IB, přidat UITableViewCellobjekt, nastavte jeho identifikátor „MyCellIdentifier“, a nastavit jeho třídu MyCell a přidat součásti. A konečně, připojit IBOutletsk složek. Všimněte si, že jsme neměli nastavit vlastníka souboru v IB.

Jiné způsoby obhajovat nastavení souboru majitel a varují před úniky paměti v případě, že XIb není načten pomocí přídavného tovární třídy. Testoval jsem výše uvedené pod nástroje / úniky a neviděl žádné úniky paměti.

Takže co je kanonický způsob, jak zavést buněk z Xibs? Ještě jsme si stanovili soubor majitel? Potřebujeme továrnu? Pokud ano, jaký je kód továrny vypadat? Pokud existuje více řešení, pojďme objasnit výhody a nevýhody každého z nich ...

Položena 12/02/2009 v 08:27
zdroj uživatelem
V jiných jazycích...                            


23 odpovědí

hlasů
292

Správné řešení je toto:

- (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;
}
Odpovězeno 29/11/2012 v 16:57
zdroj uživatelem

hlasů
282

Zde jsou dvě metody, které se původní autor uvádí doporučené IB inženýr .

Podívejte se na aktuální místo pro další podrobnosti. Dávám přednost metoda č.2, jak se zdá jednodušší.

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

Update (2014): Metoda # 2 je stále platný, ale neexistuje žádná dokumentace o tom ještě. Bývala v oficiálních dokumentů , ale je nyní odstraněn ve prospěch storyboardy.

I vysláni pracovní příklad na GitHub:
https://github.com/bentford/NibTableCellExample

Odpovězeno 21/12/2009 v 11:19
zdroj uživatelem

hlasů
33

Registrovat

Po IOS 7, tento proces byl zjednodušen až na ( 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")

( Poznámka ) Toto je také možné dosáhnout vytvořením buňky v .xibnebo .stroyboardsoubory, jako prototyp buňky. Pokud potřebujete připojit třídu k nim můžete vybrat prototyp buněk a přidejte příslušnou třídu (musí být potomkem UITableViewCell, samozřejmě).

dequeue

A později, dequeued použití ( rychlý 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
}

S tím rozdílem, že tato nová metoda nejen dequeues buňku, ale také vytváří v případě neexistující (to znamená, že nemusíte dělat if (cell == nil)vylomeniny), a buňka je připraven k použití, stejně jako ve výše uvedeném příkladu.

( Pozor ) tableView.dequeueReusableCell(withIdentifier:for:)má nové chování, pokud volání druhý (bez indexPath:) se dostanete na staré chování, kterým je nutné zkontrolovat nila instance to sami si všimněte UITableViewCell?návratovou hodnotu.

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

A samozřejmě, typ přidružené třídy buňky je ten, který je definován v souboru .xib na UITableViewCellpodtřídy, nebo alternativně pomocí jiné metody registru.

Konfigurace

V ideálním případě by vaše buňky jsou již nastaveny, pokud jde o vzhled a umístění obsahu (jako jsou štítky a zobrazení obrazu) v době, kdy jste je registrován, a na cellForRowAtIndexPathzpůsobu stačí vyplnit dovnitř.

Všichni společně

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

A samozřejmě, to vše je k dispozici v ObjC se stejnými názvy.

Odpovězeno 21/05/2015 v 01:47
zdroj uživatelem

hlasů
32

Vzal Shawna Craver jeho odpověď a vyčistit to trochu.

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

Dělám všechny podtřídy mého UITableViewCell, kterými jsou BBCell a nahradit normu

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

s:

cell = (BBDetailCell *)[BBDetailCell cellFromNibNamed:@"BBDetailCell"];
Odpovězeno 22/06/2010 v 03:15
zdroj uživatelem

hlasů
15

Použil jsem bentford je 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;
}

Funguje to, ale pozor na připojení k souboru vlastník ve své vlastní UITableViewCell .xib souboru.

Předáním owner:selfve svém loadNibNamedprohlášení, nastavíte UITableViewControllerjako samostatný soubor je vlastníkem svého UITableViewCell.

Pokud jste přetáhnout do souboru záhlaví v IB nastavit akce a výstupy, bude to je nastavit jako vlastník souboru je ve výchozím nastavení.

V roce loadNibNamed:owner:options, bude Apple kód pokusí nastavit vlastnosti na tvé UITableViewController, protože to je jejich vlastníkem. Ale nemáte tyto vlastnosti tam definovány, tak dostanete chybu o tom, že klíčovou hodnotu kódování kompatibilní s :

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

Pokud se událost k aktivaci místo, dostanete k 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

Snadným řešením je upozornit své spojení Interface Builder u UITableViewCellmajitele namísto souboru:

  1. Pravé kliknutí na souboru majitel vytáhnout seznam spojů
  2. Pak se zachytit pomocí Command-Shift-4 obrazovky (tažením vyberte oblast, která má být zachycen)
  3. x out připojení od vlastníka souboru
  4. Pravým tlačítkem myši na UITableCell v hierarchii objektů a znovu přidat připojení.
Odpovězeno 19/03/2012 v 22:41
zdroj uživatelem

hlasů
12

Rozhodl jsem se psát, protože nemám rád žádné z těchto odpovědí - věci mohou být vždy jednodušší a to je zdaleka nejvíce výstižný způsobem jsem našel.

1. Sestavte si svůj XIb v Interface Builder, jak se vám to líbí

  • Sadou pilníků Majitel třídě NSObject
  • Přidejte UITableViewCell a nastavit své třídě MyTableViewCellSubclass - pokud vaše IB pády (děje v Xcode> 4 době psaní tohoto článku), stačí použít UIView of dělat rozhraní v Xcode 4, pokud máte stále to válet
  • Dispozic subviews uvnitř této buňky a připojit své IBOutlet připojení ke svému @interface v .H nebo .m (.m je moje preference)

2. Ve své UIViewController nebo UITableViewController podtřídy

@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. Ve svých MyTableViewCellSubclass

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

    return self;
}
Odpovězeno 26/08/2013 v 09:18
zdroj uživatelem

hlasů
8

Pokud používáte Interface Builder, aby se buňky, zkontrolujte, zda jste nastavili identifikátor v inspektoru. Pak zkontrolujte, zda je to to samé, když volá dequeueReusableCellWithIdentifier.

Omylem jsem zapomněl nastavit některé identifikátory v tabulkovém těžké projektu, a tato změna výkon byl jako noc a den.

Odpovězeno 28/04/2010 v 11:55
zdroj uživatelem

hlasů
7

Loading UITableViewCells z XIBs ušetří spoustu kódu, ale obvykle vede k hrozným rychlosti rolování (ve skutečnosti, to není XIB ale nadměrné užívání UIViews, které způsobují to).

Navrhuji, abyste se podívat na toto: LINK

Odpovězeno 12/02/2009 v 15:19
zdroj uživatelem

hlasů
5

Zde je metoda třídy, které jsem používal pro vytváření vlastních buněk 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;
}

Poté v XIb, jsem nastavil název třídy a identifikátoru opětovného použití. Za to, že mohu jen zavolat, že způsob podle mého názoru řadič namísto

[[UITableViewCell] alloc] initWithFrame:]

Je tu spousta dost rychle, a je používán ve dvou z mých expedice. Je to mnohem spolehlivější než volání [nib objectAtIndex:0], a ve své mysli alespoň spolehlivější než například Stephana Burlot, protože máte zaručeno, že pouze chytit pohled ven z XIb, který je správný typ.

Odpovězeno 12/02/2009 v 14:47
zdroj uživatelem

hlasů
4

Správné řešení je 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; 
    }
Odpovězeno 07/09/2016 v 08:33
zdroj uživatelem

hlasů
3

Zkontrolujte, zda tento - http://eppz.eu/blog/custom-uitableview-cell/ - opravdu pohodlný způsob, jak pomocí malé třídy, které končí jeden řádek v implementaci řadiče:

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

zadejte popis obrázku zde

Odpovězeno 09/07/2013 v 10:18
zdroj uživatelem

hlasů
3

Překládka hrotu je drahé. Lepší je to jednou načíst, pak instanci objekty, když budete potřebovat buňku. Všimněte si, že můžete přidat UIImageViews etc na hrotu, a to i více buněk, pomocí této metody (Apple „registerNIB“ iOS5 umožňuje pouze jeden nejvyšší úrovně objekt - Chyba 10580062 „iOS5 Tableview registerNib: příliš restriktivní“

Takže můj kód je uveden níže - čtete v NIB jednou (v inicializaci jako já, nebo v viewDidload -.. Cokoliv Od té doby, instanci hrot do objektů, pak vybrat ten, který potřebujete To je mnohem účinnější než načtení hrot znovu a znovu.

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;
}
Odpovězeno 14/12/2011 v 20:01
zdroj uživatelem

hlasů
2

První importovat vlastní soubor buněk #import "CustomCell.h"a potom změnit metodu delegáta, jak je uvedeno níže:

- (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;
}
Odpovězeno 26/02/2014 v 07:48
zdroj uživatelem

hlasů
2

Správný způsob, jak to udělat, je vytvořit UITableViewCell implementační podtřídy, lišty a XIb. V XIb odstranit veškeré názory a jen přidat buňku tabulky. Nastavte třídu jako název UITableViewCell podtřídy. Pro vlastníka souboru, a to díky UITableViewController název podtřídy třídy. Připojte vlastníka souboru na buňku pomocí výstupu tableViewCell.

V záhlaví souboru:

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

V souboru implementace:

@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;
}
Odpovězeno 28/06/2012 v 22:57
zdroj uživatelem

hlasů
2

To, co dělám pro to je vyhlásit IBOutlet UITableViewCell *cellve své třídě řadiče. Potom vyvolat NSBundle loadNibNamedmetodu třídy, která bude krmit UITableViewCellna buňky uvedených výše.

Pro XIb budu vytvořit prázdný XIb a přidejte UITableViewCellobjekt do IB, kde lze nastavit podle potřeby. Tento názor je pak připojen k buňce IBOutletve třídě regulátoru.

- (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 přírůstky loadNibNamed (ADC login)

cocoawithlove.com článek, který jsem Zdrojem koncept z (získat telefonní čísla ukázkové aplikace)

Odpovězeno 12/02/2009 v 19:01
zdroj uživatelem

hlasů
1

V Swift 4.2 a Xcode 10

Mám tři buněčné soubory XIb

V ViewDidLoad zaregistrovat XIb soubory, jako je tato ...

To je první přístup

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

Druhý přístup přímo registrovat XIb soubory cellForRowAt indexPath:

To je moje Tableview delegáta funkce

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

}
Odpovězeno 12/10/2018 v 07:02
zdroj uživatelem

hlasů
1
  1. Vytvořte si vlastní přizpůsobené třídy AbcViewCellpodtřídy z UITableViewCell(Ujistěte se, že název vašeho souboru třídy a nib název souboru jsou stejné)

  2. Vytvořit tuto metodu rozšíření třídy.

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

    let cell: AbcViewCell = UITableViewCell.fromNib()

Odpovězeno 07/09/2017 v 04:07
zdroj uživatelem

hlasů
1

Nevím, jestli existuje způsob, jak kanonický, ale tady je moje metoda:

  • Vytvořte XIb pro ViewController
  • Nastavte třídu File vlastníka na UIViewController
  • Odstranit zobrazení a přidejte UITableViewCell
  • Nastavte třídu svého UITableViewCell do vlastní třídy
  • Nastavení identifikace vaší UITableViewCell
  • Nastavte výstup z vašeho pohledu pohledu regulátoru do svého UITableViewCell

A použít tento kód:

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

Ve Vašem příkladu, s použitím

[nib objectAtIndex:0]

mohou rozlomit, když Apple změní pořadí položek v XIb.

Odpovězeno 12/02/2009 v 10:03
zdroj uživatelem

hlasů
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

}
Odpovězeno 18/05/2018 v 11:17
zdroj uživatelem

hlasů
0

Zde je univerzální přístup k registraci buňky 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)
    }
}

Vysvětlení:

  1. ReusableProtokol generuje ID buňky ze své třídě názvu. Ujistěte se, že budete postupovat podle pravidla: cell ID == class name == nib name.
  2. UITableViewCellv souladu s Reusableprotokolem.
  3. UITableView Rozšíření abstrahuje pryč rozdíl registrace buňky přes hrotem nebo třídy.

Příklad použití:

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
}
Odpovězeno 18/08/2017 v 08:08
zdroj uživatelem

hlasů
0

Toto rozšíření vyžaduje 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
    }
}

Vytvořte soubor XIb, který obsahuje pouze 1 vlastní UITableViewCell.

Načíst.

let cell: BacteriaCell = try NSBundle.mainBundle().loadView("BacteriaCell")
Odpovězeno 28/08/2015 v 19:44
zdroj uživatelem

hlasů
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;
Odpovězeno 11/06/2014 v 07:38
zdroj uživatelem

hlasů
0

Tady je můj způsob, který: Vkládání vlastní UITableViewCells z XIb soubory ... Yet Another Method

Hlavní myšlenkou je vytvořit SampleCell podtřídu UITableViewCells IBOutlet UIView *contentnemovitostí a majetku za každou vlastní subview musíte konfigurovat z kódu. Pak vytvořit soubor SampleCell.xib. V tomto nib souboru, změnit vlastníka souboru na SampleCell. Přidat obsah UIViewtakové velikosti, aby vyhovovala vašim potřebám. Přidat a konfigurovat všechny subviews (označení, názory obraz, tlačítka, atd), které chcete. Nakonec propojit zobrazení obsahu a subviews na vlastníka souboru.

Odpovězeno 24/03/2011 v 12:51
zdroj uživatelem

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