阅读本文需要对ReactiveCocoa足够了解,也可以参阅图解ReactiveCocoa基本函数
Cocoa Touch Framework无疑是一个很好的框架,特别是对动画的支持,在我接触过的框架中可能是最好的(当然我接触的框架可能比较少),但是就UITableView来说确实存在很多吐槽点,从我个人理解的角度做些分析,尝试去解决这些吐槽点,并给到的解决方案。
UITableView枚举滥用
枚举从来都是为了可扩展而存在的,UITableView中对UITableViewStyle的使用堪称滥用,先看看这个枚举的定义,枚举项的命名不够直观,源码的注释也得不到有效信息,
typedef NS_ENUM(NSInteger, UITableViewStyle) {
UITableViewStylePlain, // regular table view
UITableViewStyleGrouped // preferences style table view
};
再看看如下文档的说明,基本明确了设计者的本意,UITableViewStyle想要区分的是页眉或页脚(section headers or footers)是否浮动,接下来做个剖析:
case plain
A plain table view. Any section headers or footers are displayed as inline separators and float when the table view is scrolled.
case grouped
A table view whose sections present distinct groups of rows. The section headers and footers do not float.
UITableView的初始化函数
- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style; // must specify style at creation. -initWithFrame: calls this with UITableViewStylePlain
- UITableViewStyle作为初始化函数的参数的不合理性,大多数的UIView及其子类都是一样风格的初始化函数,到了UITableView这里就显得有点另类,设计者将 UITableViewStyle放到初始化函数中作为参数,无非就是不希望style在UITableView初始化之后被改变,可能原因是UITableView滑动的过程中style被改变了,不管之前是否存在浮动的页眉或页脚,改变之后对UI的呈现可能是比较突兀的,另外这种变更可能并没有实际意义;
- UITableViewStyle的存在不合理,当一个枚举只存在两个选项时,很多时候会考虑使用BOOL来表示,可读性也不差,比如这里用isSectionGrouped,可能时不需要看注视或者文档就可以理解了;
- UITableViewStylePlain的命名不合理,我们知道UITableView总是会分section,
Plain从其语义和StoryBoard默认值的显示可以联想UITableViewStylePlain可能是想表示只有一个section的情况,那么所谓的页眉或页脚是否浮动其实就没有太大意义,如果页眉或页脚不需要浮动其实就是一个Cell了,因为最终效果都是一样的,反过来假设需要多个section,但是页眉或页脚都不需要浮动,那么这些页眉或页脚其实用Cell来表示是不是更好呢!
综上得出结论:UITableViewStyle是不该用。
UITableViewCell枚举乱用
UITableViewCell存在好几个枚举的乱用,乱用表示不该用的时候用了。
UITableViewCellStyle的乱用
typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
UITableViewCellStyleDefault, // Simple cell with text label and optional image view (behavior of UITableViewCell in iPhoneOS 2.x)
UITableViewCellStyleValue1, // Left aligned label on left and right aligned label on right with blue text (Used in Settings)
UITableViewCellStyleValue2, // Right aligned label on left with blue text and left aligned label on right (Used in Phone/Contacts)
UITableViewCellStyleSubtitle // Left aligned label on top and left aligned label on bottom with gray text (Used in iPod).
};
UITableViewCell的初始化方法中同样也带上了UITableViewCellStyle,先看代码
// Designated initializer. If the cell can be reused, you must pass in a reuse identifier. You should use the same reuse identifier for all cells of the same form.
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(nullable NSString *)reuseIdentifier;
如果说UITableView设计者觉得就只存在两种style,那么UITableViewCell设计中加入UITableViewCellStyle就显得完全是乱用了。一样的道理,枚举从来就不是为了扩展而存在,UITableViewCell做为cell的基类,扩展是必须的,不可能所有的cell都长的跟UITableViewCellStyle中定义的几个枚举项所分类的完全一样,所以这个设计是有多恶心啊。
再看看UITableViewCellStyle的各个枚举项的命名,简直是残暴啊,UITableViewCellStyleValue1,UITableViewCellStyleValue2这些是什么鬼哦,再看看注释,分别说明Used in Settings和Used in Phone/Contacts,这就很明显了,这些实现完全就是系统组件用到了这样的实现,然后直接做为api开放出来的,并没有做很好的抽象,在初始化函数中加入UITableViewCellStyle,污染了初始化函数,限制了扩展,每每在写一个UITableViewCell的子类时,总是有一种莫名的哀伤,UITableViewCellStyle做为参数存在唯一的作用就是多写了点代码,然后没有任何意义。这些cell style所表示的cell完全应该通过子类化来实现的,所以UITableViewCellStyle的乱用是有点惨不忍睹的。
UITableViewCellSeparatorStyle的乱用
typedef NS_ENUM(NSInteger, UITableViewCellSeparatorStyle) {
UITableViewCellSeparatorStyleNone,
UITableViewCellSeparatorStyleSingleLine,
UITableViewCellSeparatorStyleSingleLineEtched // This separator style is only supported for grouped style table views currently
};
怎么说也不应该存在这样一个枚举,CellSeparatorStyle这里针对不同的UITableViewStyle而设计的,不管是何种style,应该只需要isShowCellSeparatorLine这样一个BOOL值表示是否需要显示边框,如果是UITableViewStyleGrouped这种style,可能需要额外的一个isCellSeparatorLineEtched,如果根据前面的假设,页眉或页脚都是默认浮动的话,这样设计是很合理的。
当一个枚举各项的命名过于诡异时,这个枚举的存在实际上是要好好考虑下的,所以UITableViewCellSeparatorStyle也是典型的乱用。
UITableViewCell对以下枚举的使用也是有待商榷的
typedef NS_ENUM(NSInteger, UITableViewCellSelectionStyle) {
UITableViewCellSelectionStyleNone,
UITableViewCellSelectionStyleBlue,
UITableViewCellSelectionStyleGray,
UITableViewCellSelectionStyleDefault NS_ENUM_AVAILABLE_IOS(7_0)
};
UITableViewCellSelectionStyle想表示cell选中的样式,这里大概是通过这种方式来提高几种默认值,因为CellSelectionStyle还是可以定制的,但是UITableViewCellSelectionStyleDefault放在最后UITableViewCellSelectionStyleNone放在最开始,到底谁是default哦;
typedef NS_ENUM(NSInteger, UITableViewCellFocusStyle) {
UITableViewCellFocusStyleDefault,
UITableViewCellFocusStyleCustom
} NS_ENUM_AVAILABLE_IOS(9_0);
UITableViewCellFocusStyle这个枚举的存在难道仅仅是为了无病呻吟吗?