Как вы загрузить пользовательские UITableViewCells из XIb файлов?

голоса
278

Вопрос прост: Как вы загружаете на заказ UITableViewCellиз XIb файлов? Это позволяет использовать Interface Builder для разработки ваших клеток. Ответ , по- видимому, не просто из - за проблемы Managment памяти. Эта нить упоминает проблему и предлагает решение, но предварительно NDA-релиз и не имеет коды. Вот длинная нить , которая обсуждает вопрос без предоставления окончательного ответа.

Вот код, который я использовал:

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

Чтобы использовать этот код, создать MyCell.m / .h, новый подкласс UITableViewCellи добавить IBOutletsдля компонентов , которые вы хотите. Затем создайте новый файл «Пустой XIB». Откройте файл XIb в IB, добавить UITableViewCellобъект, установите его идентификатор «MyCellIdentifier», и установить его класс MyCell и добавить свои компоненты. И, наконец, подключить IBOutletsк компонентам. Обратите внимание , что мы не установили владельца файла в IB.

Другие методы пропаганда Настройки файла владелицы и предупреждать утечки памяти, если XIb не загружается через дополнительный класс фабрики. Я тестировал выше в разделе Инструменты / Утечки и не видел утечек памяти.

Так что канонический способ загрузки клеток из Xibs? установлен ли мы файл владелец? Нужен ли нам завод? Если да, то это код завода выглядеть? Если существует несколько решений, давайте проясним плюсы и минусы каждого из них ...

Задан 12/02/2009 в 08:27
источник пользователем
На других языках...                            


23 ответов

голоса
292

Правильное решение заключается в следующем:

- (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;
}
Ответил 29/11/2012 в 16:57
источник пользователем

голоса
282

Вот два способа которых оригинальный автор заявляет , рекомендовались инженером IB .

См фактический пост для более подробной информации. Я предпочитаю метод # 2, как это кажется проще.

Способ № 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;
}

Способ № 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;
}

Обновление (2014): Способ № 2 остается в силе , но нет никакой документации для него больше. Раньше в официальных документы , но теперь снимается в пользу раскадровки.

Я отправил рабочий пример на Github:
https://github.com/bentford/NibTableCellExample

Ответил 21/12/2009 в 11:19
источник пользователем

голоса
33

регистр

После того, как прошивка 7, этот процесс был упрощен до ( быстрой 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")

( Примечание ) Это также достижимо путем создания клеток в .xibили .stroyboardфайлах, в качестве прототипа ячеек. Если вам нужно прикрепить класс к ним, вы можете выбрать прототип ячейки и добавить соответствующий класс (должен быть потомком UITableViewCell, конечно).

Dequeue

И в дальнейшем, используя из очереди ( скоро 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
}

Разница в том , что этот новый метод не только dequeues клетки, но и создает , если несуществующие (это означает , что вы не должны делать if (cell == nil)махинации), и клетка готова к использованию так же , как в приведенном выше примере.

( Предупреждение ) tableView.dequeueReusableCell(withIdentifier:for:)имеет новое поведение, если вы звоните в другую (без indexPath:) вы получите старое поведение, в котором вам нужно проверить nilи экземпляр его самостоятельно, обратите внимание на UITableViewCell?возвращаемое значение.

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

И, конечно же , тип соответствующего класса ячейки является один вы определили в файле .xib для UITableViewCellподкласса, или , альтернативно, с использованием другого метода регистра.

конфигурация

В идеале, ваши клетки были уже сконфигурированы с точки зрения внешнего вида и расположения контента (например , этикетки и взглядов изображения) к тому времени вы зарегистрировали их, и на cellForRowAtIndexPathметоде вы просто заполнить их.

Все вместе

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

И, конечно же, все это доступно в ObjC с теми же именами.

Ответил 21/05/2015 в 01:47
источник пользователем

голоса
32

Принимал ответ Shawn Craver и очистить его немного.

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

Я делаю все подклассы моей UITableViewCell в о BBCell, а затем заменить стандарт

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

с:

cell = (BBDetailCell *)[BBDetailCell cellFromNibNamed:@"BBDetailCell"];
Ответил 22/06/2010 в 03:15
источник пользователем

голоса
15

Я использовал bentford в Method # 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;
}

Он работает, но следить за связи с файлом Владельцем в пользовательской UITableViewCell .xib файла.

Пропустив owner:selfв вашем loadNibNamedзаявлении вы установите в UITableViewControllerкачестве файла владельца вашего UITableViewCell.

Если перетащить в файл заголовка в IB, чтобы настроить действия и выходы, он установит их в качестве владельца файла по умолчанию.

В loadNibNamed:owner:options, код от Apple будет пытаться установить свойства на свой контекстуальный UITableViewController, так как это владелец. Но вы не имеете те свойства , определенные здесь, так что вы получите ошибку о том , ключевое значение кодирования-совместимый :

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

Если событие сработало вместо этого, вы получите 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

Легко устранить проблему, чтобы указать ваши соединения Interface Builder на этот UITableViewCellВладельце вместо файла в:

  1. Щелкните правой кнопкой мыши на File владелицей, чтобы подтянуть список соединений
  2. Возьмите захват с Command-Shift-4 экрана (перетащить, чтобы выбрать область для захвата)
  3. х из соединения от владельца файла
  4. Щелкните правой кнопкой мыши на UITableCell в иерархии объектов и повторно добавить соединения.
Ответил 19/03/2012 в 22:41
источник пользователем

голоса
12

Я решил опубликовать, так как я не нравится ни один из этих ответов - вещи всегда может быть более простым, и это, безусловно, самый краткий путь я нашел.

1. Создайте свой XIb в Interface Builder, как вам это нравится

  • Установите файл по Владелец класса NSObject
  • Добавить UITableViewCell и установить свой класс в MyTableViewCellSubclass - если ваш IB аварии (происходит в Xcode> 4, как это письмо), просто использовать UIView из сделать интерфейс в Xcode 4, если вы до сих пор его прокладку вокруг
  • Компоновка ваши подвидов внутри этой ячейки и приложить ваши соединения IBOutlet к вашему @interface в .h или .m (.m мои предпочтения)

2. В вашем UIViewController или UITableViewController подкласса

@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

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

    return self;
}
Ответил 26/08/2013 в 09:18
источник пользователем

голоса
8

Если вы используете Interface Builder, чтобы сделать ячейки, убедитесь, что вы установили идентификатор в инспекторе. Затем убедитесь, что это то же самое при вызове dequeueReusableCellWithIdentifier.

Я случайно забыл установить некоторые идентификаторы в табличном тяжелый проект, и изменение производительности был как день и ночь.

Ответил 28/04/2010 в 11:55
источник пользователем

голоса
7

Загрузка UITableViewCells из XIBs экономит много кода, но, как правило, приводит к ужасной скорости прокрутки (на самом деле, это не XIB, но чрезмерное использование UIViews, которые вызывают это).

Я предлагаю вам взглянуть на это: ссылка Ссылка

Ответил 12/02/2009 в 15:19
источник пользователем

голоса
5

Вот метод класса, который я использую для создания пользовательских ячеек из 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;
}

Затем, в XIB, я поставил имя класса и идентификатор повторного использования. После этого, я могу просто вызвать этот метод, на мой взгляд контроллера вместо

[[UITableViewCell] alloc] initWithFrame:]

Это много достаточно быстро, и используется в двух моих приложениях доставки. Это более надежный , чем вызов [nib objectAtIndex:0], и на мой взгляд , по крайней мере, более надежны , чем , например Стефана Burlot, потому что вы гарантированно только захватить вид из XIB , что является правильным типом.

Ответил 12/02/2009 в 14:47
источник пользователем

голоса
4

Правильное решение это

- (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; 
    }
Ответил 07/09/2016 в 08:33
источник пользователем

голоса
3

Проверьте это - http://eppz.eu/blog/custom-uitableview-cell/ - очень удобный способ , используя крошечное класс , который заканчивается на одну строку вверх в реализации контроллера:

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

введите описание изображения здесь

Ответил 09/07/2013 в 10:18
источник пользователем

голоса
3

Перегрузочный СИБ дорого. Лучше, чтобы загрузить его один раз, а затем создавать экземпляры объектов, когда вам нужна ячейка. Обратите внимание, что вы можете добавить UIImageViews и т.д. до кончика пера, даже нескольких ячеек, используя этот метод (от Apple «registerNIB» iOS5 допускает только один верхний объект уровня - Ошибка 10580062 «iOS5 Tableview registerNib: чрезмерно ограничительная»

Так что мой код ниже - вы читаете в СИБЕ один раз (в инициализации, как я сделал или viewDidload -.. Все, С тех пор, инстанцирование пера в объекты затем выбрать один вам нужно это намного эффективнее, чем загрузка пера вновь и вновь.

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;
}
Ответил 14/12/2011 в 20:01
источник пользователем

голоса
2

Сначала импортировать файл пользовательских ячеек , #import "CustomCell.h"а затем изменить метод делегата , как показано ниже упомянуто:

- (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;
}
Ответил 26/02/2014 в 07:48
источник пользователем

голоса
2

Правильный способ сделать это состоит в создании реализации подкласса UITableViewCell, заголовок и XIB. В XIB удалить любые мнения и просто добавить ячейку таблицы. Установите класс как имя подкласса UITableViewCell. Для владельца файла, сделать его имя класса подкласс UITableViewController. Подключение владельца файла в ячейку, используя выход tableViewCell.

В заголовочном файле:

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

В файле реализации:

@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;
}
Ответил 28/06/2012 в 22:57
источник пользователем

голоса
2

Что я могу сделать для этого провозгласить IBOutlet UITableViewCell *cellв своем классе контроллера. Затем вызовите NSBundle loadNibNamedметод класса, который накормит UITableViewCellк клетке , упомянутой выше.

Для XIb я создать пустой XIB и добавить UITableViewCellобъект в IB , где он может быть установлен по мере необходимости. Эта точка зрения затем соединяется с ячейкой IBOutletв классе контроллера.

- (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 дополнения loadNibNamed (ADC Войти)

cocoawithlove.com статье я соерсед концепцию из (получить приложение телефонные номера образца)

Ответил 12/02/2009 в 19:01
источник пользователем

голоса
1

В Swift 4.2 и Xcode 10

У меня есть три файла XIb ячейки

в ViewDidLoad зарегистрировать XIb файлы, как это ...

Это первый подход

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

Второй подход непосредственно зарегистрировать XIb файлы в cellForRowAt indexPath:

Это мои функции TableView делегата

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

}
Ответил 12/10/2018 в 07:02
источник пользователем

голоса
1
  1. Создайте свой собственный заказной класс AbcViewCellподкласс от UITableViewCell(Убедитесь , что имя файла класса и имя файла СИБ одинаковы)

  2. Создать этот метод класса расширения.

    extension UITableViewCell {
        class func fromNib<T : UITableViewCell>() -> T {
            return Bundle.main.loadNibNamed(String(describing: T.self), owner: nil, options: nil)?[0] as! T
        }
    }
    
  3. Используй это.

    let cell: AbcViewCell = UITableViewCell.fromNib()

Ответил 07/09/2017 в 04:07
источник пользователем

голоса
1

Я не знаю, если есть канонический путь, но вот мой метод:

  • Создание XIB для ViewController
  • Установите класс владельца файла на UIViewController
  • Удалить вид и добавить UITableViewCell
  • Установите класс вашего UITableViewCell для пользовательского класса
  • Установить идентификатор вашего UITableViewCell
  • Установите выход вашего зрения зрения контроллера на ваш UITableViewCell

И использовать этот код:

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

В вашем примере, используя

[nib objectAtIndex:0]

может сломаться, если Apple, изменяет порядок элементов в XIb.

Ответил 12/02/2009 в 10:03
источник пользователем

голоса
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

}
Ответил 18/05/2018 в 11:17
источник пользователем

голоса
0

Вот универсальный подход для регистрации клеток 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)
    }
}

Объяснение:

  1. ReusableПротокол генерирует идентификатор соты от его имени класса. Убедитесь , что вы будете следовать соглашению: cell ID == class name == nib name.
  2. UITableViewCellсоответствует Reusableпротоколу.
  3. UITableView расширение абстрагирует разницу в регистрации клеток через перо или класс.

Пример использования:

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
}
Ответил 18/08/2017 в 08:08
источник пользователем

голоса
0

Это расширение требует 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
    }
}

Создайте файл XIb, который содержит только один пользовательский UITableViewCell.

Загрузите его.

let cell: BacteriaCell = try NSBundle.mainBundle().loadView("BacteriaCell")
Ответил 28/08/2015 в 19:44
источник пользователем

голоса
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;
Ответил 11/06/2014 в 07:38
источник пользователем

голоса
0

Вот мой метод для этого: Загрузка пользовательских UITableViewCells из XIB файлов ... Еще один метод

Идея заключается в том , чтобы создать SampleCell подкласс UITableViewCellс IBOutlet UIView *contentимуществом и имуществом для каждого обычая подтаблицы вам нужно настроить из кода. Затем , чтобы создать файл SampleCell.xib. В этом СИБЕ файл, изменить владелец файла на SampleCell. Добавить контент UIViewразмера , чтобы соответствовать вашим потребностям. Добавление и настройка всех подвидов (этикетка, просмотр изображений, кнопок и т.д.) , которые вы хотите. И, наконец, связать представление содержимого и подвиды для владельца файла.

Ответил 24/03/2011 в 12:51
источник пользователем

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