天天看点

iOS------消息、Category和protocol

消息

消息传递模型(Message Passing)是Objective-C语言的核心机制。在Objective-C中,没有方法调用的说话,都是通过消息传递。在c++或java中调用某个类的方法,在Objective-C是给该类发送一个方法。在oc中,类与消息之间是松耦合的,方法调用只是向某一个类发送一条消息,该类可以在运行时再确定怎么处理接收到的消息。也就是说,一个类不保证一定会接收到的消息,如果接收到一个无法处理的消息,程序就会报一个错。你可以向一个值为nil的空对象发送消息,程序也不会报错。

Category

Category也称之为类别,可以动态的为已存在的类添加方法,不需要去修改源代码,也不用去创建自类,在原始类设计规模较小,功能后续增加时逐步扩展。Category通过较为简单的方式,把不同的类方法分配到到不同的类文件当中。

下面通过例子来解释,通过Category我们动态的为系统类NSString添加新的类方法,在项目中,为NSString新建类别util,在创建文件的时候选择Objective-C file

iOS------消息、Category和protocol

然后选择file type 为category,class则为你要添加类别的那个类名称,在这里我们选择NSString

iOS------消息、Category和protocol
#import <Foundation/Foundation.h>

@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。

iOS------消息、Category和protocol

Category的使用场景:

1、当你在定义类的时候,在某些情况下(例如需求变更),你可能想要为其中的某个或几个类中添加方法。

2、一个类中包含了许多不同的方法需要实现,而这些方法需要不同团队的成员实现

3、当你在使用基础类库中的类时,你可能希望这些类实现一些你需要的方法。

遇到以上这些需求,Category可以帮助你解决问题。当然,使用Category也有些问题需要注意,

1、Category可以访问原始类的实例变量,但不能添加变量,如果想添加变量,可以考虑通过继承创建子类。

2、Category可以重载原始类的方法,但不推荐这么做,这么做的后果是你再也不能访问原来的方法。如果确实要重载,正确的选择是创建子类。

3、和普通接口有所区别的是,在分类的实现文件中可以不必实现所有声明的方法,只要你不去调用它。

protocol

protocal简单来说,就是不属于任何类的方法列表,但其声明的方法可以被任何类所使用,这种模式我们常称之为代理模式。定义protocol其实很简单,我们在申明文件.h中通过关键字protocol来定义,给出protocol的名称,然后再给出protocol的实现方法,实现方法中,必须实现的用@required修饰,不必须实现的用@optional修饰。

#import <Foundation/Foundation.h>

@protocol ProtocolDelegate <NSObject>

// 必须实现的方法
@required
- (void)error;

// 可选实现的方法
@optional
- (void)other;
- (void)other2;
- (void)other3;

@end
           

然后在需要代理的类中设置代理人

#import <UIKit/UIKit.h>
#import "ProtocolDelegate.h"

@interface ViewControllerB : UIViewController

// 委托代理人,代理一般需使用弱引用(weak)
@property (weak, nonatomic) id<ProtocolDelegate> 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");
}
           

在这只是粗略的温习了一下消息,类别与协议,写得不好,欢迎指正。