Hoe ga je te laden aangepaste UITableViewCells van Xib-bestanden?

stemmen
278

De vraag is simpel: Hoe maak je aangepaste laden UITableViewCellvan Xib-bestanden? Hierdoor kunt u Interface Builder gebruiken om uw cellen. Het antwoord is blijkbaar niet eenvoudig te wijten aan geheugenbeheer problemen. Deze draad vermeldt het probleem en stelt een oplossing, maar pre-NDA afgifte en mist code. Hier is een lange draad dat de kwestie bespreekt zonder een definitief antwoord.

Hier is een code die ik heb gebruikt:

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

Om deze code te gebruiken, maakt MyCell.m / .h, een nieuwe subklasse van UITableViewCellen toe te voegen IBOutletsvoor de onderdelen die u wilt. Maak vervolgens een nieuwe Empty XIB bestand. Open het bestand Xib in IB, voeg een UITableViewCellobject, stel de identifier op MyCellIdentifier, en stel deze klasse mycell en voeg uw componenten. Ten slotte sluit de IBOutletsaan de componenten. Merk op dat we het bestand eigenaar in IB heeft ingesteld.

Andere methoden pleiten voor het instellen van het bestand Eigenaar en waarschuwen voor geheugenlekken als de Xib niet via een extra fabriek klasse wordt geladen. Ik testte de hierboven onder Instruments / morsen en zagen geen geheugenlekken.

Dus wat is de canonieke manier om cellen van Xibs laden? Hebben we stellen Bestand van de eigenaar? Hebben we een fabriek nodig? Zo ja, wat is de code voor de fabriek eruit? Als er meerdere oplossingen, laten we verduidelijken de voors en tegens van elk van hen ...

De vraag is gesteld op 12/02/2009 om 08:27
bron van user
In andere talen...                            


23 antwoorden

stemmen
292

De juiste oplossing is dit:

- (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;
}
antwoordde op 29/11/2012 om 16:57
bron van user

stemmen
282

Hier zijn twee methoden die de oorspronkelijke auteur staten door een IB ingenieur werd aanbevolen .

Bekijk de werkelijke post voor meer details. Ik geef de voorkeur methode # 2 als het eenvoudiger lijkt.

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 is nog steeds geldig, maar er is geen documentatie voor het niet meer. Vroeger was het in de officiële documenten , maar is nu verwijderd in het voordeel van storyboards.

Ik postte een werkend voorbeeld op GitHub:
https://github.com/bentford/NibTableCellExample

antwoordde op 21/12/2009 om 11:19
bron van user

stemmen
33

Registreren

Na IOS 7, heeft deze werkwijze vastgelegd vereenvoudigd tot ( 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")

( NB ) Dit is ook bereikt door het creëren van de cellen in het .xibof .stroyboardbestanden, als prototype cellen. Als u nodig hebt om een klasse hechten aan hen, kunt u het prototype cel selecteert en voeg de desbetreffende klasse (moet een afstammeling van zijn UITableViewCell, natuurlijk).

dequeue

En later, uit de rij gehaald met behulp van ( 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
}

Het verschil is dat deze nieuwe methode niet alleen de cel dequeues, het creëert ook als onbestaande (dat betekent dat je niet hoeft te doen if (cell == nil)shenanigans), en de cel is klaar om gewoon te gebruiken als in het bovenstaande voorbeeld.

( Waarschuwing ) tableView.dequeueReusableCell(withIdentifier:for:)heeft het nieuwe gedrag, als je de ander te bellen (zonder indexPath:) je het oude gedrag, waarin je nodig hebt om te controleren op te krijgen nilen bijvoorbeeld het zelf, let op de UITableViewCell?return waarde.

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

En natuurlijk, het type van de bijbehorende klasse van de cel is degene die je gedefinieerd in het .xib bestand voor de UITableViewCellonderklasse, of als alternatief, met behulp van de andere register methode.

Configuratie

Idealiter uw cellen zijn al geconfigureerd in termen van uiterlijk en de inhoud positionering (zoals labels en uitzicht op de afbeelding) tegen de tijd dat je ze geregistreerd en op de cellForRowAtIndexPathmethode die u ze gewoon in te vullen.

Alles bij elkaar

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

En natuurlijk, dit is allemaal beschikbaar in ObjC met dezelfde naam.

antwoordde op 21/05/2015 om 01:47
bron van user

stemmen
32

Nam antwoord Shawn Craver en maakten het een beetje.

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

Ik maak alle subklassen van BBCell mijn UITableViewCell's en vervang de standaard

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

met:

cell = (BBDetailCell *)[BBDetailCell cellFromNibNamed:@"BBDetailCell"];
antwoordde op 22/06/2010 om 03:15
bron van user

stemmen
15

Ik gebruikte bentford's 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;
}

Het werkt, maar kijk uit voor verbindingen naar Bestand van de eigenaar in uw aangepaste UITableViewCell .xib bestand.

Bij het passeren owner:selfin uw loadNibNamedverklaring, de door u ingestelde UITableViewControllerals Bestand van de eigenaar van je UITableViewCell.

Als u slepen en neerzetten om de header-bestand in IB voor het opzetten van acties en verkooppunten, zal het hen opgezet als Eigenaarsbestand niet anders aangegeven.

In loadNibNamed:owner:options, zal de code van Apple proberen om eigenschappen in te stellen op je UITableViewController, want dat is de eigenaar. Maar je hoeft niet die eigenschappen er gedefinieerd, dus je krijgt een foutmelding over het feit dat de belangrijkste waarde codering-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.'

Als een evenement in plaats daarvan wordt geactiveerd, ontvangt u een NSInvalidArgumentException krijgen:

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

Een eenvoudige oplossing is om uw Interface Builder verbindingen wijzen op de UITableViewCellplaats van File's Eigenaar:

  1. Klik met de rechtermuisknop op Bestand van de eigenaar om de lijst met verbindingen omhoog te trekken
  2. Een schermopname maken met Command-Shift-4 (slepen om het gebied te selecteren dat moet worden vastgelegd)
  3. x uit de verbindingen van File's Eigenaar
  4. Klik met de rechtermuisknop op de UITableCell in de Object hierarchie en opnieuw toe te voegen verbindingen.
antwoordde op 19/03/2012 om 22:41
bron van user

stemmen
12

Ik heb besloten om te posten aangezien ik geen van deze antwoorden wilt - dingen kunnen altijd meer eenvoudige en dit is veruit de meest beknopte manier die ik heb gevonden.

1. Bouw je Xib in Interface Builder zoals u het wilt

  • Stel File's Eigenaar naar de klas NSObject
  • Voeg een UITableViewCell en stel deze klasse MyTableViewCellSubclass - als uw IB crasht (gebeurt in Xcode> 4 van dit schrijven), net een UIView gebruik maken van doen de interface in Xcode 4 als u nog steeds dat rond leggend
  • Lay-out van uw subviews binnen deze cel en voeg uw IBOutlet verbindingen met uw @interface in de .h of .m (.m is mijn voorkeur)

2. In uw UIViewController of UITableViewController subklasse

@implementation ViewController

static NSString *cellIdentifier = @"MyCellIdentier";

- (void) viewDidLoad {

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

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

    ...

    return cell;
}

3. In je MyTableViewCellSubclass

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

    return self;
}
antwoordde op 26/08/2013 om 09:18
bron van user

stemmen
8

Als u gebruik maakt Interface Builder om cellen te maken, controleer dan of u de Identifier in de inspecteur hebt ingesteld. Controleer vervolgens of het is hetzelfde wanneer u belt dequeueReusableCellWithIdentifier.

Ik heb per ongeluk vergeten om een ​​aantal identificatiemiddelen vast te stellen in een tabel-zware-project, en de prestaties verandering was als dag en nacht.

antwoordde op 28/04/2010 om 11:55
bron van user

stemmen
7

Loading UITableViewCells van XIBs bespaart een hoop van code, maar resulteert meestal in afschuwelijke scrollsnelheid (eigenlijk, het is niet de XIB, maar het overmatig gebruik van UIViews die dit veroorzaken).

Ik stel voor dat je een kijkje op deze te nemen: Link referentie

antwoordde op 12/02/2009 om 15:19
bron van user

stemmen
5

Hier is de klasse methode die ik heb gebruikt voor het maken van aangepaste cellen uit 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;
}

Daarna, in de XIB, ik de naam van de klasse, en hergebruik identifier. Daarna kan ik gewoon bellen die methode in mijn ogen controller in plaats van de

[[UITableViewCell] alloc] initWithFrame:]

Het is voldoende snel genoeg, en wordt gebruikt in twee van mijn scheepvaart toepassingen. Het is betrouwbaarder dan bellen [nib objectAtIndex:0], en in mijn ogen althans, betrouwbaarder dan bijvoorbeeld Stephan Burlot omdat je gegarandeerd alleen pak een uitzicht uit een XIB dat is het juiste type.

antwoordde op 12/02/2009 om 14:47
bron van user

stemmen
4

Correcte oplossing is dit

- (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; 
    }
antwoordde op 07/09/2016 om 08:33
bron van user

stemmen
3

Check this - http://eppz.eu/blog/custom-uitableview-cell/ - echt handige manier met behulp van een kleine klasse die eindigt op één lijn in de uitvoering controller:

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

voer image beschrijving hier

antwoordde op 09/07/2013 om 10:18
bron van user

stemmen
3

Het herladen van de NIB is duur. Beter een keer te laden, dan instantiëren de objecten wanneer u een cel nodig. Merk op dat u UIImageViews etc om de penpunt kan toevoegen, zelfs meerdere cellen, met behulp van deze methode (Apple's "registerNIB" iOS5 staat slechts een top-level object - Bug 10.580.062 "iOS5 tableView registerNib: te beperkend"

Dus mijn code is hieronder - je leest in de NIB één keer (in initialize zoals ik deed of in viewDidLoad -.. Wat Vanaf dat moment, je instantiëren de penpunt in objecten dan kies degene die je nodig hebt Dit is veel efficiënter dan het laden van de penpunt opnieuw en opnieuw.

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;
}
antwoordde op 14/12/2011 om 20:01
bron van user

stemmen
2

Eerste importeer uw aangepaste mobiele bestand #import "CustomCell.h"en wijzig de afgevaardigde methode zoals hieronder vermeld:

- (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;
}
antwoordde op 26/02/2014 om 07:48
bron van user

stemmen
2

De juiste manier om het te doen is om een ​​UITableViewCell subklasse implementatie, header en XIB creëren. In de XIB verwijderen standpunten en voeg een tabel cel. Stel de klasse als de naam van de UITableViewCell subklasse. Voor de eigenaar van het bestand, maken het de UITableViewController subklasse klasse naam. Sluit de eigenaar van een bestand naar de cel met behulp van de tableViewCell stopcontact.

In de header-bestand:

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

Bij de uitvoering bestand:

@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;
}
antwoordde op 28/06/2012 om 22:57
bron van user

stemmen
2

Wat ik doe want dit is te verklaren een IBOutlet UITableViewCell *cellin de controller klasse. Roepen dan is de NSBundle loadNibNamedklasse methode, die het zal voeden UITableViewCelltot de hierboven aangegeven cel.

Voor de xib zal ik een lege xib maken en voeg het UITableViewCellobject in IB waar het kan worden opgezet als dat nodig is. Deze mening wordt dan verbonden met de cel IBOutletin de regelaar 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 toevoegingen loadNibNamed (ADC login)

cocoawithlove.com artikel dat ik afkomstig van het concept van (krijgen de telefoonnummers monster app)

antwoordde op 12/02/2009 om 19:01
bron van user

stemmen
1

In Swift 4.2 en Xcode 10

Ik heb drie XIB cel bestanden

in viewDidLoad Registreer uw XIB bestanden zoals deze ...

Dit is de eerste benadering

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

Tweede benadering rechtstreeks XIB bestanden registreren in cellForRowAt indexPath:

Dit is mijn Tableview delegeren functies

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

}
antwoordde op 12/10/2018 om 07:02
bron van user

stemmen
1
  1. Maak uw eigen aangepaste klasse AbcViewCellsubklasse van UITableViewCell(Zorg ervoor dat uw class file naam en penpunt bestandsnaam zijn hetzelfde)

  2. Maak deze uitbreiding klasse methode.

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

    let cell: AbcViewCell = UITableViewCell.fromNib()

antwoordde op 07/09/2017 om 04:07
bron van user

stemmen
1

Ik weet niet of er een canonieke manier, maar hier is mijn methode:

  • Maak een xib voor een ViewController
  • Stel de eigenaar van een bestand klasse UIViewController
  • Verwijder het uitzicht en voeg een UITableViewCell
  • Stel de klasse van uw UITableViewCell naar uw aangepaste klasse
  • Stel de Identifier van uw UITableViewCell
  • Stel de uitlaat van de weergave controller oog op uw UITableViewCell

En gebruik deze 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 uw voorbeeld, met behulp van

[nib objectAtIndex:0]

kan breken wanneer Apple de volgorde van items in de xib verandert.

antwoordde op 12/02/2009 om 10:03
bron van user

stemmen
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

}
antwoordde op 18/05/2018 om 11:17
bron van user

stemmen
0

Hier is een universele benadering voor het registreren van cellen 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)
    }
}

Uitleg:

  1. Reusableprotocol genereert cel ID van de naam van de klasse. Zorg ervoor dat u de conventie volgen cell ID == class name == nib name.
  2. UITableViewCellconform Reusableprotocol.
  3. UITableView uitbreiding abstracts weg het verschil in registratie cellen via penpunt of klasse.

Gebruik bijvoorbeeld:

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
}
antwoordde op 18/08/2017 om 08:08
bron van user

stemmen
0

Deze uitbreiding vereist 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
    }
}

Maak een Xib bestand dat slechts 1 op maat UITableViewCell bevat.

Laad het.

let cell: BacteriaCell = try NSBundle.mainBundle().loadView("BacteriaCell")
antwoordde op 28/08/2015 om 19:44
bron van user

stemmen
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;
antwoordde op 11/06/2014 om 07:38
bron van user

stemmen
0

Hier is mijn methode voor die: Laden Custom UITableViewCells van XIB Files ... Nog een andere methode

Het idee is om een SampleCell subklasse van het creëren UITableViewCellvan een IBOutlet UIView *contentwoning en een woning voor elke aangepaste subweergave u moet configureren van de code. Vervolgens naar een SampleCell.xib bestand te maken. In dit nib bestand, wijzigt u de eigenaar van een bestand te SampleCell. Voeg een inhoud UIViewbemeten om uw behoeften te passen. Toevoegen en configureren van alle subviews (label, uitzicht beeld, buttons, etc) je wilt. Ten slotte verbinden de inhoud uitzicht en de subzichten naar de eigenaar van het bestand.

antwoordde op 24/03/2011 om 12:51
bron van user

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