iOS开发——使用delegate进行消息传递

        iOS开发中,界面之间传递消息或者数据是最基本的一种需求,我们可以使用很多方法来实现这种需求,比如在头文件中暴露一个属性、比如使用notification(一对多的消息传递)等等。今天我们要来介绍另一种方式:使用delegate传递消息(一对一的消息传递)。

       delegate称为委托,同时也是一种代理设计模式。使用委托避免了类与类的耦合度过高。利用委托赋值更加安全可控,委托赋值在不暴露自己类的属性的前提下就可以对自己进行赋值。

       在iOS中委托通过协议@protocol来实现,在协议中所声明的方法,不需要在协议中有实现的方法,是由它的实现类来实现(该类需要在头文件中包含<协议名>)。“协议”和“委托”是两个不一样的概念,因为我们在看代码的时候总是会看到他们出现在一起。但不能说,delegate就是protocol,delegate是一种架构模式。举个例子什么是“委托”:比如我在开车,但是开车不能看短信,所以我就叫车里的朋友帮我看短信,这样我就可以正常的开车了。当朋友看完短信内容后,就告诉我是什么内容。这就是委托,朋友就是我的委托对象。“协议”protocol是用来定义对象的属性和行为,类似于C++中的虚函数。其中有两个关键字@required和@optional,前者表示必须要实现的方法,后者是可选的方法。

       使用delegate常用在两种情况下:

*两个类之间的传值,类A调用类B的方法,类B在执行过程中遇到问题通知类A;

*控制器(ViewController)与控制器(ViewController)之间的传值,从A跳转到B,再从B返回到A时需要通知A更新UI或者是做其他的事情,这时候就用到了代理(delegate)传值。

tips:如果没有在@protocol中显式的写上@required或者@optional,那么默认就是@required(必需的)的。为了不引起歧义,最好显式的写上@required或@optional。

       通常一个delegate的使用过程需要经过5步:

(1)创建一个delegate;

(2)委托者声明一个delegate;

(3)委托者调用delegate内的方法(method);

(4)被委托者设置delegate,以便被委托者调用;

(5)被委托者实现delegate所定义的方法;  

下面我通过1个实例来演示使用delegate传递数据,代码上传至:https://github.com/chenyufeng1991/iOS-Delegate   中的Delegate01.

(1)首先程序是基于storyboard来构建的,界面布局如下:在界面返回的时候将会传递数据。



(2)新建一个Protocol,作为我们的协议,里面可以声明一些方法。如图:

iOS开发——使用delegate进行消息传递_第1张图片


ProtocolDelegate里面的实现如下:

#import <Foundation/Foundation.h>

//实现一个protocol;
/**
 *  可以理解为Java中的接口interface;
 */
@protocol ProtocolDelegate <NSObject>

// 必须实现的方法
@required
- (void)execute;

// 可选实现的方法
@optional
- (void)function1;
- (void)function2;
- (void)function3;

@end


(3)我首先来实现第二个界面,在第二个界面的头文件.h中需要声明一个protocol,在该protocol中声明的方法可以在第一个界面中实现,并在第二个界面中进行调用。这是数据传递的关键。

#import <UIKit/UIKit.h>

// 新建一个协议,协议的名字一般是由“类名+Delegate”
/**
 *  在该协议中声明的方法,在第一个界面中实现,在该界面中调用;
 */
@protocol ViewControllerBDelegate <NSObject>

@required
- (void)sendValue:(NSString *)value;

@end

@interface ViewControllerB : UIViewController

//这里的delegate要设置在.h中;
@property (weak, nonatomic) id<ViewControllerBDelegate> delegate;

@end

(4)在第二个界面的实现文件中实现如下:在点击返回键的时候调用协议中的方法,

#import "ViewControllerB.h"

//第二个界面;
@interface ViewControllerB ()

@property (strong, nonatomic) IBOutlet UITextField *textField;

@end

@implementation ViewControllerB

- (IBAction)backAction:(id)sender{

  //界面跳转的时候调用该方法;
  [self.delegate sendValue:self.textField.text]; // 通知执行协议方法
  //返回传递消息;
  [self.navigationController popViewControllerAnimated:YES];
}

@end

(5)下面来实现第一个界面ViewController.m:

#import "ViewController.h"
#import "ProtocolDelegate.h"
#import "ViewControllerB.h"

//第一个界面;
@interface ViewController () <ProtocolDelegate, ViewControllerBDelegate>

@end

@implementation ViewController

//因为是基于storyboard的segue来构建,当界面跳转时,自动回调该方法;
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
    ViewControllerB *vc = segue.destinationViewController;
    [vc setDelegate:self];

}

// 这里实现B控制器的协议方法
- (void)sendValue:(NSString *)value{
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"成功" message:value delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
    [alertView show];
}

//该方法是ProtocolDelegate中的@required方法;
- (void)execute{
    
}


- (IBAction)pressed:(id)sender {

  NSLog(@"1111");

}


@end

(6)运行效果如下:

iOS开发——使用delegate进行消息传递_第2张图片


iOS开发——使用delegate进行消息传递_第3张图片


上面的demo是基于storyboard。由于有些项目是基于nib文件构建的,我下面来演示一下使用nib文件时的注意点。代码在:https://github.com/chenyufeng1991/iOS-Delegate   中的Delegate02.

(1)删除原来的main.storyboard,新增两个nib文件,分别绑定对应的ViewController。我推荐使用navigationBar,所以在AppDelegate.m中的实现如下:

#import "AppDelegate.h"
#import "ViewController.h"

@interface AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {



  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  self.window.rootViewController = [[ViewController alloc] init];

  self.naviController = [[UINavigationController alloc] initWithRootViewController:self.window.rootViewController];

  [self.window addSubview:self.naviController.view];
  [self.window makeKeyAndVisible];


  return YES;
}

@end

(2)在第二个界面中主要修改如下,删除prepareForSegue方法,在按钮的点击方法中实现:

- (IBAction)pressed:(id)sender {
  //如果项目本身是根据nib文件构建的,就使用下面的方式绑定delegate,并跳转;
  ViewControllerB *vb    = [[ViewControllerB alloc] initWithNibName:@"ViewControllerB" bundle:[NSBundle mainBundle]];
  vb.delegate            = self;

  [self.navigationController pushViewController:vb animated:true];

}

然后运行效果同上。不同之处也就是在ViewController绑定delegate处有不同。


     总结,Delegate委托属于程序架构层面上,是相对比较高的层次,如果我们能够熟练使用delegate,就能有效降低程序耦合度,提高代码可读性。

本文参考:http://blog.csdn.net/shenjie12345678/article/details/24555973

http://leopard168.blog.163.com/blog/static/168471844201307112149221/

http://www.cocoachina.com/ios/20150112/10880.html



github主页:https://github.com/chenyufeng1991  。欢迎大家访问!

你可能感兴趣的:(ios,Objective-C,delegate)