OC与AS3的观察者模式比较以及外部回调

一.要点

1.AS3的观察者模式,主要是体现在在哪个组件上监听,那么就在这个组件上分发事件,并且可以直接传递Function.

2.OC的观察者模式,主要是需要你指定观察的对象,和观察的对象方法selector,selector只是一个方法的指示器,OC并不能直接传递这个方法,所以你必须指定观察者的对象.

二.实例

1.AS3

amf.as

package com.ylsoft.core
{
    import com.ylsoft.event.AppEvent;
    
    import mx.controls.Alert;
    import mx.core.FlexGlobals;
    import mx.rpc.events.FaultEvent;
    import mx.rpc.events.ResultEvent;
    import mx.rpc.remoting.RemoteObject;

    public class Amf
    {
        
        private var _remoteObject : UIRemoteObject;
        
        private static var _self : Amf;
        
        private var _result:Object;
        
        private var _callback : Function ;
        
        private var _faultMsg:String;
        
        private var _use_waiting_image:*;
        
        public function Amf()
        {
            //singleton
            this._remoteObject = new UIRemoteObject();
        }
        
        /**
         * 注册result返回的回调函数
         * */
        public function registerCallBack(callback:Function):void{
            //再application上注册这个函数
            this._remoteObject.addEventListener(AppEvent.AMF_GLOABAL_COMPLETE,callback);
            this._callback = callback;
        }
        
        
        public function setFaultMessage(msg:String):void{
            this._faultMsg = msg;
        }
        
        
        public function startService(service:String,method:String,...arguments):Amf{
            //清空结果
            this._result = null;
            //开始调用
            this._remoteObject.showBusyCursor = false;
            this._remoteObject.destination = 'amfphp';//必须指定 并不一定需要service-config.xml 因为endpoint会指定destination
            this._remoteObject.source = service;
            this._remoteObject.endpoint = AppConfig.AMFURL;
            this._remoteObject.addEventListener(ResultEvent.RESULT,returnData);
            this._remoteObject.addEventListener(FaultEvent.FAULT,showFault);
            this._remoteObject.use_waiting_image = this._use_waiting_image == null ? AppConfig.USE_WAITING_IMAGE : this._use_waiting_image as Boolean;
            
            if(arguments.length == 0){
                this._remoteObject.getOperation(method).send('');
                return this;
            }
            
            switch(arguments.length){
                case 1:this._remoteObject.getOperation(method).send(arguments[0]);break;
                case 2:this._remoteObject.getOperation(method).send(arguments[0],arguments[1]);break;
                case 3:this._remoteObject.getOperation(method).send(arguments[0],arguments[1],arguments[2]);break;
            }
            return this;
        }
        
        
        private function returnData(evt:ResultEvent):void{
            this._result = evt.result;//先吧结果赋值在触发完成事件 这样在回调中就不会出现空result的错误了
            this._remoteObject.dispatchEvent(new AppEvent(AppEvent.AMF_GLOABAL_COMPLETE));
            this.clearEvent();
//            Alert.show(evt.result.toString());
        }
        
        private function showFault(evt:FaultEvent):void{
               if(this._faultMsg!=null){
                   Alert.show(this._faultMsg);
               }else{
                   Alert.show(evt.fault.message);
               }
               this.clearEvent();
        }
        
        
        public function getResult():Object{
            return this._result;
        }
        
        private function clearEvent():void{
            this._remoteObject.removeEventListener(ResultEvent.RESULT,returnData);
            this._remoteObject.removeEventListener(FaultEvent.FAULT,showFault);
            this._remoteObject.removeEventListener(AppEvent.AMF_GLOABAL_COMPLETE,this._callback);
            FlexGlobals.topLevelApplication.dispatchEvent(new AppEvent(AppEvent.UIREMOTEOBJECT_FINISH));
        }
        
        
        public function get use_waiting_image():*
        {
            return _use_waiting_image;
        }
        
        public function set use_waiting_image(value:*):void
        {
            _use_waiting_image = value;
        }
        
    }
}

外部调用

amf = new Amf();
amf.setFaultMessage("通信失败");
amf.registerCallBack(initDataGrid);
amf.startService('dailyCopyDataService','lists',new Pagelimit(0,AppConfig.PAGECOUNT),getCondition());

function initDataGrid(e:AppEvent):void{
   //code here
}

那么当_remoteObject 分发请求完成事件的时候就会调用initDataGrid 这个方法了

2.objective-c

viewController.h

//
//  ViewController.h
//  rpc
//
//  Created by 卜 峘 on 13-7-22.
//  Copyright - (void)connectionDidFinishLoading:(NSURLConnection *)connection;年 卜 峘. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "URLConnectionImpl.h"
#import "CJSONDeserializer.h"
@interface ViewController : UIViewController
{
    @private
     URLConnectionImpl *impl;
    IBOutlet UIButton *rpcbtn;
}

@property(nonatomic,retain) URLConnectionImpl *impl;
@property(nonatomic,retain) IBOutlet UIButton *rpcbtn;

-(IBAction)send:(id)sender;
-(void)fetchData:(id)sender;

@end

viewController.m

//
//  ViewController.m
//  rpc
//
//  Created by 卜 峘 on 13-7-22.
//  Copyright (c) 2013年 卜 峘. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController
@synthesize impl;
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    impl  =  [[[URLConnectionImpl alloc]autorelease ]init];
    impl.executeData = @selector(fetchData:);//注册接收数据的回调函数
    impl.target = self;//设置调用fetchData 的对象
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(void)send:sender{
    NSString *address = @"http://127.0.0.1/oc/test.php";
    NSURL  *url = [[[NSURL alloc]autorelease ] initWithString:address];
    NSURLRequest *req  = [[[NSURLRequest alloc] autorelease]initWithURL:url];
    NSURLConnection *conn = [[[NSURLConnection alloc] autorelease] initWithRequest:req delegate:impl];
}

-(void)fetchData:(id)sender{
    //从通知中心得到数据
    NSData *data = [[sender userInfo]objectForKey:@"data"];
    NSDictionary *dic = [[CJSONDeserializer deserializer] deserializeAsDictionary:data error:nil];
    NSLog(@"%@",[dic objectForKey:@"name"]);
}


@end

URLConnectionImpl.h

//
//  URLConnectionImpl.h
//  rpc
//
//  Created by 卜 峘 on 13-7-22.
//  Copyright (c) 2013年 卜 峘. All rights reserved.
//    NSURLConnection 的代理实现类 需在nsurlconnection的delegate参数中传入本类的实例
//    主要功能 实现数据的外部回调
 //

#import <Foundation/Foundation.h>

@interface URLConnectionImpl : NSObject <NSURLConnectionDelegate,NSURLConnectionDataDelegate>{
    SEL executeData;  //执行回调的对象里的方法
    NSObject  *target;//执行回调的对象
}

@property SEL executeData;
@property(nonatomic,retain) NSObject *target;

@end

URLConnectionImpl.m

//
//  URLConnectionImpl.m
//  rpc
//
//  Created by 卜 峘 on 13-7-22.
//  Copyright (c) 2013年 卜 峘. All rights reserved.
//

#import "URLConnectionImpl.h"

@implementation URLConnectionImpl
@synthesize executeData;
@synthesize target;
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
    NSLog(@"%@",error);
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
    [[NSNotificationCenter defaultCenter]addObserver:self.target selector:self.executeData name:@"fetchWebServiceData" object:nil];//注册通知 实际上这里的selector也就是个char*类型  猜测内部应该是 [self.target self.executeData]这样的调用方式
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
    [[NSNotificationCenter defaultCenter]postNotificationName:@"fetchWebServiceData" object:self.target
     userInfo:[NSDictionary dictionaryWithObject:data forKey:@"data"]];//发送通知
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
    
}

@end

相比之下OC这种方式更为灵活一些,能够随意分配指定delegate并且更灵活的指定观察者.

原文地址:https://www.cnblogs.com/lost-1987/p/3208864.html