iOS开发深度好文iOS开发首页投稿(暂停使用,暂停投稿)

分类和扩展的使用

2017-07-31  本文已影响21人  小白进城

一、类扩展

格式:

@interface 类名()
//属性
//方法
@end

说明:

1、类扩展可以为某一个类添加额外的属性,成员变量,方法等,并且都是该类的私有项

2、类扩展一般都是在.m文件中,在类实现的上方,比如在我们新建UIController时,系统已经为我们写好了类扩展,再其他文件中,如UIView里,我们也可以手写上述格式来使用类扩展

3、通过新建类扩展文件来使用类扩展,但是子类是不能使用父类类扩展成员,因为是父类私有的


二、分类/类别

格式:

@interface 类名(分类名字)
/*方法声明*/
@end
@implementation类名(分类名字)
/*方法实现*/
@end

说明:

1、类别用来为已有的类(通常是系统的类)添加新方法

2、类别一般只扩充方法,不能新增属性和成员变量


三、分类/类别的应用场景

a、扩展系统类方法

这是我们经常使用分类的情形,分类的好处就是在不新建类的情况下,可以通过扩展系统类方法来实现某种功能,例如分类NSString,将日期转换为字符串类型

.h 文件

/**
 日期转成字符串
 @param date 日期
 @param format 格式
 @return 日期字符串
 */
+(NSString*)dateToString:(NSDate*)date format:(NSString *)format;

.m 文件

+(NSString*)dateToString:(NSDate*)date format:(NSString *)format{
    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat:format];
    NSString *dateString = [dateFormat stringFromDate:date];
    return dateString;
}

这样我们就可以直接通过NSString类来调用日期转字符串方法了:

分类来新增方法

b、方法工厂

有时候,我们手写初始化代码时,要写控件的很多样式,通过分类,我们可以快速完成控件初始化。这种方式依旧是新增方法,我们通过给UIButton新增方法来说明:

/**
 *  普通的按钮样式
 */
+(UIButton*)buttonNormalWithTitle:(NSString*)title
                           target:(id)target
                         selector:(SEL)selector
                            frame:(CGRect)frame
                            bgImage:(UIImage*)bgImage
                     imagePressed:(UIImage*)imagePressed
                        textColor:(UIColor*)aColor
                         textFont:(UIFont*)textFont;

这样,我们就可以在初始化时,调用该法类快速完成一个按钮的初始化了,是不是很方便呢?


c、新增属性

一般来说,分类里是不能添加属性的,即使新增里属性,也不会自动生成setter和getter方法,但是OC的特点之一就是动态运行时,我们可以根据这一特性来关联实现setter和getter方法,以达到新增属性的功能

这里我们给UIViewController新增属性为例:

1)、新建UIViewController的分类

新建分类

2)、新增属性

@interface UIViewController (Based)
@property (copy ,nonatomic) NSString *name;
@end

3)、使用运行时完成setter和getter方法

#import <objc/runtime.h>
@implementation UIViewController (Based)
-(void)setName:(NSString *)name{
    objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
-(NSString *)name{
    return objc_getAssociatedObject(self, _cmd);
}
@end

4)、导入文件,使用

self.name = @"LOLITA";
NSLog(@"%@",self.name);

5)、运行结果


运行结果

这里,可能有人会问了,我可以直接在Controller里新增这个属性啊?使用分类做会不会多次一举呢?当然不是,有没有遇到过这样的情况呢?在维护别人的代码时,想针对共用的属性、方法、控件等做统一的管理,但是项目中又没有使用继承,新建一个基础类成本又太大,那么使用分类是你比较好的选择


为何是使用UIViewController来举例呢?笔者在维护别人的代码时,就遇到的上述头疼的问题,就采用来分类来优化项目,将通用部分统统放到了分类中去,并使用懒加载的方式,到了需要的时候才会申请空间,并大大减少了代码量,提高了复用性。

共用的部分通常包括:指示器Loading控件,导航栏视图、自定义返回手势、检查更新、获取网络状态、权限提示框、请求类等等,将这些放到分类中,大大减少了重复造轮子的问题,并且不像继承那样具有依赖性


补充:新增控件

@property (strong, nonatomic) NavigationView *navigationBar;
-(NavigationView *)navigationBar{
    NavigationView *navBar = objc_getAssociatedObject(self, _cmd);
    if (navBar==nil) {
        navBar = [[NavigationView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 64)];
        objc_setAssociatedObject(self, @selector(navigationBar), navBar, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        navBar.backgroundColor = RiseColor;
        navBar.delegate = self;
        [self.view addSubview:navBar];
    }
    return navBar;
}
-(void)setNavigationBar:(NavigationView *)navigationBar{
    objc_setAssociatedObject(self, @selector(navigationBar), navigationBar, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

四、体会

1、合理的使用分类可以很好的简化代码

2、如果有不正确的地方,或者有其他分类的使用,欢迎留言交流

3、针对笔者的问题,如果有更好的解决办法,也欢迎留言交流,谢谢

上一篇下一篇

猜你喜欢

热点阅读