在ios中,比如NSString,NSArray, NSNumber 这些都是类簇,大概就是说,他们在alloc的时候其实是还没定是什么类型,只是生成了一个中间态的类,然后在init的时候在根据具体要初始化什么类型,在实际的生成对应的类型。比如看下面的列子:
id obj1 = [NSArray alloc];
id obj2 = [NSMutableArray alloc];
id obj3 = [obj1 init];
id obj4 = [obj2 init];
NSLog(@"%@",NSStringFromClass([obj1 class]));
NSLog(@"%@",NSStringFromClass([obj2 class]));
NSLog(@"%@",NSStringFromClass([obj3 class]));
NSLog(@"%@",NSStringFromClass([obj4 class]));
/*
结果:
2016-01-13 20:58:29.455 1fundation框架[2570:230724] __NSPlaceholderArray
2016-01-13 20:58:29.456 1fundation框架[2570:230724] __NSPlaceholderArray
2016-01-13 20:58:29.457 1fundation框架[2570:230724] __NSArray0
2016-01-13 20:58:29.457 1fundation框架[2570:230724] __NSArrayM
*/
发现+alloc之后并非生成了我们期望的类实例 而是一个__NSPlaceholderArray的中间对象 后面的-init或者-initWithxx等方法调用都是把消息发送给这个中间对象 再由它做工厂 生成真正的对象。(这里的__NSArrayI和__NSArrayM分别对应immutable和mutable)
对于开发者:iOS开发中的应用
1.表现和行为完全一样 但是数据源不一样
2.cell的类型不一样
3.应用的兼容,iOS6、7的图片资源不同
现在很多应用需要同时兼顾iOS6和iOS7,在表现上需要为不同的系统加载不同的图片资源,最简单粗暴的方法就是各种if/else判断,像这样:
if ([[UIDevice currentDevice]systemMajorVersion] < 7) {
/* iOS 6 and previous versions /
} else {
/ iOS 7 and above */
}
其实我们可以类似用类簇的方法来做,看起来就优雅很多了,我们可以把跟视图具体元素无关的代码放在基类,跟系统版本相关的代码拆成两个子类,然后在各自的类中加载相应的资源,比如我们的父类:
@interface TestView: UIView
-(void)test;
@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。
注意上面这种写法,其实是有问题的,会死循环,子类调用父类alloc,不停循环这里只是让大家了解这种思想,实际编码中不能这样写。
@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
这种设计模式不错,可以运用到以后的项目中.