消息
消息傳遞模型(Message Passing)是Objective-C語言的核心機制。在Objective-C中,沒有方法調用的說話,都是通過消息傳遞。在c++或java中調用某個類的方法,在Objective-C是給該類發送一個方法。在oc中,類與消息之間是松耦合的,方法調用隻是向某一個類發送一條消息,該類可以在運作時再确定怎麼處理接收到的消息。也就是說,一個類不保證一定會接收到的消息,如果接收到一個無法處理的消息,程式就會報一個錯。你可以向一個值為nil的空對象發送消息,程式也不會報錯。
Category
Category也稱之為類别,可以動态的為已存在的類添加方法,不需要去修改源代碼,也不用去建立自類,在原始類設計規模較小,功能後續增加時逐漸擴充。Category通過較為簡單的方式,把不同的類方法配置設定到到不同的類檔案當中。
下面通過例子來解釋,通過Category我們動态的為系統類NSString添加新的類方法,在項目中,為NSString建立類别util,在建立檔案的時候選擇Objective-C file
然後選擇file type 為category,class則為你要添加類别的那個類名稱,在這裡我們選擇NSString
#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。
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");
}
在這隻是粗略的溫習了一下消息,類别與協定,寫得不好,歡迎指正。