消息传递模型(Message Passing)是Objective-C语言的核心机制。在Objective-C中,没有方法调用的说话,都是通过消息传递。在c++或java中调用某个类的方法,在Objective-C是给该类发送一个方法。在oc中,类与消息之间是松耦合的,方法调用只是向某一个类发送一条消息,该类可以在运行时再确定怎么处理接收到的消息。也就是说,一个类不保证一定会接收到的消息,如果接收到一个无法处理的消息,程序就会报一个错。你可以向一个值为nil的空对象发送消息,程序也不会报错。
Category也称之为类别,可以动态的为已存在的类添加方法,不需要去修改源代码,也不用去创建自类,在原始类设计规模较小,功能后续增加时逐步扩展。Category通过较为简单的方式,把不同的类方法分配到到不同的类文件当中。
下面通过例子来解释,通过Category我们动态的为系统类NSString添加新的类方法,在项目中,为NSString新建类别util,在创建文件的时候选择Objective-C file
然后选择file type 为category,class则为你要添加类别的那个类名称,在这里我们选择NSString
#import
@interface NSString (util)
- (BOOL)isString;
- (NSString *)stringByAppendingString1:(NSString *)aString;
@end
#import "NSString+util.h"
@implementation NSString (util)
- (BOOL)isString{
return NO;
}
- (NSString *)stringByAppendingString1:(NSString *)aString{
return @"10086";
}
@end
我们在类别的.h文件中为NSString新建两个类方法isString和stringByAppendingString1,然后在.m文件中实现自己想要的结果,然后以后在这个类的使用中就可以直接调用这两个方法:
NSString *str = @"12";
str = [str stringByAppendingString1:@"111"];
BOOL a = [str isString];
然后就可以得到结果,str=@”10086”,BOOL a = NO。
Category的使用场景:
1、当你在定义类的时候,在某些情况下(例如需求变更),你可能想要为其中的某个或几个类中添加方法。
2、一个类中包含了许多不同的方法需要实现,而这些方法需要不同团队的成员实现
3、当你在使用基础类库中的类时,你可能希望这些类实现一些你需要的方法。
遇到以上这些需求,Category可以帮助你解决问题。当然,使用Category也有些问题需要注意,
1、Category可以访问原始类的实例变量,但不能添加变量,如果想添加变量,可以考虑通过继承创建子类。
2、Category可以重载原始类的方法,但不推荐这么做,这么做的后果是你再也不能访问原来的方法。如果确实要重载,正确的选择是创建子类。
3、和普通接口有所区别的是,在分类的实现文件中可以不必实现所有声明的方法,只要你不去调用它。
protocal简单来说,就是不属于任何类的方法列表,但其声明的方法可以被任何类所使用,这种模式我们常称之为代理模式。定义protocol其实很简单,我们在申明文件.h中通过关键字protocol来定义,给出protocol的名称,然后再给出protocol的实现方法,实现方法中,必须实现的用@required修饰,不必须实现的用@optional修饰。
#import
@protocol ProtocolDelegate <NSObject>
// 必须实现的方法
@required
- (void)error;
// 可选实现的方法
@optional
- (void)other;
- (void)other2;
- (void)other3;
@end
然后在需要代理的类中设置代理人
#import
#import "ProtocolDelegate.h"
@interface ViewControllerB : UIViewController
// 委托代理人,代理一般需使用弱引用(weak)
@property (weak, nonatomic) id delegate1;
@end
最后需要在实现文件中实现这个代理方法
- (void)viewDidLoad {
{
[super viewDidLoad];
if ([_delegate1 respondsToSelector:@selector(error)]) { // 如果协议响应了error方法
[_delegate1 error];
}
}
现在协议已经生成,我们只要在需要调用的地方设置好代理,就和tableview中delegate一样的实现该代理方法了
#import "ViewController.h"
#import "ProtocolDelegate.h"
#import "ViewControllerB.h"
@interface ViewController () <ProtocolDelegate, ViewControllerBDelegate>
@end
@implementation ViewController
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
ViewControllerB *vc = segue.destinationViewController;
[vc setDelegate1:self];
}
// 这里实现B控制器的协议方法
- (void)error
{
NSLog(@"1");
}
在这只是粗略的温习了一下消息,类别与协议,写得不好,欢迎指正。