IOS 类簇
类簇(class cluster)是一种设计模式,在Foundation Framework中被广泛使用,举个简单的例子
NSArray *arr = [NSArray arrayWithObjects:@"foo",@"bar", nil];
NSLog(@"arr class:%@", [arr class]);
// output: __NSArrayI
显然__NSArrayI是一个私有类,来看看这个类的头文件
@interface __NSArrayI : NSArray {
unsigned int _used;
}
可以看出__NSArrayI继承了NSArray。为什么要这么设计呢?拿NSNumber来举个例子,我们都知道NSNumber可以存储多种类型的数字,如Int/Float/Double等等,一种方式是把NSNumber作为基类,然后分别去实现各自的子类,比如所float,int,double
初看起来也没什么问题,但如果子类很多,这对使用者来说显然不够方便,得记住这么多类。如果使用类簇,问题就变得简单了,把Number作为抽象基类,子类各自实现存取方式,然后在基类中定义多个初始化方式,像这样:
现在只需要记住一个类就可以了。NSNumber的初始化伪代码大概像这样:
- (id)initWithBool
{
return [[__NSCFBoolean alloc]init];
}
- (id)initWithLong
{
return [[__NSCFNumber alloc]init];
}
也可以想这样子
- (id)initWithType:(Type)type
{
case:type
{
return [xxx new];
}
break;
case:type
{
return [xxx new];
}
break;
}
这样做的好处就是在基类中不必做过多的判断,公共的方法可以写在基类中,而不同的方法可以写在各自的类中,这样做可以使代码更加的清晰。
在iOS项目中的应用现在很多应用需要同时兼顾不同的系统版本,在表现上需要为不同的系统加载不同的图片资源,最简单粗暴的方法就是各种if/else判断,像这样:
if ([[UIDevice currentDevice]systemMajorVersion] < 7)
{
/* iOS 6 and previous versions */
}
else
{
/* iOS 7 and above */
}
不够优雅,可以使用类簇的思想来去掉if/else判断,把跟视图具体元素无关的代码放在基类,跟系统版本相关的代码拆成两个子类,然后在各自的类中加载相应的资源。
/* TestView.h */
@interface TestView: UIView
/* Common method */
- ( void )test;
@end
/* TestView.m */
@implementation TestView
+ (id)alloc
{
if ([self class]== [TestView class])
{
if ([[UIDevice currentDevice] systemMajorVersion] < 7)
{
return [TestViewIOS6 alloc];
}
else
{
return [TestViewIOS7 alloc];
}
}
else
{
return [super alloc];
}
}
- ( void )test
{}
@end
这里alloc时并没有返回TestView类,而是根据系统版本返回TestViewIOS6 或 TestViewIOS7。
/* TestViewIOS6.m */
@implementation TestViewIOS6: TestView
- (void)drawRect: (CGRect)rect
{
/* Custom iOS6 drawing code */
}
@end
/* TestViewIOS7.m */
@implementation TestViewIOS7
- (void)drawRect: (CGRect)rect
{
/* Custom iOS7 drawing code */
}
@end
网友评论
这道题考察的点有
越界判断
传参校验
Class Clusters(类簇):直接针对NSMutabledArray做Method Swizzling是没用的
Method Swizzling实战:具体实现、触发时机、方法交换时的校验等
他这里面直接对可变数组做交换方法没用是因为可变数组继承自不可变数组吗
我对不可变数组加交换方法的分类是不是就可以了呢