溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

iOS設(shè)計(jì)模式之KVO

發(fā)布時(shí)間:2020-07-17 22:39:08 來(lái)源:網(wǎng)絡(luò) 閱讀:356 作者:ymanmeng123 欄目:移動(dòng)開(kāi)發(fā)
  • 觀察者設(shè)計(jì)模式

KVO也叫 “發(fā)布--訂閱”模式,很像雜志的訂閱。

     讀者把名字和郵寄地址提供給發(fā)行商

     發(fā)行商在發(fā)行新一期的的雜志時(shí),就能將雜志送到每一個(gè)讀者手中


原理:

     訂閱者注冊(cè)成為發(fā)布者的某一屬性的觀察者

     當(dāng)發(fā)布者的這一屬性發(fā)生變化時(shí),所有的觀察者都會(huì)得知該屬性的變化

     KVC(鍵值編碼)是實(shí)現(xiàn)KVO的基礎(chǔ)

與代理的功能類似,用來(lái)實(shí)現(xiàn):對(duì)象間傳遞事件、數(shù)值,但不能為自身屬性賦值


  • 觀察者設(shè)計(jì)的使用步驟

1)發(fā)布者添加屬性

    如一個(gè)Person類,添加屬性age

@interface AMPerson : NSObject
@property (nonatomic, strong) NSNumber* age;
@end

2)注冊(cè)成為訂閱者

    發(fā)布者調(diào)用addObserver:forKeyPath:options:context:方法,注冊(cè)其指定屬性的訂閱者

- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context

    如控制器創(chuàng)建一個(gè)Person對(duì)象,并成為其訂閱者

self.person = [[AMPerson alloc] init];
self.person.age = @10;
[self.person addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew context:nil];

3)訂閱者實(shí)現(xiàn)observeValueForKeyPath:ofObject:change:context:方法

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context

     如:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
    if ( [keyPath isEqualToString:@"age"] ) {
        NSLog(@"%@", change);
    }
}

4)發(fā)布者的屬性發(fā)生變化時(shí)訂閱者會(huì)響應(yīng)

    響應(yīng)方法即發(fā)布者的observeValueForKeyPath:ofObject:change:context:方法

    注意:必須使用KVC的賦值方式訂閱者才會(huì)響應(yīng)

    如:

NSInteger age = self.person.age.integerValue+1;
[self.person setValue:@(age) forKey:@"age"];

5)訂閱者銷毀前將注冊(cè)信息刪除

     發(fā)布者使用removeObserver:forKeyPath:方法刪除指定的訂閱者

- (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath

    如:

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



  • 通知機(jī)制

通知機(jī)制是基于觀察者設(shè)計(jì)模式實(shí)現(xiàn)一種對(duì)象間的通信技術(shù)。

     雖然Objective-C的對(duì)象支持直接使用觀察者設(shè)計(jì)模式開(kāi)發(fā),但通知機(jī)制的使用過(guò)程更加簡(jiǎn)單

     通知中心是一種多對(duì)多的通信方式,而觀察者僅僅是一對(duì)多的通信方式

    iOS設(shè)計(jì)模式之KVO


通知中心:

     每個(gè)應(yīng)用程序都有一個(gè)實(shí)現(xiàn)通知機(jī)制的實(shí)例,稱作通知中心(NSNotificationCenter)

     獲得其單例對(duì)象:

+ (NSNotificationCenter *)defaultCenter

     通知中心還包含添加、刪除通知關(guān)系的方法


通知的發(fā)布者:

     任何對(duì)象都可以向通知中心發(fā)布消息


通知的接受者:(響應(yīng)者)

     任何對(duì)象都可以在通知中心注冊(cè)所關(guān)心的消息,并在關(guān)系消息被發(fā)布時(shí)收到  


通知對(duì)象(NSNotification)主要包含以下三個(gè)屬性:

@property(readonly, copy) NSString *name   //通知名
@property(readonly, retain) id object  //通知的發(fā)布者
@property(readonly, copy) NSDictionary *userInfo  //通知中可以攜帶的數(shù)據(jù)


  • 通知的使用過(guò)程

1)起一個(gè)通知的名字

    一般在發(fā)布者源文件中定義并在頭文件中聲明

//AMAppView.h
extern NSString * const AMAppViewNameBtnClickedNotification;
//AMAppView.m
NSString * const AMAppViewNameBtnClickedNotification = @"AMAppViewNameBtnClickedNotification";

2)通知發(fā)布者通過(guò)通知中心發(fā)布通知

    通知中心使用postNotification方法發(fā)布通知

- (void)postNotification:(NSNotification *)notification
- (void)postNotificationName:(NSString *)notificationName object:(id)notificationSender
- (void)postNotificationName:(NSString *)notificationName object:(id)notificationSender userInfo:(NSDictionary *)userInfo

    如:

[[NSNotificationCenter defaultCenter] postNotificationName:AMAppViewNameBtnClickedNotification object:self userInfo:@{@"appModel":self.appModel}];

3)通知接收者通過(guò)通知中心注冊(cè)想要接收的通知

    使用通知中心的addObserver方法

- (void)addObserver:(id)notificationObserver selector:(SEL)notificationSelectorname:(NSString *)notificationName object:(id)notificationSender
- (id<NSObject>)addObserverForName:(NSString *)name object:(id)obj queue:(NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block

    如:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appViewNameBtnClicked:) name:AMAppViewNameBtnClickedNotification object:v];

4)通知接收者實(shí)現(xiàn)通知的響應(yīng)方法或block

- (void) appViewNameBtnClicked:(NSNotification*) notification
{
    NSLog(@"%@", notification.name);
    NSLog(@"%@", notification.object);
    NSLog(@"%@", notification.userInfo);
}

5)通知接收者在被銷毀或者不再想接收通知時(shí),從通知中心移除

    使用通知中心的removeObserver方法

- (void)removeObserver:(id)notificationObserver
- (void)removeObserver:(id)notificationObserver name:(NSString *)notificationNameobject:(id)notificationSender

    一般放在接受者的dealloc方法中調(diào)用,如:

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


使用場(chǎng)景的區(qū)別:

     代理設(shè)計(jì)模式:一對(duì)一的關(guān)系   對(duì)象間關(guān)系相對(duì)比較緊密

     觀察者設(shè)計(jì)模式:一對(duì)多的關(guān)系

     通知機(jī)制:多對(duì)多的關(guān)系









向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI