Xib dosyalarından özel UITableViewCells'i nasıl yüklersiniz?


293

Soru basit: UITableViewCellXib dosyalarından özel yükleme nasıl yapılır? Bunu yapmak, hücrelerinizi tasarlamak için Interface Builder'ı kullanmanızı sağlar. Görünüşe göre cevap, bellek yönetimi sorunları nedeniyle basit değil. Bu iş parçacığı bu sorundan bahseder ve bir çözüm önerir, ancak NDA sürümünden önce gelir ve koddan yoksundur. İşte bu uzun iplik kesin bir cevap vermeden konuyu tartışmaktadır.

İşte kullandığım bazı kod:

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

Bu kodu kullanmak için, yeni bir alt sınıf olan MyCell.m / .h dosyasını oluşturun UITableViewCellve IBOutletsistediğiniz bileşenlere ekleyin . Sonra yeni bir "Boş XIB" dosyası oluşturun. IB'de Xib dosyasını açın, bir UITableViewCellnesne ekleyin , tanımlayıcısını "MyCellIdentifier" olarak ayarlayın ve sınıfını MyCell olarak ayarlayın ve bileşenlerinizi ekleyin. Son olarak, IBOutletsbileşenlere bağlayın . IB'de Dosyanın Sahibini ayarlamadığımızı unutmayın.

Diğer yöntemler, Dosya Sahibinin ayarlanmasını savunur ve Xib ek bir fabrika sınıfı aracılığıyla yüklenmezse bellek sızıntıları konusunda uyarır. Yukarıdakileri Aletler / Sızıntılar altında test ettim ve bellek sızıntısı görmedim.

Peki Xib'lerden hücre yüklemenin kanonik yolu nedir? Dosyanın Sahibini ayarlıyor muyuz? Bir fabrikaya ihtiyacımız var mı? Eğer öyleyse, fabrikanın kodu neye benziyor? Birden fazla çözüm varsa, her birinin artılarını ve eksilerini açıklığa kavuşturalım ...


2
Birisi konuyu gerçekten soruyu soracak şekilde düzenleyebilir, yani "Xib dosyalarından özel UITableViewCells'i nasıl yüklersiniz?" (Stackoverflow'da bu mümkün değilse yoksayın.)
Steven Fisher

1
İOS 5 ve üstü için bu çözüm: giuseppe'nin çözümü ile aynı olan stackoverflow.com/questions/15591364/… .
Matt Becker

Hızlı not, daha basit (2013 çevresi) burada cevap stackoverflow.com/questions/15378788/… jamihash
Fattie

Yanıtlar:


288

İşte orijinal yazar devletlerin bir IB mühendisi tarafından önerildiği iki yöntem .

Daha fazla ayrıntı için asıl gönderiye bakın. Daha basit göründüğü gibi # 2 yöntemini tercih ederim.

Yöntem 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;
}

Yöntem # 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;
}

Güncelleme (2014): Yöntem # 2 hala geçerli, ancak artık herhangi bir dokümantasyon yok. Eskiden resmi dokümanlardaydı, ancak şimdi film şeridi lehine kaldırıldı.

Github'da çalışan bir örnek yayınladım:
https://github.com/bentford/NibTableCellExample

Swift 4.2 için düzenleme

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
    self.tblContacts.register(UINib(nibName: CellNames.ContactsCell, bundle: nil), forCellReuseIdentifier: MyIdentifier)
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: MyIdentifier, for: indexPath) as! ContactsCell

    return cell
}

1
Yöntem 1 için, "cell = (BDCustomCell *) [[temporaryController.view retain] autorelease];" geçici kontrol cihazı serbest bırakıldığında hücre serbest kalmıyor mu?
Tod Cunningham

Hm. # 2 ile ilgili belgeler hala XIB dosyasındaki hücrenin sahibini bilinen bir denetleyici sınıfına ayarlamanızı söyler. Yükleme sırasında sahibini ne zaman ayarladığınız önemli olmayabilir.
Oscar

@OscarGoldman XIB dosyasındaki hücrenin sahibi bir sınıftır (yani sahip türü). LoadNibNamed: owner: options içindeki hücrenin sahibi, XIB'de belirtilen türde bir nesnedir.
bentford

2
@CoolDocMan # 2 Seçeneği hala çalışıyor. Sorun büyük olasılıkla ucu ile ilgilidir. İşte bir örnek: github.com/bentford/NibTableCellExample
bentford

2
Bu süper eski kod neden bu kadar yüksek sıralanıyor? Stackoverflow bir şeyler yapın: /
Nico S.

304

Doğru çözüm şudur:

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

bu iOS5 uygulamalarını kıracak mı? UINib'i hiç görmedim
Adam Waite

@AdamWaite NIB dosyalarının kaydedilmesi iOS 5 ve sonraki sürümler için çalışır, bu nedenle iOS 5 uygulamalarını bozmaz. Ve UINib, iOS 4'ten beri bile var
Mecki

İyi bir örnek için, buradaki üst yanıtta belirtilen git
repo'suna bakın

39

Kayıt ol

İOS 7'den sonra, bu işlem ( swift 3.0 ) için basitleştirildi :

// For registering nib files
tableView.register(UINib(nibName: "MyCell", bundle: Bundle.main), forCellReuseIdentifier: "cell")

// For registering classes
tableView.register(MyCellClass.self, forCellReuseIdentifier: "cell")

( Not ) Bu, prototip hücreleri olarak .xibveya .stroyboarddosyalarındaki hücreler oluşturularak da elde edilebilir . Onlara bir sınıf eklemeniz gerekiyorsa, hücre prototipini seçebilir ve karşılık gelen sınıfı ekleyebilirsiniz UITableViewCell(elbette soyundan gelmeli ).

Dequeue

Ve daha sonra, ( swift 3.0 ) kullanılarak feshedildi :

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    let cell : UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)

    cell.textLabel?.text = "Hello"

    return cell
}

Aradaki fark, bu yeni yöntemin yalnızca hücreyi ayıklamak değil, aynı zamanda var olmayan (yani, şenanigans yapmak zorunda olmadığınız anlamına gelir if (cell == nil)) oluşturur ve hücrenin yukarıdaki örnekte olduğu gibi kullanıma hazır olmasıdır.

( Uyarı ) tableView.dequeueReusableCell(withIdentifier:for:)yeni davranışa sahiptir, diğerini çağırırsanız (olmadan indexPath:) kontrol etmeniz nilve kendiniz örneklemeniz gereken eski davranışı alırsınız , UITableViewCell?dönüş değerini fark edin .

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

Ve elbette, hücrenin ilişkili sınıfının türü, UITableViewCellalt sınıfın .xib dosyasında veya alternatif olarak diğer kayıt yöntemini kullanarak tanımladığınız türdür .

Yapılandırma

İdeal olarak, hücreleriniz, onları kaydettiğiniz zamana ve cellForRowAtIndexPathyalnızca doldurduğunuz yönteme göre görünüm ve içerik konumlandırma (etiketler ve görüntü görünümleri gibi) açısından zaten yapılandırılmıştır .

Hep birlikte

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

Ve elbette, bunların hepsi aynı isimlerle ObjC'de mevcut.


İşte objC versiyonu:[self.tableView registerNib:[UINib nibWithNibName:@"BlaBlaTableViewCell" bundle:nil] forCellReuseIdentifier:kCellIdentifier];
Zeb

33

Shawn Craver'ın cevabını aldı ve biraz temizledi.

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

BBCell'in tüm UITableViewCell alt sınıflarımı yapıyorum ve ardından standardı değiştiriyorum

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

ile:

cell = (BBDetailCell *)[BBDetailCell cellFromNibNamed:@"BBDetailCell"];

16

Bentford'ın Yöntem # 2'sini kullandım :

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

Çalışır, ancak özel UITableViewCell .xib dosyanızdaki Dosya Sahibine bağlantılara dikkat edin .

İfadenizi ileterek owner:self, dosyanızın Dosya Sahibi olarak loadNibNamedayarlayın .UITableViewControllerUITableViewCell

İşlemleri ve çıkışları ayarlamak için IB'deki başlık dosyasına sürükleyip bırakırsanız, bunları varsayılan olarak Dosya Sahibi olarak ayarlar.

In loadNibNamed:owner:options, Apple'ın kodu UITableViewControllersahibi olduğu için özelliklerinizi ayarlamaya çalışacaktır . Ancak, burada tanımlanmış bu özelliklere sahip olmadığınızdan, anahtar değer kodlamasına uyumlu olma konusunda bir hata alırsınız :

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

Bunun yerine bir Olay tetiklenirse, bir NSInvalidArgumentException alırsınız:

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

Kolay bir çözüm, Arayüz Oluşturucu bağlantılarınızı UITableViewCellDosya Sahibi yerine işaret etmektir :

  1. Bağlantı listesini açmak için Dosya Sahibine sağ tıklayın
  2. Command-Shift-4 ile ekran görüntüsü alma (çekilecek alanı seçmek için sürükleyin)
  3. Dosya Sahibinden bağlantıları x
  4. Nesne hiyerarşisinde UITableCell'e sağ tıklayın ve bağlantıları yeniden ekleyin.

Bahsettiğiniz bir sorun vardı, ama Dosya sahibi yerine UITableViewCell bağlantıları nasıl? Adımlarınızı anlamıyorum, örneğin neden ekran görüntüsü almak gerekiyor? ve prizin yanındaki ekle düğmesini tıkladığımda hiçbir şey olmuyor
xu huanze

@xuhuanze Ekran görüntüsü almayı önerdim, böylece Dosya'nın sahibinin zaten bağlı olduğu şeylerin kaydını tutabilirsiniz. Ardından aynı bağlantıları yeniden oluşturabilirsiniz. Bağlantıları eklemek için sürükleyip bırakmanız gerekir - sadece tek bir tıklama değil.
Mart'ta 13

Çok teşekkürler, ben "bu sınıf anahtar değeri kodlama uyumlu anahtar değil" sorunu vardı ve sizin yardımınızla çözüldü. Başkalarına, özel hücre sınıfı olarak kullandığınız UITableViewCell sınıfınızı da sınıfınıza değiştirmeniz gerektiğini söylemek istiyorum.
Denis Kutlubaev

14

Bu cevaplardan hiçbirini beğenmediğim için göndermeye karar verdim - işler her zaman daha basit olabilir ve bu benim bulduğum en kısa yol.

1. Xib'inizi Interface Builder'da istediğiniz gibi oluşturun

  • Dosyanın Sahibini NSObject sınıfına ayarlayın
  • Bir UITableViewCell ekleyin ve sınıfını MyTableViewCellSubclass olarak ayarlayın - IB'niz çökerse (bu yazıdan sonra Xcode> 4'te olur), hala etrafta varsa Xcode 4'te bir arayüz UIView kullanın.
  • Alt görünümlerinizi bu hücreye yerleştirin ve IBOutlet bağlantılarınızı .h veya .m'deki @ arayüzünüze ekleyin (.m benim tercihimdir)

2. UIViewController veya UITableViewController alt sınıfınızda

@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. MyTableViewCellSubclass'ınızda

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

    return self;
}

9

Hücre yapmak için Arayüz Oluşturucu'yu kullanıyorsanız, Denetleyicide Tanımlayıcıyı ayarladığınızdan emin olun. Sonra dequeueReusableCellWithIdentifier'ı çağırırken aynı olup olmadığını kontrol edin.

Masa üstü bir projede yanlışlıkla bazı tanımlayıcılar ayarlamayı unuttum ve performans değişikliği gece gündüz gibiydi.


8

UITableViewCells'i XIB'lerden yüklemek çok fazla kod tasarrufu sağlar, ancak genellikle korkunç kaydırma hızıyla sonuçlanır (aslında, XIB değil, buna neden olan UIViews'un aşırı kullanımı).

Şuna bir göz atmanızı öneririm: Bağlantı başvurusu


6

İşte XIB'lerden özel hücreler oluşturmak için kullandığım sınıf yöntemi:

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

Sonra XIB, sınıf adını ayarlamak ve tanımlayıcı yeniden kullanın. Bundan sonra, bu yöntemi görünüm denetleyicim yerine

[[UITableViewCell] alloc] initWithFrame:]

Yeterince hızlı ve iki gönderim uygulamamda kullanılıyor. Bu çağırarak daha güvenilir olduğunu [nib objectAtIndex:0]ve sadece sağ türüdür bir XIB'nin bir görünüm dışarı kapmak için aklımda hiç olmazsa, Stephan Burlot en Örneğin daha güvenilir garantili çünkü.


5

Doğru Çözüm bu

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

4

NIB'i yeniden yüklemek pahalıdır. Bir kez yüklemek daha iyidir, daha sonra bir hücreye ihtiyacınız olduğunda nesneleri somutlaştırın. Bu yöntemi kullanarak UIImageViews vb nib, hatta birden fazla hücre ekleyebilirsiniz unutmayın (Apple'ın "registerNIB" iOS5 sadece bir üst düzey nesneye izin verir - Hata 10580062 "iOS5 tableView registerNib: aşırı kısıtlayıcı"

Kodum aşağıda - NIB'de bir kez okudum (yaptığım gibi başlat ya da viewDidload'da - her neyse. O zamandan itibaren, ucu nesnelere somutlaştırır, sonra ihtiyacınız olanı seçersiniz. tekrar ve tekrar.

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

4

Bunu kontrol edin - http://eppz.eu/blog/custom-uitableview-cell/ - denetleyici uygulamasında bir satır sona eren küçük bir sınıf kullanarak gerçekten kullanışlı bir yol:

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

resim açıklamasını buraya girin


3

Bunu yapmanın doğru yolu, bir UITableViewCell alt sınıf uygulaması, üstbilgi ve XIB oluşturmaktır. XIB'de görünümleri kaldırın ve bir tablo hücresi ekleyin. Sınıfı UITableViewCell alt sınıfının adı olarak ayarlayın. Dosya sahibi için, onu UITableViewController alt sınıf sınıfı adı yapın. TableViewCell çıkışını kullanarak dosya sahibini hücreye bağlayın.

Başlık dosyasında:

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

Uygulama dosyasında:

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

3

Bunun için yaptığım şey IBOutlet UITableViewCell *cellkontrolör sınıfınızda bir beyan etmektir. Ardından NSBundle loadNibNamed, UITableViewCellyukarıda belirtilen hücreye beslenecek olan sınıf yöntemini çağırın .

Xib için boş bir xib oluşturacağım ve UITableViewCellIB'de nesneyi gerektiği gibi ayarlanabileceği yere ekleyeceğim . Bu görünüm daha sonra IBOutletdenetleyici sınıfındaki hücreye bağlanır .

- (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 eklentileri loadNibNamed (ADC girişi)

cocoawithlove.com makale Ben konsept kaynaklı (telefon numaraları örnek uygulaması olsun)


3
  1. Kendi özelleştirilmiş sınıf AbcViewCellalt sınıfınızı oluşturun UITableViewCell(Sınıf dosya adınızın ve uç dosya adınızın aynı olduğundan emin olun)

  2. Bu uzantı sınıfı yöntemini oluşturun.

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

    let cell: AbcViewCell = UITableViewCell.fromNib()


2

Önce özel hücre dosyanızı içe aktarın #import "CustomCell.h"ve sonra temsilci yöntemini aşağıda belirtildiği gibi değiştirin:

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

2

In Swift 4.2 ve Xcode 10

Üç XIB hücre dosyam var

in ViewDidLoad XIB dosyalarınızı böyle kaydedin ...

Bu ilk yaklaşım

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

İkinci yaklaşım XIB dosyalarını doğrudan cellForRowAt indexPath'e :

Bu benim tablo görünümü temsilci işlevlerim

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

}

1

İşte benim yöntem: XIB dosyalarından özel UITableViewCells yükleme… Yine başka bir yöntem

Fikir, koddan yapılandırmanız gereken her özel alt görünüm için UITableViewCellbir IBOutlet UIView *contentözelliğe ve bir özelliğe sahip bir SampleCell alt sınıfı oluşturmaktır . Sonra bir SampleCell.xib dosyası oluşturun. Bu uç dosyasında, dosya sahibini SampleCell olarak değiştirin. UIViewİhtiyaçlarınıza uyacak boyutta bir içerik ekleyin . İstediğiniz tüm alt görünümleri (etiket, resim görünümleri, düğmeler vb.) Ekleyin ve yapılandırın. Son olarak, içerik görünümünü ve alt görünümleri dosya sahibine bağlayın.


1

İşte hücreleri kaydetmek için evrensel bir yaklaşım 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)
    }
}

Açıklama:

  1. Reusableprotokol kendi sınıf adından hücre kimliği oluşturur. Emin kuralını izleyin Make: cell ID == class name == nib name.
  2. UITableViewCellReusableprotokole uygundur .
  3. UITableView genişleme, hücrelerin uç veya sınıf yoluyla kaydedilmesindeki farkı ortadan kaldırır.

Kullanım örneği:

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
}

0

Kanonik bir yol olup olmadığını bilmiyorum, ama işte benim yöntemim:

  • ViewController için xib oluşturma
  • Dosya Sahibi sınıfını UIViewController olarak ayarlayın
  • Görünümü silin ve bir UITableViewCell ekleyin
  • UITableViewCell Sınıfınızı özel sınıfınıza ayarlayın
  • UITableViewCell'inizin Tanımlayıcısını Ayarlama
  • Görünüm denetleyicisi görünümünüzün çıkışını UITableViewCell'inize ayarlayın

Ve bu kodu kullanın:

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

Örneğin,

[nib objectAtIndex:0]

Apple xib'deki öğelerin sırasını değiştirirse kırılabilir.


Benim için bu her zaman yeni bir örnek oluşturmaya neden olur. dequeue her zaman sıfır dönüyor gibi görünüyor.
garip

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;

0

Bu uzantı Xcode7 beta6 gerektiriyor

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

Yalnızca 1 özel UITableViewCell içeren bir Xib dosyası oluşturun.

Yükle.

let cell: BacteriaCell = try NSBundle.mainBundle().loadView("BacteriaCell")

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

}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.