我有一个UITableViewCell
子类,它在每个单元格中都有一个大的缩略图和一个标题。该单元格可以显示视频、图像、照片库或绘图。
根据单元格显示的内容类型,缩略图顶部会有一个小图标,以明确单元格中显示的内容种类。例如,如果单元格正在显示视频,它会有一个缩略图,上面可能有三角形播放图标,以显示这是一个视频。一幅画可能有一支铅笔。
我想以一种有组织的、遵循MVC的方式来做这件事,因为我正在努力学习如何保持代码的组织性和可维护性。
我的第一个想法是为每种内容类型都有一个UITableViewCell
子类,但当唯一改变的是顶部的一个小图标时,似乎需要维护很多不同的类。
我的下一个想法是在类上有一个type
实例变量来表示它所显示的内容,然后显示与类型对应的图标。但在这种情况下,单元格不是MVC中的view
(V)吗?视图是否也应该在显示它时处理逻辑?
还有更好的东西吗?
最后,这是如何与Interface Builder结合使用的?如果是后一种解决方案,我是否将它们全部添加到IB中作为隐藏,然后根据类型以编程方式取消隐藏?
您的视图应该只显示内容,尽可能减少决策。最好的解决方案是为每种类型创建单独的单元格。这是一个非常坚固的体系结构,它将是esker进行更改并添加新功能。
- 为每个项目创建单独的模型(照片、视频、图纸)
- 创建一个MediaItemCell,它将是每个itemCells(照片、viode等)的基类
添加每个MediaItem应该具有的基本功能 - 为每种类型创建一个单独的单元格。(PhotoCell、VideoCell、DrawingCell)实现特定类型的功能
- 在StoryBoard或Xib文件中创建4个不同的单元格,并设置正确的布局和单元格ID
为了获得最佳性能,您应该重用UItableViewCell,避免更改其布局和修改单元格子视图(不要添加或删除子视图)。这就是为什么有一个显示所有对象的单元格是个坏主意。
您的viewController将有一组需要显示的项目。项目数组
[图像,视频,绘图,图像,…]
最好创建一个单独的类来容纳这些项和处理这些项的方法。通过这种方式,您可以隐藏实现细节
我称之为MediaItemsViewModel——它将保存它注意显示的所有项,数组的简单包装器
您可以在objc.io 上阅读更多Clean表视图代码
在CellForRowAtIndexPath中,您将获得一个Object,并根据其类型为其返回相应的单元格
这是Swift的代码。你可以在Objective-C中做类似的事情,也可以在Objective-C 中对对象类型进行动态调度
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
enum Cells: String {
case Photo = "Photo"
case Video = "Video"
case Drawing = "Drawing"
}
let object = objects[indexPath.row]
switch object {
case let image as Image:
let cell = tableView.dequeueReusableCellWithIdentifier("ImgeCellID", forIndexPath: indexPath) as ImageCell
cell.image = image
case let image as Video:
let cell = tableView.dequeueReusableCellWithIdentifier("VideoCellID", forIndexPath: indexPath) as VIdeoCell
cell.video = video
return cell
}
Objective-C代码。与Swift中以前的代码非常相似。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *objectCells = @{@"Video": @"VideoCell",
@"Image": @"ImageCell",
@"Drawing": @"DrawingCell"};
id<MediaItem>object = objects[indexPath.row];
NSString *cellID = objectCells[object.type];
MediaItemTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID forIndexPath:indexPath];
// MediaItemTableViewCell class that takes MediaItem
// Every class has it's own implementation to correctly show media item
cell.object = object
return cell;
}