IOS中消息传递的8种方式

原创Blog,转载请注明出处

blog.csdn.net/hello_hwc

一 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的数字加一

- (IBAction)up:(id)sender {
    NSInteger lastNum = self.label.text.integerValue;
    lastNum++;
    self.label.text = [NSString stringWithFormat:@"%ld",lastNum];
}

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

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

-(void)down:(id)sender{
    NSInteger lastNum = self.label.text.integerValue;
    lastNum--;
    self.label.text = [NSString stringWithFormat:@"%ld",lastNum];
}

然后,在ViewDidLoad函数中,用代码绑定target-action

[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定义)

<pre name="code" class="objc">
//
//  CustomAnimationView.h

#import <UIKit/UIKit.h>
@class CustomAnimationView;
typedef void(^AnimationFinishedBlock)();

@protocol CustomAnimationViewDataSource <NSObject>
-(NSTimeInterval)animationDuration;
-(CGPoint)AnimateToPoint;
@end

@protocol CustomAnimationViewDelegate <NSObject>
@optional
-(void)willStartAnimate:(CustomAnimationView *)view;
-(void)didFinishedAnimate:(CustomAnimationView *)view;
@end

然后,在CustomAnimationView的接口里定义

</pre><pre name="code" class="objc"><pre name="code" class="objc">@interface CustomAnimationView : UIView
@property (weak,nonatomic) id<CustomAnimationViewDataSource>datasource;
@property (weak,nonatomic) id<CustomAnimationViewDelegate>delegate;
@property (copy,nonatomic) AnimationFinishedBlock completeBlock;
@end

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

-(void)animate:(id)sender{
    if (self.datasource == nil || CGPointEqualToPoint(self.circleView.center, [self.datasource AnimateToPoint])){
        return;
    }
    if ([self.delegate respondsToSelector:@selector(willStartAnimate:)]) {
        [self.delegate willStartAnimate:self];
    }
    [UIView animateWithDuration:[self.datasource animationDuration]
                     animations:^{
                         self.circleView.center = [self.datasource AnimateToPoint];
                     }
                     completion:^(BOOL finished) {
                         if ([self.delegate respondsToSelector:@selector(didFinishedAnimate:)]) {
                             [self.delegate didFinishedAnimate:self];
                         }
                         if (self.completeBlock) {
                             self.completeBlock();
                         }
                     }];
}

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

<pre name="code" class="objc">@interface SecondViewController ()<CustomAnimationViewDataSource,CustomAnimationViewDelegate>
@property (weak, nonatomic) IBOutlet CustomAnimationView *customview;

@end

@implementation SecondViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.customview.delegate = self;
    self.customview.datasource = self;
    self.customview.completeBlock = ^(){
        NSLog(@"Got finished action from block");
    };

}
    // Do any additional setup after loading the view.

-(NSTimeInterval)animationDuration{
    return 1.0;
}

-(CGPoint)AnimateToPoint{
    return CGPointMake(200, 400);
}

-(void)willStartAnimate:(CustomAnimationView *)view{
    NSLog(@"will start");
}
-(void)didFinishedAnimate:(CustomAnimationView *)view{
    NSLog(@"did finished");
}

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

2015-01-29 20:29:06.582 MessageTransitionExample[3355:117440] will start
2015-01-29 20:29:07.584 MessageTransitionExample[3355:117440] did finished
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注册监听的属性

  [self.firstView addObserver:self forKeyPath:@"backgroundColor" options:NSKeyValueObservingOptionNew context:(void*)&PrivateKVOContext];

然后,在如下方法中监听变化,

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    if (context == &PrivateKVOContext){
        NSLog(@"first view backgroud color changed from KVO");
        NSLog(@"%@",change.description);
    }
}

这里的context

static const int PrivateKVOContext = 0;

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

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

[[NSNotificationCenter defaultCenter] postNotificationName:KRANDOMCHANGECOLORVIEWNOTIFICATION object:randomColor];

然后,在ThridViewController中监听广播

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

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

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

-(void)viewWillDisappear:(BOOL)animated{
    [self.firstView removeObserver:self forKeyPath:@"backgroundColor"];
    [[NSNotificationCenter defaultCenter] removeObserver:KRANDOMCHANGECOLORVIEWNOTIFICATION];
}

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

2015-01-29 20:31:07.675 MessageTransitionExample[3355:117440] first view backgroud color changed from KVO
2015-01-29 20:31:07.676 MessageTransitionExample[3355:117440] {
    kind = 1;
    new = "UIDeviceRGBColorSpace 0.00784314 0.247059 0.168627 1";
}
2015-01-29 20:31:10.731 MessageTransitionExample[3355:117440] Color chagne from notification
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

时间: 2024-11-05 10:55:35

IOS中消息传递的8种方式的相关文章

IOS中键盘隐藏几种方式

在ios开发中,经常需要输入信息.输入信息有两种方式: UITextField和UITextView.信息输入完成后,需要隐藏键盘,下面为大家介绍几种隐藏键盘的方式. <一> 点击键盘上的return按钮,隐藏键盘 1.UITextField 遵守协议 设置代理 使用代理中方法 2.UITextView 遵守协议 设置代理 使用代理中方法 <二> 在键盘上添加一个按钮,点击按钮隐藏键盘 设置按钮 1.UITextField  2.UITextView 添加隐藏键盘方法 <三&

iOS代码加密的几种方式

众所周知的是大部分iOS代码一般不会做加密加固,因为iOS APP一般是通过AppStore发布的,而且苹果的系统难以攻破,所以在iOS里做代码加固一般是一件出力不讨好的事情.万事皆有例外,不管iOS.adr还是js,加密的目的是为了代码的安全性,虽然现在开源畅行,但是不管个人开发者还是大厂皆有保护代码安全的需求,所以iOS代码加固有了生存的土壤.下面简单介绍下iOS代码加密的几种方式. iOS代码加密的几种方式 1.字符串加密 字符串会暴露APP的很多关键信息,攻击者可以根据从界面获取的字符串

IOS数据持久化的4种方式

9.1 数据持久化概述 9.2 iOS应用程序目录结构 9.3 读写属性列表 9.4 对象归档 9.5 访问SQLite 9.1 数据持久化概述 iOS中可以有四种持久化数据的方式: 属性列表.对象归档.SQLite3和Core Data 9.2 iOS应用程序目录结构 iOS应用程序运行在Mac os模拟器时候,有一下临时目录模拟器3.1.3为例子: /Users/tony/Library/Application Support/iPhone Simulator/3.1.3/Applicati

iOS数据存储的几种方式

iOS的数据存储是iOS应用开发的重要知识点: 关于这方面知识,网上有很多介绍,但对于代码层次的使用方式并未有系统全面介绍.此文章针对iOS稍熟悉的童鞋,需要对CoreData的原理有一定的了解.目前存储方式大概有以下几种: NSKeyedArchiver  适用简单数据加密 NSUserDefaults  适用配置参数 Write  文件操作,同NSKeyedArchiver SQLite3  操作较复杂,不建议使用. CoreData  取代SQLite3,但要遵循NSManagedObje

关于iOS中音视频播放的几种方式介绍

在IOS设计中,音视频的播放通常涉及到大部分设计过程中,因此清晰了解并使用音视频播放结构就很重要了,下面介绍几种常用的音视频的播放方式: (一) 使用系统提供的播放器,用system sound service去播放时长小于30s的音乐,通常是.caf,.aif,.wav格式: 创建一个系统播放对象: AudioServicesCreateSystemSoundID ( CFURLRef inFileURL, SystemSoundID *outSystemSoundID); AudioServ

iOS狂暴之路---iOS中应用的数据存储方式解析

一.前言 前面一篇文章中已经介绍了iOS应用中的视图控制器知识点,而本文不会按照常理来介绍View的知识点,而是先介绍iOS中的数据存储知识点,因为关于View的知识点太多了,后面会连续详细介绍一下.这篇先来看一下iOS中的数据存储功能分析.每一个iOS应用和Android应用一样,都有其对应的沙盒存储自己的数据,但是iOS和Android有一个区别就在于没有SD卡的概念了,也就说在iOS中应用的数据只能保存到自己的沙盒中.这也可以看出来iOS为了应用的安全考虑. 在开发Android的时候都知

iOS中常用的四种数据持久化方法简介

iOS中常用的四种数据持久化方法简介 iOS中的数据持久化方式,基本上有以下四种:属性列表.对象归档.SQLite3和Core Data 1.属性列表涉及到的主要类:NSUserDefaults,一般 [NSUserDefaults standardUserDefaults]就够用了 @interface User : NSObject <NSCoding>@property (nonatomic, assign) NSInteger userID;@property (nonatomic,

iOS保存数据的4种方式

在iOS开发过程中,不管是做什么应用,都会碰到数据保存的问题.将数据保存到本地,能够让程序的运行更加流畅,不会出现让人厌恶的菊花形状,使得用户体验更好.下面介绍一下数据保存的方式: 1.NSKeyedArchiver:采用归档的形式来保存数据,该数据对象需要遵守NSCoding协议,并且该对象对应的类必须提供encodeWithCoder:和initWithCoder:方法.前一个方法告诉系统怎么对对象进行编码,而后一个方法则是告诉系统怎么对对象进行解码.例如对Possession对象归档保存.

UI进阶--iOS中的数据存储常用方式

iOS中的数据存储常用方式: 1.xml属性列表(plist): 2.preference偏好设置; 3.NSKeyedArchiver归档(需要遵守NSCodeing协议); 4.SQLite 3; 5.Core Data; ...... 应用沙盒: 每个iOS应用都有?己的应?沙盒(应用沙盒就是文件系统目录),与其他文件系统隔离.应?必须待在?己的沙盒里,其他应用不能访问该沙盒(提示:在IOS8中已经开放访问) 应?沙盒的文件系统?录,如下图所示(假设应用的名称叫Layer) 模拟器应?用沙