iOS學(xué)習(xí)筆記(三) 消息機(jī)制

這里有一篇介紹詳細(xì)的文章 objc io 中文版

各種消息機(jī)制使用場(chǎng)景

Target-Action

這是最典型的一種消息機(jī)制。最常見的情況就是,點(diǎn)擊 view 中 button時(shí),會(huì)觸發(fā) controller 中函數(shù)。

  • Target-Action 的一個(gè)限制是,Target-Action 的參數(shù)不能自定義,一般情況下參數(shù)為action的發(fā)送者。
  • Target-Action間為松耦合關(guān)系。recipient 在接受到消息前,并不知道sender是誰(shuí)(多個(gè)控件可以與同一個(gè)函數(shù)關(guān)聯(lián));sender 在發(fā)送前也不知 recipient 是誰(shuí)(若在父類中定義action,action將從子類傳到父類中響應(yīng)( responder chain ))。

delegate

delegate 在 iOS開發(fā)中經(jīng)常被用到,功能與使用類似于C中的回調(diào)函數(shù)。發(fā)送者需要知道接受者,接受者可以不知道發(fā)送者。最常見的情況就是 tableview 的使用:使用tableview的時(shí)候,設(shè)置 datasource 與 delegate,就相當(dāng)于tableview這個(gè)發(fā)送者知道接受者信息;此 tableview 的 controller 中也必須實(shí)現(xiàn)相關(guān) protocol 。

  • 使用delegate最大的好處,就是可以定義任何方法,可以根據(jù)需求來(lái)傳遞消息;發(fā)送者也可以通過(guò)接受者的返回值來(lái)作出響應(yīng)。

Block

Block 是 iOS 中,實(shí)現(xiàn)函數(shù)回調(diào)的第二種方法,第一種就是上面說(shuō)的 delegate 。Block可以代替delegate使用,即將一個(gè) Block 作為一個(gè) property 。

Block也有自己的要求。

  • Block中要避免產(chǎn)生 retain cycle 。
  • Block可以增強(qiáng)代碼大可讀性。多用在動(dòng)作完成的回調(diào)、錯(cuò)誤的回調(diào)等類似的事情。

Notification

這是經(jīng)典的生產(chǎn)者-發(fā)送者模型之一。 Notification 的一個(gè)優(yōu)點(diǎn)是,消息發(fā)送者與接受者不需要知道對(duì)方,可以在兩個(gè)互不相同的模塊中使用。

  • Notification 可以用來(lái)發(fā)送任何消息,可以將要發(fā)送的消息內(nèi)容放在 userinfo字典中。
  • Notification 的傳遞是單向的,不能回復(fù)通知。
    這里實(shí)現(xiàn)一個(gè)小 demo。主要功能是,在輸入框中輸入數(shù)字,當(dāng)輸入為5~10時(shí),在label中打印出輸入值。
//消息名稱
static  NSString *inputNotifciation = @"linw.test.notification";
- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [_inputField becomeFirstResponder];
//注冊(cè)消息接受者及調(diào)用函數(shù)
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNotif:) name:inputNotifciation object:nil];
}

- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidAppear:animated];
//移除消息觀察者
    [[NSNotificationCenter defaultCenter] removeObserver:self name:inputNotifciation object:nil];
}
//按鈕動(dòng)作
- (IBAction)sendButton:(UIButton *)sender
{
    NSInteger inputNum = _inputField.text.integerValue;
    if (inputNum >= 5 && inputNum < 10) {
        NSLog(@"post notification");
        [[NSNotificationCenter defaultCenter] postNotificationName:inputNotifciation object:self userInfo:@{@"Num" : [NSNumber numberWithInteger:inputNum]}];
    }
    else
    {
        _targetLabel.text = @"input is invaild";
    }
    
    _inputField.text = @"";
}
//收到消息后調(diào)用函數(shù)
- (void)receiveNotif:(NSNotification *)notif
{
    NSLog(@"receive notification");
    _targetLabel.text = [[NSString alloc] initWithFormat:@"Receive notification: %@", notif.userInfo[@"Num"]];
    [_inputField resignFirstResponder];
}
@end
初始狀態(tài)
輸入非法
輸入5~10

KVO

KVO是另外一種生產(chǎn)者-消費(fèi)者模式,當(dāng)一個(gè)對(duì)象值被改變時(shí),另一個(gè)對(duì)此對(duì)象感興趣的對(duì)象,將得到通知。實(shí)現(xiàn)原理,當(dāng)使用KVO時(shí),編譯器會(huì)自動(dòng)生成一個(gè)子類,子類中重寫方法,實(shí)現(xiàn)消息通知。

  • 消息接收者需要知道被觀察者。
  • 消息接收者也需要知道被觀察者生命周期。需要在被觀察者被 dealloc 前,注銷觀察者身份,不然會(huì)出現(xiàn)未預(yù)料的錯(cuò)誤。

以下是一個(gè)小demo。功能如下:當(dāng)按下 add 5按鈕時(shí),改變被觀察者值(price,每次加5),在消息通知函數(shù)中,改變 textfield 內(nèi)容顯示當(dāng)前 price。

#import "ViewController.h"

@interface ViewController ()

@property (weak, nonatomic) IBOutlet UITextField *priceText;
@property (nonatomic) float price;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    _priceText.text = @"15.00";
    //設(shè)置被觀察的屬性
    [self setValue:@"15.0" forKey:@"price"];
    //添加觀察者
    [self addObserver:self forKeyPath:@"price" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
    
}

//消息通知函數(shù)
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"price"])
    {
        NSLog(@"receive KVO notification");
        
        //_priceText.text = [[NSString alloc] initWithFormat:@"%f", ((NSNumber *)[self valueForKey:@"price"]).doubleValue];
        _priceText.text = [[NSString alloc] initWithFormat:@"%.2f", ((NSNumber *)change[NSKeyValueChangeNewKey]).floatValue];
    }
}

//add 5 button action
- (IBAction)addFiveStockPrice:(id)sender
{
    //[self setValue:@"20.0" forKey:@"price"];
    _price = _price + 5.00;
   [self setValue:[[NSString alloc] initWithFormat:@"%f", _price] forKey:@"price"];
}

- (void)dealloc
{
    [self removeObserver:self forKeyPath:@"price"];
}

@end

效果如下:

初始狀態(tài)
按下 add 5后,修改price值

以上是對(duì)iOS消息機(jī)制的一些理解。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 每個(gè)應(yīng)用程序或多或少,都由一些松耦合的對(duì)象構(gòu)成,這些對(duì)象彼此之間要想很好的完成任務(wù),就需要進(jìn)行消息傳遞。 本文將介...
    石丘閱讀 1,840評(píng)論 4 7
  • 每個(gè)應(yīng)用或多或少都由一些需要相互傳遞消息的對(duì)象結(jié)合起來(lái)以完成任務(wù)。在這篇文章里,我們將介紹所有可用的消息傳遞機(jī)制,...
    愛(ài)敲代碼的果果閱讀 4,300評(píng)論 0 2
  • *面試心聲:其實(shí)這些題本人都沒(méi)怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來(lái)就是把...
    Dove_iOS閱讀 27,653評(píng)論 30 472
  • 設(shè)計(jì)模式 1.delegate和notification什么區(qū)別,什么情況使用? 2.描述一下KVO和KVC。 K...
    丶逐漸閱讀 2,033評(píng)論 3 2
  • 白云在隨意游走 外面,陽(yáng)光明媚 小鳥在籠 嘰嘰喳喳,遠(yuǎn)方 誰(shuí)在翱翔 我在高樓 做,那體制的囚徒 虛無(wú)沒(méi)過(guò)靈魂 連青...
    桐萬(wàn)里閱讀 261評(píng)論 2 2

友情鏈接更多精彩內(nèi)容