类别的扩展

类别的扩展 续


利用类别分散实现代码

  • 在大型的项目中,一个类的实现可能很大,而且 .m 文件不能分离.可是使用类别能够将一个类的实现分散且有规律的组织在不同的文件里.还能够将一个类的实现分散到不同的框架中.
  • 编程人员能够更加easy阅读代码并实现多人合作编码
  • 版本号管理减少冲突
  • 维护人员跟easy理解代码

在代码的头文件里,假如有例如以下这么多的成员变量,也就须要对应的 setter, 和 getter 方法

#import <Foundation/Foundation.h>

@interface Things : NSObject
{
    NSUInteger thing1;
    NSUInteger thing2;
    NSUInteger thing3;
    NSUInteger thing4;
    NSUInteger thing5;
}

- (void)resetAllValue;
- (void)print;

- (void)setThing1:(NSUInteger)thing1;
- (NSUInteger)thing1;

- (void)setThing2:(NSUInteger)thing2;
- (NSUInteger)thing2;

- (void)setThing3:(NSUInteger)thing3;
- (NSUInteger)thing3;

- (void)setThing4:(NSUInteger)thing4;
- (NSUInteger)thing4;

- (void)setThing5:(NSUInteger)thing5;
- (NSUInteger)thing5;

@end

这样对应的. m 文件就会繁琐到不行,这才是5个变量,假如是100个,须要很多人来完毕,总不能让每一个人都拿着核心文件吧,于是把它们分散开很有必要,而类别给我们提供了一种这种机制,仅仅须要一个总的实现文件 .m,然后把当中部分方法分散到其类别文件里去实现.例如以下, 头文件Things.h文件要改动代码例如以下:

@interface Things : NSObject
{
    NSUInteger thing1;
    NSUInteger thing2;
    NSUInteger thing3;
    NSUInteger thing4;
    NSUInteger thing5;
}

- (void)resetAllValue;
- (void)print;
//类的扩展例如以下
@interface Things (thing1)
- (void)setThing1:(NSUInteger)thing1;
- (NSUInteger)thing1;
@end

@interface Things (thing2)

- (void)setThing2:(NSUInteger)thing2;
- (NSUInteger)thing2;
@end

@interface Things (thing3)

- (void)setThing3:(NSUInteger)thing3;
- (NSUInteger)thing3;
@end

@interface Things (thing4)
- (void)setThing4:(NSUInteger)thing4;
- (NSUInteger)thing4;
@end

@interface Things (thing5)

- (void)setThing5:(NSUInteger)thing5;
- (NSUInteger)thing5;
@end

实现文件 Things.m 的内容仅仅须要核心的方法,其余让其扩展类别去做:

#import "Things.h"

@implementation Things

- (void)print
{
    NSLog(@"%ld,%ld,%ld,%ld,%ld",self.thing1,self.thing2,self.thing3,self.thing4,self.thing5);
}

- (void)resetAllValue
{
    self.thing1 = 100;
    self.thing2 = 200;
}

@end

其余详细实现,即须要好多人做的部分,给他们分开,以下举一个 Things+Thing1.m 文件

#import "Things.h"

@implementation Things (Thing1)

- (void)setThing1:(NSUInteger)t
{
    thing1 = t;

}

- (NSUInteger)thing1
{
    return thing1;
}

@end

通过类别创建前向引用和方法声明


  • Cocoa 没有真正的私有方法,可是假设你知道对象支持的某个方法的名称,就算是该对象所在的了类的接口中没有声明这种方法,也能够调用它.由于能够使用类别告诉编译器此方法已经声明过了.
  • 越狱项目中常用类别的这个功能,完毕调用私有 API.

响应选择器


  • 所谓响应选择器,能够理解为方法的类型.
  • 响应选择器也是 Objective-C 运行时的特性.
  • 能够通过选择器来推断一个对象能否够运行某一个方法或者说測试一个对象能否响应指定的消息.
  • 响应选择器既然能够理解为方法或者说消息的类型所以它能够作为方法的參数传递使用.也能够作为实例变量被储存,很灵活.
  • 使用@ selector() 编译器指令来指定选择器,圆括号中是详细的方法名.如:
@selector(setEngine:)
@selector(setTire:atIndex)
  • 选择器的类型关键字: SEL
  • (BOOL)respondsToSelector:(SEL)aSelector;// 使用此方法能够推断某一对象能否够运行指定的方法.
    举例代码:
        QYCar *car = [[Car alloc] init];
        if([car respondsToSelector:@selector(setEngine:)]){
            NSLog(@"hihi");
         }

托付和非正式协议


  • 所谓托付,事实上就是一个对象有还有一个对象请求运行某些操作的技术实现.
  • 所谓非正式协议,事实上就是创建一个 NSObject 的类别.

以下,我就用一个简单的样例来实现非正式协议实现托付
第一步,创建名 QYXiaoMing的类继承自NSObject 类,在创建一个 QYXiaoHong 的类,来实现一个这种功能:
小明学习累了,想让小红在他睡着后某段时间后再把他叫起来,这时候小红叫小明这个动作就是一个托付 .详细代码例如以下:

QYXiaoMing.h 的内容

#import <Foundation/Foundation.h>

@interface QYXiaoMing : NSObject

//小明学习累了,有学习的行为
- (void)startSleep:(NSUInteger) time;

@end//QYXiaoMing.h

QYXiaoMing.m 的内容

#import "QYXiaoMing.h"
#import "QYXiaoHong.h"
@implementation QYXiaoMing

- (void)startSleep:(NSUInteger)time
{
    NSLog(@"Sleep...");
    QYXiaoHong *xiaohong = [[QYXiaoHong alloc] init];
    [xiaohong call:time];
}

@end//QYXiaoMing.m

头文件QYXiaoHong.h

#import <Foundation/Foundation.h>

@interface QYXiaoHong : NSObject

- (void)call:(NSUInteger)time;

@end//QYXiaoHong.h

详细实现QYXiaoHong.m

#import "QYXiaoHong.h"

@implementation QYXiaoHong

- (void)call:(NSUInteger)time
{
    //须要在指定的时间里把小明叫起来(计时器的使用方法)
    [NSTimer  scheduledTimerWithTimeInterval:time target:self selector:@selector(callXiaoMing) userInfo:nil repeats:NO];
}

@end //QYXiaoHong.m

类别头文件NSObject+CallXiaoMing.h

 #import <Foundation/Foundation.h>

@interface NSObject (CallXiaoMing)

- (void)callXiaoMing;

@end

类别实现文件NSObject+CallXiaoMing.m

#import "NSObject+CallXiaoMing.h"

@implementation NSObject (CallXiaoMing)

- (void)callXiaoMing
{
    NSLog(@"lalala,don't sleep!");
}
@end

main.m 的代码

#import <Foundation/Foundation.h>

#import "QYXiaoMing.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        QYXiaoMing *xiaoming = [[QYXiaoMing alloc] init];
        [xiaoming startSleep:5];//5是5秒


        //要求程序运行到这里,不能结束, 是为了让显示的时间循环显示下
        [[NSRunLoop currentRunLoop] run];
    }
    return 0;
}//main.m