Iphone UITableViewCell CustomCell - PullRequest
       1

Iphone UITableViewCell CustomCell

0 голосов
/ 08 февраля 2011

Попытка реализовать «Простой» CustomCell, У меня есть обычный tableViewController, который хорошо отрисовывается с использованием обычных методов по умолчанию, но мне нужно реализовать пользовательскую ячейку с некоторыми UILabel и UIImage.

Итак, я создал CustomCell.h, CustomCell.m, CustomCell.xib

.H

@interface CustomCell : UITableViewCell <UITextViewDelegate>
{
    IBOutlet UIImageView *image;
    IBOutlet UILabel *name;
    IBOutlet UILabel *date;
    IBOutlet UILabel *comment;
}

@property (retain,nonatomic) IBOutlet UIImageView *image;
@property (retain,nonatomic) IBOutlet UILabel *name;
@property (retain,nonatomic) IBOutlet UILabel *date;
@property (retain,nonatomic) IBOutlet UILabel *comment;

и .M

@implementation CustomCell

@synthesize image;
@synthesize name;
@synthesize date;
@synthesize comment;


#pragma mark -
#pragma mark View lifecycle

- (id) initWithController: (Controller *) ctnlr 
{
    ControllerPointer = ctnlr;
    return(self);
}

- (void) SetImage:(UIImageView*)Image
{
    image = Image;
}

- (void) SetName:(NSString*)Name
{
    [Name retain];
    [name.text release];
    name.text = Name;
}

- (void) SetDate:(NSString*)Date
{
    [Date retain];
    [date.text release];
    date.text = Date;
}

- (void) SetComment:(NSString*)Comment
{
    [Comment retain];
    [comment.text release];
    comment.text = Comment;
}

в любом случае, когда я пытаюсь создать эти пользовательские ячейки в cellForRowAtIndexPath (как и следовало ожидать, может быть реализован), у меня остается только пустой экран. Очевидно, что мне не хватает чего-то большого ... Когда я создал файл .XIB с помощью «Интерфейсного Разработчика», я обязательно подключил «Ссылочные выходы» к соответствующим меткам и изображениям.

Итак, следуя подразумеваемой логике работы платформы Xcode, Я следовал тем же рассуждениям (из-за отсутствия точного примера). Во всяком случае, если есть какие-то гики IPhone, которые хотели бы просветить меня ... (да, звонков «[что-то освободить]» нет, я даже не уверен, нужно ли что-то выделять. Пожалуйста, скажите, что я пропускаю только пару звонков, это не может быть слишком много, чем что-то простое, как это верно ...?

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{   
  static NSString *CellIdentifier = @"Cell";        
    CustomCell *cell = (CustomCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if(cell == nil)
    {
        cell = [[[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil] lastObject];
    }

    NSUInteger row = [indexPath row];
    SnsObject *sObj = [SnsArray objectAtIndex:row]; 
    [cell SetName:[sObj getUserName]];

    NSUInteger row = [indexPath row];
    SnsObject *sObj = [SnsArray objectAtIndex:row]; 
    cell.name = [[UILabel alloc]init];
    cell.name.text = [sObj getUserName];

    cell.date = [[UILabel alloc]init];
    cell.date.text = [sObj getDateTime];

    cell.comment = [[UILabel alloc]init];
    cell.comment.text = [sObj getCommentText];

    cell.image = [[UIImageView alloc]init];
    cell.image.image = [sObj getImageUrl];
  return(cell)
}

Заранее спасибо!

Ответы [ 3 ]

4 голосов
/ 08 февраля 2011

Существуют и другие проблемы с кодом, помимо тех, о которых упоминал mrcrowl, теперь требующих "alloc-init" для выходов. В частности, эта строка:

cell = [[[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil] lastObject];

Это не типичная идиома, используемая для загрузки пользовательской ячейки табличного представления из .xib. Прежде всего, вы передаете «owner: self», что означает, что вы хотите соединить объекты розетки в файле .xib с элементами розетки в вашем tableviewcontroller объекте, возможно, не то, что вы предполагали. Во-вторых, вы полагаетесь на порядок объектов, возвращаемых из loadNibNamed: owner: options:, который, хотя он может работать сегодня, может не работать завтра или в новой версии iOS.

Вместо этого обычная идиома состоит в объявлении выхода для всей ячейки табличного представления в вашем контроллере табличного просмотра: (в файле .h):

...
   UITableViewCell *tvCell;
...

@property (nonatomic, retain) IBOutlet UITableViewCell *tvCell;

Тогда вместо вашей строки, у вас есть это:

[[NSBundle mainBundle] loadNibNamed:@"NewsArchiveTitleTvCell" owner:self options:nil];
cell = tvCell;
self.tvCell = nil;

Обычно это делается не с помощью подклассов, обратите внимание, как я объявил класс не как CustomCell, а как ванильный UITableViewCell. Так как же получить эти надоедливые подпредставления, чтобы настроить их? Использование тегов является нормальным способом:

...
#define kMyKewlLabelTag 1
...
    UILabel *kewlLabel = (UILabel *) [cell viewWithTag:kMyKewlLabelTag];
    kewlLabel.text = [NSString stringWithFormat:@"Hi there from row %d!", indexPath.row];
...

EDIT: редактировать: вот немного подробнее, комментарии слишком короткие, чтобы ответить на вопрос "что здесь происходит?" вопрос. Вот выдержка из одного из моих приложений, загружающего UITableViewCell из .xib:

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

    static NSString *CellIdentifier = @"MyShoppingCartTvCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) 
    {
        [[NSBundle mainBundle] loadNibNamed:@"ShoppingCartTvCell" owner:self options:nil];
        cell = tvCell;
        self.tvCell = nil;
    }
        ...
        // (insert code to grab model data for this row)
        ...
    UILabel *nameLabel = (UILabel *) [cell viewWithTag:1];
    nameLabel.text = itemNameStr;

    UILabel *countLabel = (UILabel *) [cell viewWithTag:2];
    countLabel.text = [NSString stringWithFormat:@"%d", itemCount];

    UIImageView *iv = (UIImageView *) [cell viewWithTag:3];
        ...

Вот что здесь происходит:

  • Не существует пользовательского подкласса UITableViewCell, есть только файл .xib с именем «ShoppingCartTvCell.xib», содержащий UITableViewCell, и элементы пользовательского интерфейса, размещенные внутри UITableViewCell. Элементам пользовательского интерфейса, данные которых должны изменяться в каждой строке, присваивается уникальный тег (поле тега находится в Инспекторе атрибутов CMD-1 в IB), чтобы ваш код мог получить указатель на эти объекты, чтобы изменить их (настроить метки, изображения и т. Д.) , Убедитесь, что вы не используете «0», так как все элементы по умолчанию имеют тег 0. Также убедитесь, что поле «Идентификатор» UITableViewCell в Инспекторе атрибутов CMD-1 является строкой CellIdentifier.

  • Владелец файла .xib-файла - это ваш контроллер табличного представления, в котором вы хотите отобразить ячейку. Точнее, это может быть любой класс, содержащий IBOutlet UITableViewCell * tvCell; член. Это экземпляр этого класса, который вы передаете как владелец loadNibNamed: owner: options :. До тех пор, пока значение связанного выхода равно нулю в владельце, когда вы вызываете loadNibNamed: owner: options, выход владельца заполняется объектом из .xib (до тех пор, пока соединение было установлено в. хиб в иб). Понимание того, что это магический момент в программировании Apple, открывает перед вами совершенно новые перспективы:).

  • Вы должны установить self.tvCell = nil;, чтобы подготовиться к следующему cellForRowAtIndexPath, который необходимо загрузить из .xib. Я также иногда устанавливаю nil перед loadNibNamed: owner: options :, я думаю, что это на самом деле немного безопаснее.

Вот как вы собираетесь загружать ваши UITableViewCells из .xib:

  • В xcode добавьте IBOutlet UITableViewCell * tvCell; в ваш класс UITableViewController (включая объявление свойства, если хотите)

  • В вашем проекте xcode создайте новый файл, пользовательский интерфейс, пустую Xib. Откройте этот .xib в IB

  • В IB перетащите TableViewCell из библиотеки в пустой файл .xib в поле «Первый ответчик»

  • Щелкните Владелец файла, CMD-4 (Identify Inspector), и в разделе «Класс» выберите класс, содержащий IBOutlet UITableViewCell * tvCell, который вы добавили (вероятно, ваш подкласс UITableViewController, класс, в котором вы управляете своей таблицей).

  • Удерживая клавишу Control, перетащите владелец файла в UITableViewCell и выберите розетку, которую хотите подключить. Это поле, в котором будет храниться UITableViewCell, недавно загруженный из xib, когда вы вызываете loadNibNamed: owner: параметры с экземпляром Владелец файла в качестве параметра "owner".

  • Добавление элементов пользовательского интерфейса в UITableViewCell (убедитесь, что они внутри иерархии UITableViewCell). Любые элементы, которые вы хотите настроить для каждой строки, требуют уникального значения тега.

  • следуйте рецепту, который я дал выше в cellForRowAtIndexPath

  • У вас есть волшебный момент, когда вы начинаете понимать, как файлы .xib и объекты-владельцы файла действительно работают вместе, и начинаете создавать множество классных UITableViewCells и других пользовательских объектов представления в IB, потому что это действительно просто и намного лучше, чем создавать их в коде (ИМНШО).

2 голосов
/ 08 февраля 2011

Когда вы загружаете UITableViewCell из .xib, вам не нужно создавать элементы управления вручную.

Например, такие вещи не нужны:

cell.name = [[UILabel alloc]init];

Это заменит метку, загруженную из вашей xib, новой меткой с нулевым кадром, то есть новая метка будет расположена в 0,0 и не будет иметь ширину или высоту. Следовательно, не работает .

Если вы правильно подключили xib к IBOutlets CustomCell, то элементы управления, которые вы ищете, уже должны быть там.

P.S. Простите, если я читаю слишком много в имени вашего метода, но я не думаю, что эта строка тоже будет работать, потому что свойство .image ожидает UIImage:

cell.image.image = [sObj getImageUrl];
0 голосов
/ 09 февраля 2011

Ладно ... Спасибо всем за хороший вклад, но иногда самый простой ответ не только самый красноречивый, но и самый лучший ... Вот что я нашел для работы, поддерживая его как можно более простым, не меняя вещь вне одной функции.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{   
    static NSString *CellIdentifier = @"CustomCellIdentifier";  
    CustomCell *cell = (CustomCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if(cell == nil)
    {
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
        for(id oneObject in nib)
        {
            if([oneObject isKindOfClass:[CustomCell class]])
            {
                cell = (CustomCell*)oneObject;
            }
        }
    }
    NSUInteger row = [indexPath row];
    printf("MainMessageBoard.m cellForRowAtIndexPath = [%i]\n",row);
    SnsObject *sObj = [SnsArray objectAtIndex:row];
    cell.Name.text = [sObj getUserName];
    cell.Date.text = [sObj getDateTime];
    cell.Comment.text = [sObj getCommentText];
    cell.Image.image = [self resizeImage: [self imageFromURLString: [sObj getImageUrl]] scaledToSize:CGSizeMake(32.0f, 32.0f)];
    cell.CommentCount.text = [NSString stringWithFormat:@"(%d)", [sObj getCommentCount]];
    cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
    return(cell);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...