İOS 6 UITableView dequeueReusableCellWithIdentifier: forIndexPath kullanırken UITableViewCell stilini ayarlama:


82

UITableViewCellStyleİOS 6'daki yeni yöntemleri kullanırken nasıl ayarlanacağını çözmeye çalışıyorum UITableView.

Önceden, bir oluştururken numaralandırmayı arama sırasında farklı türlerde varsayılan hücreler oluşturacak şekilde UITableViewCelldeğiştirirdim, ancak toplayabildiğim kadarıyla durum artık böyle değil.UITableViewCellStyleinitWithStyle:

UITableViewEyaletler için Apple belgeleri :

Dönüş Değeri : İlişkili yeniden kullanım tanımlayıcısına sahip bir UITableViewCell nesnesi. Bu yöntem her zaman geçerli bir hücre döndürür.

Tartışma : Performans nedenleriyle, bir tablo görünümünün veri kaynağı, hücreleri tableView: cellForRowAtIndexPath: yöntemindeki satırlara atadığında genellikle UITableViewCell nesnelerini yeniden kullanmalıdır. Tablo görünümü, veri kaynağının yeniden kullanılmak üzere işaretlediği UITableViewCell nesnelerinin bir sırasını veya listesini tutar. Tablo görünümü için yeni bir hücre sağlamanız istendiğinde veri kaynağı nesnenizden bu yöntemi çağırın. Bu yöntem, mevcut bir hücre varsa kuyruğundan çıkarır veya önceden kaydettiğiniz sınıf veya uç dosyasına göre yeni bir hücre oluşturur.

Önemli : Bu yöntemi çağırmadan önce registerNib: forCellReuseIdentifier: veya registerClass: forCellReuseIdentifier: yöntemini kullanarak bir sınıf veya uç dosyası kaydetmeniz gerekir.

Belirtilen tanımlayıcı için bir sınıf kaydettiyseniz ve yeni bir hücre oluşturulması gerekiyorsa, bu yöntem hücreyi initWithStyle: reuseIdentifier: yöntemini çağırarak başlatır. Uç tabanlı hücreler için bu yöntem, hücre nesnesini sağlanan uç dosyasından yükler. Mevcut bir hücre yeniden kullanım için uygunsa, bu yöntem bunun yerine hücrenin preparForReuse yöntemini çağırır.

Bu nasıl benim yeni cellForRowAtIndexPathyeni yöntemlerin uygulanması sonrasında görünüyor:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"cell_identifier";

    [tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:cellIdentifier];

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];

    return cell;
}

Şimdiye kadar sahip olduğum kod iyi çalışıyor ancak her zaman varsayılan stili döndürüyor. Nasıl gibi diğer stilleri ile hücreleri oluşturmak, böylece bu değiştirebilir UITableViewCellStyleDefault, UITableViewCellStyleValue1, UITableViewCellStyleValue2ve UITableViewCellStyleSubtitle?

Alt sınıfa ayırmak istemiyorum UITableViewCell, sadece varsayılan türü iOS 6'dan önce yapabildiğim gibi değiştirmek istiyorum. Apple'ın gelişmiş yöntemler sunması garip görünüyor, ancak bunların uygulanmasını desteklemek için asgari belgelerle.

Bu konuda uzmanlaşan veya benzer bir soruna giren var mı? Herhangi bir makul bilgi bulmakta zorlanıyorum.

Yanıtlar:


106

Bir alt sınıf oluşturmak istemediğini söylediğini biliyorum, ama bu kaçınılmaz görünüyor. İOS 6.0 simülatöründe test yaparken montaj koduna göre, gerçekleştirerek UITableViewyeni örneklerini UITableViewCell(veya alt sınıflarını) oluşturur.

[[<RegisteredClass> alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:<ReuseIdentifier>]

Başka bir deyişle, gönderilen stil ( UITableViewCellStyleDefault) sabit kodlanmış görünmektedir. Bunu aşmak için, varsayılan başlatıcıyı geçersiz kılan initWithStyle:reuseIdentifier:ve kullanmak istediğiniz stili geçen bir alt sınıf oluşturmanız gerekir :

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    // ignore the style argument, use our own to override
    self = [super initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:reuseIdentifier];
    if (self) {
        // If you need any further customization
    }
    return self;
}

Ayrıca, göndermek daha iyi olabilir registerClass:forCellReuseIdentifier:de viewDidLoadyerine bunu bir hücre istenen her zaman yapmanın,:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.tableView registerClass:<RegisteredClass> forCellReuseIdentifier:<ReuseIdentifier>];
}

4
Durumun gerçekten böyle olacağını varsaymaya başlıyordum. Bu büyük bir sorun değil, ancak UITableViewCelldiğer varsayılan stilleri elde etmek için alt sınıflara sahip olmak , sadece gereksiz dosyalar oluşturduğu için bir acıdır. Yorumunuz ve şüphelerimi teyit ettiğiniz için teşekkürler.
CaptainRedmuff

11
Alt sınıflandırma yerine, hala geçerli olan eski iOS5 yöntemini kullanabileceğinizi unutmayın. Bu şekilde, istediğiniz hücre stilini kendiniz başlatabilirsiniz. Diğer yanıta bakın.
SpacyRicochet

60

dequeueReusableCellWithIdentifierkullanımdan kaldırılmadığı için yenisini kullanmanız gerekmez dequeueReusableCellWithIdentifier:forIndexPath:.

Özel bir hücre sınıfı kullanıyorsanız, ancak UITableViewCellStyle numaralandırmalarından birini kullanmak istiyorsanız eski yöntemi kullanın.


1
Süslü yeni yöntemleri kullanmak zorunda olmadığınızı belirtmek için oy verildi . Yalnızca amacınıza uygunlarsa veya alternatifler kullanımdan kaldırılırsa.
SpacyRicochet

Özellikle hevesliyseniz, dequeueReusableCellWithIdentifier:forIndexPath:hücreleri eski yöntemle inşa eden (ve onları döndüren) bazı tanımlayıcılar sağlamak için geçersiz kılmanın bir sakıncası yoktur . Diğer tanımlayıcılar super'i arayacak ve bunu döndürecektir. Bu NSDictionarytür bir tanımlayıcı için bloklar oluşturmak için bir tanımlayıcıya sahip olmak mantıklı olabilir .
Benjohn

11

Film şeridi arabirim oluşturucuyu kullanarak gereksiz bir alt sınıftan kaçınabilirsiniz:

  1. Film Şeridi görünümünde, tablo görünümü hücre prototip hücresini seçin (tablo görünümünde)
  2. Yardımcı Programlar görünümünde, Nitelikler denetçisinde Stil değerini değiştirin
  3. (İsteğe bağlı olarak) Seçim ve Aksesuar gibi diğer değerleri değiştirin

Yeni iOS 6.0 dequeueReusableCellWithIdentifier:forIndexPath:, yeni hücreleri ayırırken ve döndürürken bu değerleri kullanır. (Xcode 4.5.2 kullanılarak bir iOS 6.0 derlemesinde test edilmiştir)


7

Bir dosyayı kaydeden başka bir alternatif de bir Uç oluşturmak ve registerNib:forCellReuseIdentifier:onun yerine kullanmaktır .

Ucu yapmak çok kolay: Interface Builder'da yeni bir .xib dosyası oluşturun. Varsayılan görünümü silin. Tablo Görünümü Hücresi nesnesi ekleyin. Nitelik Denetçisi'ni kullanarak hücrenin stilini değiştirin. (Burada ayrıca diğer özellikleri ayarlayarak hücreyi daha da özelleştirme fırsatına sahipsiniz.)

Ardından tablo görünümü denetleyicinizin viewDidLoadyönteminde aşağıdaki gibi bir şey çağırın:

[self.tableView registerNib:[UINib nibWithNibName:@"StyleSubtitleTableCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"Cell"];

initWithStyle: reuseIdentifier çağrılmaz.
thierryb

0

Bolot'un cevabı doğru. Basittir ve herhangi bir XIB dosyası oluşturmanıza gerek yoktur.

Sadece Objective-C yerine Swift kullanarak yapanlar için cevabını güncellemek istedim:

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
    super.init(style: .value1, reuseIdentifier: reuseIdentifier)
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

-5

Buna çözümüm, initWithStyle: reuseIdentifier:onu kullanarak elde ettikten sonra aramaktır [self.tableView dequeueReusableCellWithIdentifier:@"cellId" forIndexPath:indexPath]. Sonuçta init, sadece başka bir seçicidir ve derleyici, onu zaten başlatılmış bir nesnede çağırma konusunda hiçbir kısıtlama yapmaz. Bununla birlikte, init'i çağırmanın sonucunu kullanmamaktan şikayet edecek, ben de şunu yapıyorum:

UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:@"cellId" forIndexPath:indexPath];
cell = [cell initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cellId"];

Bunun Swift'de işe yaramayacağını tahmin ediyorum ...


En zarif çözüm imo. Umarım initWithStyle'ın cesareti her şeyi yeniden yaratmaz.
Scott Birksted

2
Pekala, sanırım böyle yaparsan, sır çözme işlerini tamamen bırakabilirsin ...
stk

1
Hücrelerin yeniden kullanılması, yüksek performanslı bir UITableView için anahtardır. Çözümünüz hücreleri yeniden kullanmamayı öneriyor.
Berik

2
Aradığınızda initWithStyle: reuseIdentifierikinci kez, aslında yeni oluşturulmuş bir nesne ile hücreyi üzerine yazıyorsunuz. Evet, hafızanın tahsisi zaten yapıldı ve yeni hücre aynı hafıza konumunun üzerine yazacak, ama aslında onu yeniden başlattığınızda tamamen yeni bir nesne yaratıyorsunuz. Bu, ilk etapta hücreleri yeniden kullanmanın tüm amacı olan tüm optimizasyonu geçersiz kılar.
AnthonyMDev

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.