曾静的博客

但行好事,莫问前程.

嗨,我是曾静 (@devzeng),目前暂居深圳。


这是我用来记录平日学习笔记的地方,欢迎您的访问.

iOS开发中的类簇设计模式

在iOS开发中经常会使用NSArray、NSNumber这样的系统提供的类来组织我们的数据,就拿NSNumber来说,NSNumber有两个比较常用的类方法,如下所示的定义:

(1)用来把BOOL类型的数据包装成一个OC的对象:

+ (NSNumber *)numberWithBool:(BOOL)value;

(2)用来把int类型包装成一个OC对象:

+ (NSNumber *)numberWithInt:(int)value;

在Xcode中运行下面的代码片段:

NSNumber *boolNumber = [NSNumber numberWithBool:YES];
NSLog(@"%@", [[boolNumber class] description]);

执行上面的代码片段在Xcode的控制台会输出__NSCFBoolean

NSNumber *intNum = [NSNumber numberWithInt:1];
NSLog(@"%@", [[intNum class] description]);

执行上面的代码片段在Xcode的控制台会输出__NSCFNumber

[instance class]方法返回的当前的对象的类的名称,[NSNumber numberWithInt:1][NSNumber numberWithBool:YES]通过上面的验证可以看出明显不是同一个类,而且__NSCFNumber__NSCFBoolean很明显是一个私有类。

上面出现的这种现象在Foundation Framework中是很常见的一种情况,我们称作为类簇设计模式。那为什么要这样做呢?以NSNumber为例,我们知道NSNumber可以存储很多类型的数据,如int、Float、Double等等,具体支持哪些数据类型可以到NSNumber的头文件中查看,具体支持的类型如下:

char、unsigned char、short、unsigned short、int、unsigned int、long、unsigned long、long long、unsigned long long、float、double、BOOL、NSInteger、NSUInteger

一般情况下实现类似的效果一种方式是把NSNumber作为基类,然后分别去实现各自的子类,如下图所示:

iOS_Class_Cluster_1.png

但是一旦需要实现的子类多起来之后就会发现这样需要继承的子类太多,比如如果要仿NSNumber需要写这样十多个类。

iOS_Class_Cluster_2.png

最好的就是把这些子类写成私有的类,所有对外都在NSNumber中调用即可,对于使用者来说就轻松很多。

在iOS中的应用

现在很多应用需要同时兼容iOS6、iOS7目前还需要针对iOS8进行适配。适配iOS7不是简单的让APP在iOS7的系统上运行正常,而是需要按照苹果官方的推荐设计指南进行重新设计,这样就给开发者带来很多的工作量。对于iOS6之前应用的样式都差不多,而针对iOS7设计了新的样式,为了同时支持iOS6和iOS7,也在各个系统上显示的效果符合系统原生的风格,就可以采用类簇的设计进行设计。

1、定义一个名字为DemoView的类,继承UIView如下所示:

DemoView.h

@interface DemoView : UIView

@end

DemoView.m

@implementation DemoView

@end

2、在DemoView.m文件中创建三个私有的类,分别用来对三个系统进行单独处理:

////////////////iOS6适配代码////////////////////

@interface dz_DemoView_ios6 : DemoView

@end

@implementation dz_DemoView_ios6

- (void)drawRect: (CGRect)rect
{
    /* Custom iOS6 drawing code */
}

@end

////////////////iOS7适配代码////////////////////

@interface dz_DemoView_ios7 : DemoView

@end

@implementation dz_DemoView_ios7

- (void)drawRect: (CGRect)rect
{
    /* Custom iOS7 drawing code */
}

@end

////////////////iOS8适配代码////////////////////

@interface dz_DemoView_ios8 : DemoView

@end

@implementation dz_DemoView_ios8

- (void)drawRect: (CGRect)rect
{
    /* Custom iOS8 drawing code */
}

@end

3、在DemoView.m中重写alloc的方法:

+ (instancetype)alloc
{
    if([self class] == [DemoView class])
    {
        float v = [[[UIDevice currentDevice] systemVersion] floatValue];
        if(v > 7)
        {
            //iOS8
            return [dz_DemoView_ios8 alloc];
        }
        else if(v < 7 )
        {
            //iOS 6
            return [dz_DemoView_ios6 alloc];
        }
        else
        {
            //iOS 7
            return [dz_DemoView_ios7 alloc];
        }
    }
    else
    {
        return [super alloc];
    }
}

4、在需要使用该View的地方直接使用,调用者无需关注其他事情:

DemoView *demoView = [[DemoView alloc] init];
[self.view addSubView: demoView];

参考资料

1、《类簇在iOS开发中的应用》

2、《iOS 类簇(Class Cluster)使用心得》

3、《Concepts in Objective-C Programming》

4、《Strategies to support the new iOS7 UI》

最近的文章

iOS8中的通知中心快速回复

iOS8拥有了全新的通知中心,有全新的通知机制。当屏幕顶部收到推送时只需要往下拉,就能看到快速操作界面,并不需要进入该应用才能操作。在锁屏界面,对于推送项目也可以快速处理。基本上就是让用户尽量在不离开当前页面的前提下处理推送信息,再次提高处理效率。能够进行直接互动的短信、邮件、日历、提醒,第三方应用,可以让你不用进入程序就能进行快捷操作,并专注于手中正在做的事情,用户可以做如下操作: 在通知横幅快速回复信息,不用进入短信程序; 可直接拒绝或接受邮件邀请; 可对提醒进行标记为完成或推迟...…

iOS继续阅读
更早的文章

iOS8中使用CoreLocation定位

在iOS8中,苹果已经强制开发者在请求定位服务时获得用户的授权,此外iOS状态栏中还有指示图标,提示用户当前应用是否正在使用定位服务。另外在iOS8中,苹果进一步改善了定位服务,让开发者请求定位服务时需要向用户提供更多的透明。此外,iOS8中还支持让应用开发者调用全新的“访问监控”功能,当用户允许后应用才能获得更多的定位数据。iOS8以前使用CoreLocation定位1、首先定义一个全局的变量用来记录CLLocationManager对象,引入CoreLocation.framework...…

iOS继续阅读