IOS中消息传递的8种方式

来源:互联网 发布:java中的mvc模式 编辑:程序博客网 时间:2024/06/17 13:03

一 MVC简介

MVC是将应用中的类组织起来的一种策略。是iOS开发最常用的设计模式,当然,还有诸如MVVM,VIPER等模式,不过不在本文的讨论范畴。

MVC代表什么:Model-View-Controller。

Model:应用是什么(what the app is )

Controller:如何呈现Model

View:你看到的东西

注意:

1.Controller可以直接访问Model和View。

2.Model和View不要直接通信。

3.View和Model是不依赖于Controller的,这是最基本的,不然你的工程在测试和维护起来都非常麻烦。

二 消息传递的8种方式

为了更好的理解消息传递,我写了个简单的demo,三个ViewController分别展示不同的消息传递方式。

第一个ViewController如图

Up,Down两个Button点击后分别会将Label的数字加减一


1 Outlet(Controller访问View)

注意:Outlet应当是weak的,因为强Outlet不应该参与引用计数。

使用Outlet非常简单,

在storyboard上拖出一个控件,然后control+drag拖出一个outlet,如图沿着红线拖拽


不要忘记给ViewController设定为自定义的类,不然打开辅助编辑界面不会无法拖拽。

这样,就可以用属性的访问方式来直接访问label


2 target Action(盲通信,View反馈给Controller)

Up Button使用方式一,在storyboard上拖拽


然后在自动创建方法种进行如下定义,这个方法负责将label的数字加一

[objc] view plain copy
  1. - (IBAction)up:(id)sender {  
  2.     NSInteger lastNum = self.label.text.integerValue;  
  3.     lastNum++;  
  4.     self.label.text = [NSString stringWithFormat:@"%ld",lastNum];  
  5. }  


Down Button使用方式二,用代码添加

定义如下函数,来处理Down Button点击事件

[objc] view plain copy
  1. -(void)down:(id)sender{  
  2.     NSInteger lastNum = self.label.text.integerValue;  
  3.     lastNum--;  
  4.     self.label.text = [NSString stringWithFormat:@"%ld",lastNum];  
  5. }  
然后,在ViewDidLoad函数中,用代码绑定target-action

[objc] view plain copy
  1. [self.downButton addTarget:self action:@selector(down:) forControlEvents:UIControlEventTouchUpInside];  

第二个ViewController很简单,就是在Storyboard上拖出一个View,并把类选择为我自定义的一个类CustomAnimateView,这个类里实现了用代理,block,DataSource。

点击Animate按钮,红色的原点会移动到SecondViewController提供位置,移动的时间由DataSource提供,移动开始和结束的事件由Delegate来提供,移动结束的事件同时也由Block提供。


3 Delegate (View传递事件给Controller,也用用来Controller传递数据,用处比较广泛,解耦合)

4 DataSource (View的数据源,解耦合的方式)

5 Block(常常用来传递事件)

首先定义Protocol和DataSource,以及响应完成的Block类型(typedef定义)

[objc] view plain copy
  1. <pre name="code" class="objc">  
[objc] view plain copy
  1. //  
  2. //  CustomAnimationView.h  
  3.   
  4. #import <UIKit/UIKit.h>  
  5. @class CustomAnimationView;  
  6. typedef void(^AnimationFinishedBlock)();  
  7.   
  8.   
  9. @protocol CustomAnimationViewDataSource <NSObject>  
  10. -(NSTimeInterval)animationDuration;  
  11. -(CGPoint)AnimateToPoint;  
  12. @end  
  13.   
  14. @protocol CustomAnimationViewDelegate <NSObject>  
  15. @optional  
  16. -(void)willStartAnimate:(CustomAnimationView *)view;  
  17. -(void)didFinishedAnimate:(CustomAnimationView *)view;  
  18. @end  

然后,在CustomAnimationView的接口里定义

[objc] view plain copy
  1. </pre><pre name="code" class="objc"><pre name="code" class="objc">@interface CustomAnimationView : UIView  
  2. @property (weak,nonatomicid<CustomAnimationViewDataSource>datasource;  
  3. @property (weak,nonatomicid<CustomAnimationViewDelegate>delegate;  
  4. @property (copy,nonatomic) AnimationFinishedBlock completeBlock;  
  5. @end  

最后,Button的事件中进行事件传递,

[objc] view plain copy
  1. -(void)animate:(id)sender{  
  2.     if (self.datasource == nil || CGPointEqualToPoint(self.circleView.center, [self.datasource AnimateToPoint])){  
  3.         return;  
  4.     }  
  5.     if ([self.delegate respondsToSelector:@selector(willStartAnimate:)]) {  
  6.         [self.delegate willStartAnimate:self];  
  7.     }  
  8.     [UIView animateWithDuration:[self.datasource animationDuration]  
  9.                      animations:^{  
  10.                          self.circleView.center = [self.datasource AnimateToPoint];  
  11.                      }  
  12.                      completion:^(BOOL finished) {  
  13.                          if ([self.delegate respondsToSelector:@selector(didFinishedAnimate:)]) {  
  14.                              [self.delegate didFinishedAnimate:self];  
  15.                          }  
  16.                          if (self.completeBlock) {  
  17.                              self.completeBlock();  
  18.                          }  
  19.                      }];  
  20. }  

然后在SecondViewController中,让SecondViewController遵循Delegate和DataSource,提供DataSource所需的必要方法,提供Delegate的方法

[objc] view plain copy
  1. <pre name="code" class="objc">@interface SecondViewController ()<CustomAnimationViewDataSource,CustomAnimationViewDelegate>  
  2. @property (weak, nonatomic) IBOutlet CustomAnimationView *customview;  
  3.   
  4. @end  
  5.   
  6. @implementation SecondViewController  
  7.   
  8. - (void)viewDidLoad {  
  9.     [super viewDidLoad];  
  10.     self.customview.delegate = self;  
  11.     self.customview.datasource = self;  
  12.     self.customview.completeBlock = ^(){  
  13.         NSLog(@"Got finished action from block");  
  14.     };  
  15.       
  16. }  
  17.     // Do any additional setup after loading the view.  
  18.   
  19. -(NSTimeInterval)animationDuration{  
  20.     return 1.0;  
  21. }  
  22.   
  23. -(CGPoint)AnimateToPoint{  
  24.     return CGPointMake(200400);  
  25. }  
  26.   
  27. -(void)willStartAnimate:(CustomAnimationView *)view{  
  28.     NSLog(@"will start");  
  29. }  
  30. -(void)didFinishedAnimate:(CustomAnimationView *)view{  
  31.     NSLog(@"did finished");  
  32. }  

这样,点击的时候,就会按照DataSource提供的动画时间和动画的结束点来运行,并且可以在Log中,看到监听事件成功。

[objc] view plain copy
  1. 2015-01-29 20:29:06.582 MessageTransitionExample[3355:117440] will start  
  2. 2015-01-29 20:29:07.584 MessageTransitionExample[3355:117440] did finished  
  3. 2015-01-29 20:29:07.585 MessageTransitionExample[3355:117440] Got finished action from block  

第三个ViewController如图,两个View(自定义的RandomChangeColorView)各添加了点击的手势,点击的时候,随机更改自己的backgroundColor,然后,第一个View由KVO的方式监听变化,第二个View用Notificaition的方式来监听变化

6 KVO(Model反馈给View)

在ThridViewController注册监听的属性

[objc] view plain copy
  1. [self.firstView addObserver:self forKeyPath:@"backgroundColor" options:NSKeyValueObservingOptionNew context:(void*)&PrivateKVOContext];  
然后,在如下方法中监听变化,

[objc] view plain copy
  1. -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(voidvoid *)context{  
  2.     if (context == &PrivateKVOContext){  
  3.         NSLog(@"first view backgroud color changed from KVO");  
  4.         NSLog(@"%@",change.description);  
  5.     }  
  6. }  
这里的context

[objc] view plain copy
  1. static const int PrivateKVOContext = 0;  

7 Notification(盲通信,用处也比较广泛)

在RandomChangeColorView的响应事件中,进行广播

[objc] view plain copy
  1. [[NSNotificationCenter defaultCenter] postNotificationName:KRANDOMCHANGECOLORVIEWNOTIFICATION object:randomColor];  
然后,在ThridViewController中监听广播

[objc] view plain copy
  1. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(colorChange:) name:KRANDOMCHANGECOLORVIEWNOTIFICATION object:nil];<pre name="code" class="objc">-(void)colorChange:(NSNotification *)notificaiton{  
  2.     NSLog(@"Color chagne from notification");  
  3.     NSLog(@"%@",notificaiton.object);  
  4. }  

这里的KRNADOMCHANGECOLORNOTIFICATION是一个宏定义的NSString

注意,注册KVO和通知都应该在合理的位置取消注册

[objc] view plain copy
  1. -(void)viewWillDisappear:(BOOL)animated{  
  2.     [self.firstView removeObserver:self forKeyPath:@"backgroundColor"];  
  3.     [[NSNotificationCenter defaultCenter] removeObserver:KRANDOMCHANGECOLORVIEWNOTIFICATION];  
  4. }  

点击第三个ViewController的两个View,在Log中看到了监听成功

[objc] view plain copy
  1. 2015-01-29 20:31:07.675 MessageTransitionExample[3355:117440] first view backgroud color changed from KVO  
  2. 2015-01-29 20:31:07.676 MessageTransitionExample[3355:117440] {  
  3.     kind = 1;  
  4.     new = "UIDeviceRGBColorSpace 0.00784314 0.247059 0.168627 1";  
  5. }  
  6. 2015-01-29 20:31:10.731 MessageTransitionExample[3355:117440] Color chagne from notification  
  7. 2015-01-29 20:31:10.731 MessageTransitionExample[3355:117440] UIDeviceRGBColorSpace 0.388235 0.482353 0.835294 1  

8 Segue在ViewController切换的时候,常常用来传递信息

之前的几篇文章,我详细介绍了各种,segue,并且附上了demo。

嵌入式Segue

自定义Segue

Modal Segue和Unwind Segue

三 最后说说代理和Notification的区别

  代理就像打电话,只有先接通了才能进行信息交流。而Notification就像是广播,你收听不收听,多少个人收听跟我没关系,反正我要广播,但是注意,你跟广播站注册了你要收听广播,但是你不收听了却不提前告诉广播站。下次广播站发现有通知要给你,你却不知道哪去了,你就要遭殃了(App 有可能会崩溃)。

最后,附上整个Demo的下载链接。

CSDN链接

http://download.csdn.net/detail/hello_hwc/8408187

0 0