2013-02-07 160 views
1

雖然循環的哪種方法更好/更清潔?

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {} 

方法IM設置數據到我的自定義單元格(圖像和文本)。我想知道實現這個目標的最佳方法是什麼。

我可以使用2個不同的陣列(圖像陣列和文本陣列)和執行類似:

cell.image setImage: //get image from imageArray with indexPath.row 
cell.text.text = [textArray objectAtIndex:indexPath.row]; 

,或者使用一個多維陣列是這樣的:

cell.image setImage: [imageArray objectAtIndex:indexPath.row] objectAtIndex:0; 
cell.text.text = [textArray objectAtIndex:indexPath.row] objectAtIndex:1; 

// or use of dictionary with keys 

什麼方法是更快的或更具可讀性?

+3

如果文本和圖像是密切相關的,也許你應該添加一個類來保存圖像和文本對(例如MyClass)。然後使用MyClass的實例數組,以便獲得更清晰可讀的代碼。 – onevcat

+0

這也是最有效的方法嗎? –

+0

這不能成爲使用課堂的大問題。所有的副作用是你應該創建一些實例。與圖像繪製和文本呈現相比,實例生成和簡單的指針分配將非常便宜。 – onevcat

回答

2

我個人認爲以下是最乾淨的解決方案:

  • 爲陣列中的項目創建模型。
  • 創建一個UITableViewCell子類以在單元格中顯示模型。子類將擁有一個接受該模型並在模型更改時自行重繪的屬性。

比方說,我們有一個新聞應用程序。該數組填充了我們爲其創建模型NewsItem的項目。該模型頭部看起來是這樣的:

NewsItem.h

@interface FSNewsItem : NSObject <NSCoding> 

@property (nonatomic, copy, readonly) NSString *title; 
@property (nonatomic, copy, readonly) NSURL *URL; 
@property (nonatomic, copy, readonly) NSString *time; 
@property (nonatomic, copy, readonly) NSString *points; 
@property (nonatomic, copy, readonly) NSString *author; 

// initialiser 
+ (FSNewsItem *)newsItemWithTitleNode:(HTMLNode *)node 
          subTextNode:(HTMLNode *)subNode; 

@end 

現在對於我們創建一個NewsItemCell細胞。對於NewsItemCell代碼可能類似於以下內容:

NewsItemCell.h

@interface FSNewsItemCell : UITableViewCell 

@property (nonatomic, strong) FSNewsItem *newsItem; 

@end 

NewsItemCell.m

@interface FSNewsCell() 

@property (nonatomic, strong) UILabel *titleLabel; 
@property (nonatomic, strong) UILabel *detailLabel; 

@end 


@implementation FSNewsItemCell 

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 
{ 
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 
    if (self) 
    { 
     self.titleLabel      = [[UILabel alloc] init]; 
     [self addSubview:_titleLabel]; 

     self.detailLabel      = [[UILabel alloc] init]; 
     [self addSubview:_detailLabel]; 
    } 
    return self; 
} 

- (void)layoutSubviews 
{ 
    [super layoutSubviews]; 

    const CGRect bounds = self.bounds; 
    CGFloat width = bounds.size.width - (FS_FLOAT_PADDING * 2) - 15.0f; 
    _titleLabel.frame = CGRectMake(FS_FLOAT_PADDING, FS_FLOAT_CELL_PADDING_VERTICAL, width, 20.0f); 

    CGFloat y = _titleLabel.frame.size.height + (FS_FLOAT_CELL_PADDING_VERTICAL * 2); 
    _detailLabel.frame = CGRectMake(FS_FLOAT_PADDING, y, width, 15.0f); 
} 

#pragma mark - Private 

- (void)setNewsItem:(FSNewsItem *)newsItem 
{ 
    if (_newsItem == newsItem) 
    { 
     return; 
    } 

    _newsItem = newsItem; 

    self.titleLabel.text = newsItem.title; 

    if (_newsItem.points && _newsItem.time) 
    { 
     self.detailLabel.text = [NSString stringWithFormat:@"%@ | %@", _newsItem.points, newsItem.time]; 
    } 
    else 
    { 
     self.detailLabel.text = newsItem.time; 
    } 

    [self setNeedsLayout]; 
} 

最後,當我們希望顯示在新聞項目我們的代碼如下所示:

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

    FSNewsItemCell *cell = (FSNewsItemCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) 
    { 
     cell = [[FSNewsItemCell alloc] initWithStyle:UITableViewCellStylePlain reuseIdentifier:CellIdentifier]; 
    } 

    cell.newsItem = [_items objectAtIndex:indexPath.row]; 

    return cell; 
} 

這是我認爲最乾淨的解決方案和我大部分時間採取的方法。我喜歡保持我的視圖控制器小。我也喜歡這樣的事實,我的視圖控制器不必知道我的(自定義)表格視圖單元格具有哪些控件。表格視圖單元根據提供的數據對如何繪製自己負全部責任。

+0

看起來非常好!我想即時通訊使用這個 –

1

我會添加一個簡單的數據類,並將類實例放入NSArray。或者使用NSArrayNSDictionary對象,以便項目可以按名稱尋址,而不是位置。

例類代碼(類是很容易的這些天):

@interface DisplayItems : NSObject 
@property (nonatomic, strong) NSString *text; 
@property (nonatomic, strong) UIImage *image; 
@end 

@implementation DisplayItems 
@end 
+0

所以像我建議的第二種方法? –

+0

是的,但不是二維數組,按名稱選擇項目會更加清晰,並且如果需要更多項目,將會在未來擴展良好。 – zaph

+0

這是一個很好的建議。有一個數據模型對象,每行一個實例。 – nielsbot

1

一個想法是創建一個自定義類:

@interface CellInfo : NSObject 
@property (....) UIImage *image; 
@property (....) NSString *text; 
@end 

然後:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
... 
    CellInfo *info = [self.cellInfoArray objectAtIndex:indexPath.row]; 
    cell.image = info.image; 
    cell.text = info.text; 
... 
}