天天看點

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");
}
           

在這隻是粗略的溫習了一下消息,類别與協定,寫得不好,歡迎指正。