Objective-C 回調Callbacks 中目標-動作對、輔助對象、通知簡單使用

回調:將一段可執行的代碼和一個特定的事件綁定起來當特定的事情發生時就會執行這段代碼

運行循環runloop:事件驅動的程序需要有一個對象,專門負責等待事件的發生,NSRunLoop類的實例會持續等待,當特定的事件發生時,就會向相應的對象發送消息。它會在特定的事件發生時觸發回調。

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        [[NSRunLoop currentRunLoop] run];
    }
    return 0;
}

一、目標動作對

程序開始等待前,要求當事件發生時向指定的對象發送某個特定的消息,接收消息的對象是目標target,消息的選擇器selector是動作action。

創建計時器,設定延遲,目標和動作。指定時間後,計時器會向設定好的目標發送指定的消息。這裏我們創建一個WKLLogger類,並將其設置爲被NSTimer對象發送消息的目標。每隔兩秒發送一次。

@selector語句來傳遞動作消息的名稱給相應的方法,這就需要傳遞相應的實參,不能值傳遞方法的名字

//.h
@interface WKLLogger : NSObject
@property(nonatomic) NSDate *lastTime;
-(NSString *)lastTimeString;
-(void)updateLastTime:(NSTimer *)t;
@end
//.m
@implementation WKLLogger
- (NSString *)lastTimeString{
    static NSDateFormatter *dateFormatter = nil;
    if (!dateFormatter) {
        dateFormatter = [[NSDateFormatter alloc] init];
        [dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
        [dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
        NSLog(@"create dateFormatter");
                         
    }
    return [dateFormatter stringFromDate:self.lastTime];
}
- (void)updateLastTime:(NSTimer *)t{
    NSDate *now =[NSDate date];
    [self setLastTime:now];
    NSLog(@"Just set time to %@",self.lastTimeString);
}
@end
//main.m
#import <Foundation/Foundation.h>
#import "WKLLogger.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        WKLLogger *logger = [[WKLLogger alloc] init];
        NSTimer *timer=[NSTimer scheduledTimerWithTimeInterval:2.0 target:logger selector:@selector(updateLastTime:) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] run];
    }
    return 0;
}
/*
2019-10-21 20:42:23.727667+0800 OC6[57413:8762046] create dateFormatter
2019-10-21 20:42:23.738714+0800 OC6[57413:8762046] Just set time to 下午8:42:23
2019-10-21 20:42:25.727780+0800 OC6[57413:8762046] Just set time to 下午8:42:25
2019-10-21 20:42:27.727692+0800 OC6[57413:8762046] Just set time to 下午8:42:27
*/

在runloop中需要手動終止程序

二、輔助對象

程序開始等待前,要求當事件發生時向遵守相應協議的輔助對象發送消息

需要在對象實現中,聲明協議,實現協議方法。

@interface WKLLogger : NSObject
    <NSURLConnectionDelegate, NSURLConnectionDataDelegate>
{
    NSMutableData * _incomingData;
}
@end
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
    NSLog(@"receive %lu bytes",[data length]);
    if (!_incomingData) {
        _incomingData = [[NSMutableData alloc] init];
    }
    [_incomingData appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
    NSLog(@"Got it all");
    NSString *string = [[NSString alloc] initWithData:_incomingData encoding:NSUTF8StringEncoding];
    _incomingData = nil;
    NSLog(@"string has %lu characters",[string length]);
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
    NSLog(@"connect failed:%@",[error localizedDescription]);
}
//main
NSURL *url = [NSURL URLWithString:@"https://www.baidu.com/img/bd_logo1.png"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
__unused NSURLConnection *fetchConn = [[NSURLConnection alloc] initWithRequest:request delegate:logger startImmediately:YES];
[[NSRunLoop currentRunLoop] run];

當前回調規則爲:當想要向一個對象發送多個回調的時候,apple會使用符合相應協議的輔助對象,根據用途,輔助對象常被稱爲對象和數據源。

三、通知

Apple提供了通知中心Notification center對象。在程序開始等待前,告訴通知中心,某個對象正在等待某些特定的通知,當其中某個通知出現的時候,向指定的對象發送特定消息。當事件發生時,相關的對象會向通知中心發佈通知,然後再由通知中心將通知轉發給正在等待該通知的對象

當Mac中某些系統設置被更改時,程序中很多對象需要知道系統發生的這一變化,這些對象都可以通過通知中心將自己註冊爲觀察者observer

當系統時區設置發生變化時,會向通知中心發佈NSSystemTimeZoneDidChangeNotification通知,然後通知中心會將通知轉發給相應觀察者。將Logger實力註冊爲觀察者。在系統時區變化時可以收到相應的通知

- (void)zoneChange:(NSNotification *)note{
    NSLog(@"system zone changed!");
}
#import <Foundation/Foundation.h>
#import "WKLLogger.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        [[NSNotificationCenter defaultCenter] addObserver:logger                     
        selector:@selector(zoneChange:) name:NSSystemTimeZoneDidChangeNotification object:nil];
        [[NSRunLoop currentRunLoop] run];
    }
    return 0;
}

/*
2019-10-21 21:00:23.754958+0800 OC6[57497:8776939] system zone changed!
2019-10-21 14:00:25.537425+0100 OC6[57497:8776939] system zone changed!
*/

注意!

當某個對象註冊爲觀察者,那麼應該在釋放該對象時將其移出通知中心

- (void)dealloc{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

某個新創建的對象是另一個對象的委託對象或數據源對象,那麼該對象應該在其dealloc方法中取消相應的關聯

  • setDelegate:nil
  • setDataSource:nil

某個新創建的對象是另一個對象的目標,那麼該對象應該在其delloc方法中將相應的目標指針賦值爲nil

  • setTarget:nil

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章