Несколько подклассов UiTableViewCell в одном UiTableView? Почему этот код не работает - PullRequest
4 голосов
/ 29 января 2009

Хорошо, так вот моя проблема. У меня есть таблица, немного похожая на Apple AddressBook.app, которая использует разные подклассы ячеек для отображения информации по-разному. В этом конкретном приложении у меня есть 3 различных подкласса UiTableViewCell, все со своими собственными кончиками.

Я не могу получить правильный код :-(, если я пытаюсь получить доступ к переменной экземпляра моей ячейки в методе CellForRowPath, он говорит: «(ERROR-запрос для элемента« type »в чем-то, что не является структурой или объединением»). Я предполагаю, что слово «что-то» является корнем моей проблемы .. Код, который я собираюсь вставить, очевидно, неправильно настроил мою ячейку. Вот код:

Есть 3 оператора if, чтобы получить правильный подкласс ячейки в зависимости от вызываемого раздела:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *PoolFacilityCellIdentifier = @"PoolFacilityCellIdentifier";
static NSString *PoolFacilityAddressCellIdentifier = @"PoolFacilityAddressCellIdentifier";
static NSString *PoolFacilityPoolCellIdentifier = @"PoolFacilityPoolCellIdentifier";
NSUInteger section = indexPath.section;

//Creat a generic container for cell which will be cast during one of the next two statements
id cell;

//Change the identifier depending on cell type. MIGHT NEED TO ADD SOMETHING ELSE FOR POOLS AND PRICES
if (section == KAddressIndex) {
    cell = (PoolFacilityAddressCell *)[tableView dequeueReusableCellWithIdentifier:PoolFacilityAddressCellIdentifier];

    if (cell == nil) {

        //Load the appropriate nib for the type of cell being asked for.

            NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"PoolFacilityAddressCell" owner:self options:nil];

            for (id object in nib) {

                if ([object isMemberOfClass:[PoolFacilityAddressCell class]]) 
                    cell = (PoolFacilityAddressCell *) object;

            }
    }

}
else if (section == KPoolIndex) {
    cell = (PoolFacilityPoolCell *)[tableView dequeueReusableCellWithIdentifier:PoolFacilityPoolCellIdentifier];

    if (cell == nil) {

        //Load the appropriate nib for the type of cell being asked for.

        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"PoolFacilityPoolCell" owner:self options:nil];

        for (id object in nib) {

            if ([object isMemberOfClass:[PoolFacilityPoolCell class]]) 
                cell = (PoolFacilityPoolCell *) object;


        }
    }
}
else {
    cell = (PoolFacilityCell *)[tableView dequeueReusableCellWithIdentifier:PoolFacilityCellIdentifier];

    if (cell == nil) {

        //Load the appropriate nib for the type of cell being asked for.

        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"PoolFacilityCell" owner:self options:nil];

        for (id object in nib) {

            if ([object isMemberOfClass:[PoolFacilityCell class]]) 
                cell = (PoolFacilityCell *) object;
        }
    }

}

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

Код, который выдает мою ошибку, - это (в частности, cell.type.text = thePool.type) cell.type - это Iboutlet UiLabel:

if (section == KPoolIndex) {

    NSMutableArray *thePools = [allSections objectForKey:sectionAsNumber];

    if ([thePools count] > 0) {
        [cell setPromptMode:NO];
        //Set the label and Pool from the Pool Object
        Pool *thePool = [thePools objectAtIndex:row];
        cell.type.text = thePool.type;


    }

}

Спасибо

Dan

Ответы [ 4 ]

2 голосов
/ 29 января 2009

У Мэтта Галлахера есть статья, в которой изложен более понятный способ создания такого типа стола. Он разбивает код конкретной ячейки на свои собственные классы. Облегчает управление.

cocoawithlove.com - Гетерогенные ячейки в UITableViewController

В вашем коде эта строка выглядит как проблема

cell.type.text = thePool.type;

thePool - это объект "Pool", есть ли у него свойство с именем "type"? Убедитесь, что @property и @synthesize правильно настроены для «type» в вашем объекте «Pool».

1 голос
/ 29 января 2009

У меня может быть несколько ответов на мой вопрос:

1 - Как уже упоминал Дрю, клеточные остатки типа ID. Я подумал, что, если функции приведут к типу ячейки, она будет определенным типом, но это не так.

2 - Решением было бы иметь 3 больших оператора if для каждого типа ячеек. Каждый оператор if, заканчивающийся

возвратная ячейка;

вызов.

3 - Решение, которое я собираюсь попробовать сейчас, состоит в том, чтобы иметь только один подкласс ячейки вместо 3 и иметь метод в моем подклассе ячейки под названием

- (Недействительными) setCellBehaviour: (интермедиат) definedNumber

Таким образом, я могу скрывать слои / метки и т. Д. И настраивать их по своему желанию.

обновление

Я достиг требуемых результатов, как это:

У меня есть только один подкласс ячейки, который имеет один NIB со многими различными UIlabels.

Я вызываю это в cellForRowAtIndexPath: метод моего контроллера uiview, когда ячейка была выделена / init.

//Set the behaviour
    [cell setCellBehaviour:KCellBehaviourName];

Это относится к определениям, которые я установил в заголовочном файле контроллера представления:

//Definitions for cell type behaviour. Passed to cell during creation.

(HASH) определяет KCellBehaviourStandard 0 (HASH) определить KCellBehaviourName 1 (HASH) определить KCellBehaviourAddress 2 (HASH) определить KCellBehaviourPool 3

(похоже, в этом посте не может быть хэшей)

Тогда у моего UITableViewCellSubclass есть этот метод, который мы вызывали ранее:

-(void)setCellBehaviour:(NSUInteger)definedBehaviour {

switch (definedBehaviour) {
    case KCellBehaviourStandard:
        self.label.hidden = NO;
        self.value.hidden = NO;
        self.length.hidden = YES;
        self.poolType.hidden = YES;
        break;
    case KCellBehaviourName:
        self.label.hidden = NO;
        self.value.hidden = NO;
        self.length.hidden = YES;
        self.poolType.hidden = NO;
        break;
    case KCellBehaviourAddress:
        self.label.hidden = NO;
        self.value.hidden = NO;
        self.length.hidden = YES;
        self.poolType.hidden = YES;
        break;
    case KCellBehaviourPool:
        self.label.hidden = NO;
        self.value.hidden = NO;
        self.length.hidden = NO;
        self.poolType.hidden = YES;
    default:
        break;
}

}

1 голос
/ 29 января 2009

Я полагаю, это может быть связано с тем, что ваша ячейка объявлена ​​как id, и вы пытаетесь получить доступ к свойству из одного из подклассов вашей ячейки. Вы можете отправить все сообщения , которые вы хотите, объекту типа id, но попытка получить доступ к свойствам объекта типа id не удастся во время компиляции. Кроме того, обязательно импортируйте файлы .h, содержащие ваши подклассы.

0 голосов
/ 04 февраля 2009

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

Это строка, которая вызывает ошибку:

cell.type.text = thePool.type;

Вы можете исправить это, заменив это следующими строками:

PoolFacilityCell* poolCell = (PoolFacilityCell *)cell;
poolCell.type.text = thePool.type;

Точечный синтаксис для доступа к свойствам работает, только если компилятор знает, с каким классом вы работаете. Он не может иметь дело с cell.type, потому что cell объявлен как тип id, поэтому во время компиляции он не знает, что type должен быть свойством Objective-C. Сообщение об ошибке называет это «что-то не структура или объединение», потому что оно думает, что вы рассматриваете cell как простую структуру C, а это не так, следовательно, ошибка.

Кстати, строки, где вы пишете:

cell = (PoolFacilityAddressCell *) object;

не имеют смысла. Поскольку cell объявлен как id (любой универсальный объект), нет необходимости в приведении. Исходя из более раннего комментария, вы, кажется, думаете, что приведение типов подобным образом как-то влияет на переменную cell. Это не. Строка выше компилируется в инструкции, которые просто копируют адрес памяти экземпляра из object в cell. Приведение типов позволяет избежать предупреждений и ошибок во время компиляции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...