本章主要講解回調的概以及具有目標動作回調接口的組件如何使用。
回調,也叫事件觸發,在底層開發中也就服務或中斷服務。其產生過程較為復雜,所有我們再次不會展開講解。只是單純講解如果配置回調。
在使用一些較為復雜,或者和用戶有交互類型的組件時。我們通常需要根據組件觸發的事件來做出相應的響應。
比如我們使用一個開關控制一個燈。我們在編寫代碼的時候並不能准確的知道開關的狀態,也就無法確定燈的狀態。所有我們只能在開關狀態發送改變的時候,獲取開關的狀態且根據開關的狀態對燈的狀態進行改變。
這時候就需要開關有一個能反饋自身狀態的機制。這種機制便成為回調機制。
我們在編程中可以通過回調機制讓代碼在運行的過程中捕獲開關狀態的改變點,從而實現對燈的控制。
回調機制具體有三種表現形式:
下面我們展開講解目標-動作回調。
目標:接收事件反饋的對象。比如開關要反饋自身狀態,此時接收反饋信息的對象便成為目標。目標對象為id
類型,因在設計開關時,並不知道開關的使用者是什麼類型的對象。在代碼中通常用target
來表示目標對象。
動作:事件反饋所要觸發的方法。比如開關要反饋給我狀態改變的信息,在代碼中的具體表現形式為,通調用我的某個方法來進行告知。動作對象為SEL
類型。
SEL類型是OC語言為存儲方法名創造的變量類型。同時還創造了一個運算符,用於把一個方法名轉換成一個SEL值。
SEL test = @selector(方法名);
在編程中,如果我們想使用開關,並且要根據開關狀態的反饋做出不同的處理,那麼我們就需要設置開關的反饋目標和反饋動作。
能夠設置反饋目標和反饋動作的組件我們成為具有目標動作回調接口的組件。
在真實情況下,具有目標動作接口的組件都是復雜類組件。所有在本章講解中,使用虛擬的組件來進行OC語法上的學習。
首先我們來了解兩個虛擬的組件,開關和燈
燈的聲明文件
@interface Light : NSObject
-(void)turnOff;//開燈
-(void)turnOn;//關燈
@end
可見等的操作很簡單,只有開燈和關燈兩個方法。
開關的聲明文件
typedef enum : NSUInteger {
SwitchStateOff,//default
SwitchStateOn,
} SwitchState;
@interface Switch : NSObject
@property(nonatomic,assign,readonly)SwitchState currentState;
-(void)addChangeStateTarget:(id)target Action:(SEL)action;
@end
開關有一個只讀屬性,為當前開關的狀態,其狀態變量為枚舉類型
開關還有一個addChangeStateTarget方法,通過該方法為這個開關設置反饋對象和反饋動作,以實現讓反饋對象受到開關狀態的改變信息。
下面我們假設有一個房間,房間中有一個開關和一個燈。代碼實現如下:
@interface Room : NSObject
@end
@interface Room ()
@property(nonatomic,strong) Light * aLight;
@property(nonatomic,strong) Switch * aSwitch;
-(void)changeState:(Switch *)s;
@end
@implementation Room
- (instancetype)init
{
self = [super init];
if (self)
{
self.aLight = [[Light alloc] init];
self.aSwitch = [[Switch alloc] init];
//設置反饋對象和反饋方法
[self.aSwitch addChangeStateTarget:self Action:@selector(changeState:)];
}
return self;
}
-(void)changeState:(Switch *)s
{
if (self.sw.state == SwitchStateOff)
{
[self.light turnOn];
}
else
{
[self.light turnOff];
}
}
@end
上段代碼中我們依次做了如下事情
這樣當代碼開始運行,開關狀態被用戶改變之後,燈的狀態也會隨之改變。當然,這段代碼是虛擬的。在之後章節中我們會接觸到可以真正運行的代碼。還需要同學們努力學習。