你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> 設計模式深入學習IOS版(7)觀察者模式

設計模式深入學習IOS版(7)觀察者模式

編輯:IOS開發綜合

1 前言

觀察者(Observer)模式也叫發布/訂閱(Publish/Subscribe)模式,是MVC(模型-視圖-控制器)模式的重要組成部分。在IOS的Cocoa Touch裡面也有的廣泛的應用,今天我們就來學習一下這個模式。

轉載請注明出處:http://blog.csdn.net/developer_zhang

2 詳述

該模式使用來解決一個對象狀態改變連帶影響到其他對象的狀態發生改變的情景的。而且復用性強,可以做到對象之間匿名通信。

2.1 實現原理

觀察者模式的類圖如下:

\

圖中4個角色:

抽象主題(Subject):在Object-C中,抽象主題是一個協議,它是一個觀察者集合容器,定義了增加觀察者(attach)方法,移除觀察者(detach)方法和為所有觀察者發送通知的方法(notifyObserver)。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+vt/M5db3zOKjulN1YmplY3TQrdLptcS+38zlyrXP1qGjPC9wPgo8cD6z6c/zuduy7NXfo6hPYnNlcnZlcqOpo7qz6c/zuduy7NXfysfSu7j20K3S6aOsy/vKx9K7uPa4/NDCo6h1cGRhdGWjqbe9t6ihozwvcD4KPHA+vt/M5bnbsuzV36OoQ29uY3JldGVPYnNlcnZlcqOpo7pPYnNlcnZlcrXEvt/M5cq1z9ahozwvcD4KPHA+0v3I68HLU3ViamVjdLrNT2JzZXJ2ZXLV4sG9uPbQrdLpuvOjrLK7vfbM4bjfwcvPtc2ztcS/ybi008PQ1KOsu7m9tbXNwcvx7rrPtsihozwvcD4KPHA+tPrC68q1z9ajujwvcD4KPHA+s+nP89b3zOLQrdLpo7o8YnI+CjwvcD4KPHA+PC9wPgo8cCBjbGFzcz0="p1">

#import 
@class Observer;

/*!
 *  抽象主題協議
 *
 *  @since V1.0
 */
@protocol Subject 

@required

/*!
 *  增加觀察者
 *
 *  @param observer 觀察者實例
 *
 *  @since V1.0
 */
-(void)attach:(Observer*) observer;
/*!
 *  移除觀察者
 *
 *  @param observer 觀察者實例
 *
 *  @since V1.0
 */
-(void)detach:(Observer*) observer;
/*!
 *  為觀察者發送通知
 *
 *  @since V1.0
 */
-(void)notifyObservers;

@end


觀察者協議:

#import 

/*!
 *  觀察者協議
 *
 *  @since V1.0
 */
@protocol Observer 

@required
-(void)update;

@end


具體的觀察者類:

#import 
#import "Observer.h"

/*!
 *  具體的觀察者類
 *
 *  @since V1.0
 */

@interface ConcreteObserver : NSObject

@end


具體主題類:

#import 
#import "Subject.h"

/*!
 *  具體主題類
 *
 *  @since V1.0
 */
@interface ConcreteSubject : NSObject
{
    NSMutableArray *observers;
}
@property(nonatomic,strong)NSMutableArray* observers;
/*!
 *  單例構建自身對象
 *
 *  @return 自身對象
 *
 *  @since V1.0
 */
+(ConcreteSubject*)shareConcreteSubject;

@end


2.2 Cocoa Touch中的觀察者模式的應用(通知機制和KVO)

通知機制與委托機制不同的是,前者是“一對多”的對象之間的通信,後者是“一對一”的對象之間的通信。

2.2.1 通知機制

IOS中,通知分為廣播通知(broadcast notification),本地通知(localnotification)和推送通知(push notification),本節主要介紹的廣播通知。它是Cocoa Touch框架中實現觀察者模式的一種機制,它可以在一個應用內部的多個對象之間發送消息;本地通知和推送通知中的“通知”是給用戶一種“提示”。

如圖:

\

通知機制中對某個感興趣的所有對象都可以成為接受者。首先,需要對象向通知中心(NSNotificationCenter)發出addObserver:selector:name:object:消息進行注冊,在投送對象投送通知給消息中心時,通知中心會把通知廣播給注冊過的接收者。所有的接收者都不知道是誰投送的,更不關心它的細節。投送對象與接收者是一對多關系。接收者如果對通知不再關注,會給通知中心發出removeObserver:name:object:消息解除注冊,以後不再接收通知。

代碼實例:

下面我們模擬一下,應用退出後發送給視圖通知的例子,類圖如下:

\

對於注冊通知中的通知的類圖如下:

\

其中name是名字,object是投送通知時傳過來的對象,userInfo是投送通知時定義的字典對象。


我們也可以把通知中的名字@“AppWillDidEnterBackgroundNotification“修改為UIApplicationDidEnterBackgroundNotification來替代,可以起到相同效果,但是不會有userInfo參數傳入。

AppDelegate:

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    NSDate* date = [NSDatedate];
    NSDictionary* dataDict = [NSDictionarydictionaryWithObject:date forKey:@"DidEnterBackgroundDate"];
    [[NSNotificationCenterdefaultCenter] postNotificationName:@"AppWillDidEnterBackgroundNotification"object:selfuserInfo:dataDict];
}


MainViewController.m:

#import "MainViewController.h"

@interface MainViewController ()

@end

@implementation MainViewController

- (void)viewDidLoad
{
    [superviewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
    //注冊通知
//    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleTerminate:) name:@"AppWillDidEnterBackgroundNotification" object:nil];
    [[NSNotificationCenterdefaultCenter] addObserver:selfselector:@selector(handleTerminate:)name:UIApplicationDidEnterBackgroundNotificationobject:nil];
}

#pragma mark -處理通知
-(void)handleTerminate:(NSNotification*)notification
{
    NSDictionary* theData = [notification userInfo];
    if (theData!=nil) {
        NSDate *date = [theData objectForKey:@"DidEnterBackgroundDate"];
        NSLog(@"MainViewController App DidEnterBackground Date:%@",date);
    }else{
        NSLog(@"MainViewController App DidEnterBackground by UIApplication");
    }
}

-(void)dealloc
{
    //移除通知
    [[NSNotificationCenterdefaultCenter] removeObserver:self];
}


2.2.2 KVO(KEY-VALUE-OBSERVERING)

KVO不想通知機制那樣通過一個通知中心通知所有觀察者對象,而是在對象屬性變化時通知會被直接發送給觀察者對象。圖為KVO機制解析圖。

\

可以看到,屬性發生變化的對象需要發出消息addObserver:forKeyPath:options:context:給注冊觀察者,使觀察者關注她得某個屬性的變化。當對象屬性變化時,觀察者會接收到通知,觀察者需要重寫方法observeValueForKeyPath:ofObject:change:context:以響應屬性變化。

App狀態觀察者:

#import 

/*!
 *  App狀態觀察者
 *
 *  @since V1.0
 */
@interface AppStatusWatcher : NSObject

@end


AppStatusWatcher.m:

#import "AppStatusWatcher.h"

@implementation AppStatusWatcher

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    NSLog(@"Property '%@' of object '%@' changed: %@ context: %@ ",keyPath,object,change,context);
}

@end


AppDelegate.h:

#import 
#import "AppStatusWatcher.h"

@interface AppDelegate : UIResponder 

@property (strong, nonatomic) UIWindow *window;
//應用狀態
@property (strong, nonatomic) NSString *appStatus;
//應用狀態觀察者
@property (strong, nonatomic) AppStatusWatcher *watcher;

@end


AppDelegate.m:

#import "AppDelegate.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Override point for customization after application launch.
    self.watcher = [AppStatusWatcher new];
    //添加注冊觀察
    [self addObserver:self.watcher forKeyPath:@"appStatus" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:@"Pass context"];
    self.appStatus = @"launch";
    
    return YES;
}

/*!
 *  即將不活躍
 *
 *  @param application UIApplication
 *
 *  @since V1.0
 */
- (void)applicationWillResignActive:(UIApplication *)application
{
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    self.appStatus = @"inactive";
}

/*!
 *  進入後台
 *
 *  @param application UIApplication
 *
 *  @since V1.0
 */
- (void)applicationDidEnterBackground:(UIApplication *)application
{
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    self.appStatus = @"background";
}

/*!
 *  即將進入前台
 *
 *  @param application UIApplication
 *
 *  @since V1.0
 */
- (void)applicationWillEnterForeground:(UIApplication *)application
{
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
    self.appStatus = @"inactive";
}

/*!
 *  變為活動狀態
 *
 *  @param application UIApplication
 *
 *  @since V1.0
 */
- (void)applicationDidBecomeActive:(UIApplication *)application
{
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    self.appStatus = @"active";
}

/*!
 *  即將被打斷
 *
 *  @param application UIApplication
 *
 *  @since V1.0
 */
- (void)applicationWillTerminate:(UIApplication *)application
{
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    self.appStatus = @"teminate";
}

3 結語

以上是所有內容,希望對大家有所幫助。

代碼下載地址:

http://download.csdn.net/detail/u010013695/6959029

http://download.csdn.net/detail/u010013695/6965217

http://download.csdn.net/detail/u010013695/6965961


  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved