码迷,mamicode.com
首页 > 移动开发 > 详细

IOS笔记047-代理传值和block传值

时间:2015-06-13 19:54:30      阅读:229      评论:0      收藏:0      [点我收藏+]

标签:

在两个不同的控制器之间传递数据,可以使用代理传值或者block传值。

例子是一个简单通讯录。

主界面如下:

技术分享

添加联系人界面

技术分享

查看/编辑联系人界面:默认是查看模式,点击编辑后进入编辑模式

技术分享

编辑模式

技术分享

数据更新成功。

技术分享

其中添加联系人界面的数据传递使用代理方式实现。

编辑联系人界面的数据传递使用block实现。

下面来看具体过程

1、整个界面搭建

技术分享

在storyboard里拖拽四个控制器,其中联系人界面是一个UITableView。界面之间的跳转使用代码实现,但是要给每一个控制器指定一个标识。按功能分别指定为login,contact,add,edit.

技术分享   技术分享

具体细节我就不说了,关键是代理传值的实现。

2、代理传值

数据传递方向是从add控制器传递到contact控制器。至于为什么使用代理,主要是为了降低类之间的耦合度。

    1、这里需要给add控制器添加一个代理对象,然后定义一个代理需要遵守的协议。

    // 代理实现逆传数据

    @classSLQContact; // 模型对象

    @classSLQAddViewController; //

    @protocol SLQAddViewControllerDelegate<NSObject>

 

    @optional

    // 代理方法

    - (void)addViewController:(SLQAddViewController *)addVC DidClickBtnWithContact:(SLQContact *)contact;

 

    @end

 

    @interface SLQAddViewController : UIViewController

    /*代理对象*/

    @property (strong, nonatomic) id<SLQAddViewControllerDelegate> delegate;

 

    @end

    2、等需要传递数据时只需通知代理一声即可,不需要关心代理如何做。

在添加联系人界面里点击添加按钮后就去通知代理传递数据。

    // 添加联系人按钮,单击后传递数据到联系人控制器,并返回上一个界面

    - (IBAction)addBtn:(id)sender {

        

        //传递模型数据

        SLQContact *temp = [SLQContactcontactWithName:_nameField.textandPhone:_phoneField.text];

 

        // 通知代理

        if([_delegate respondsToSelector:@selector(addViewController:DidClickBtnWithContact:)])

        {

            [_delegateaddViewController:selfDidClickBtnWithContact:temp];

        }

        // 返回上一个界面

        [self.navigationControllerpopViewControllerAnimated:YES];

    }

    3、还有最关键的一步,那就是指定代理对象是谁

        这里指定代理对象的是contact控制器,因为,要把数据传递给它,所以它作为接收者也就是代理方。

    // 添加按钮,按下后进入添加联系人界面

    - (IBAction)addBtn:(id)sender {

        //

    //    [self performSegueWithIdentifier:@"contactToAdd" sender:nil];

        // 通过代码获取storyboard中得控制器

        UIStoryboard *story = [UIStoryboard storyboardWithName:@"Main" bundle:nil];

        // 获取main。storyboard中得控制器,以标识符区分

        SLQAddViewController* addVC = [story instantiateViewControllerWithIdentifier:@"add"];

        // 代理逆传数据

        //如果通过代码跳转的话,必须知道目的控制器,整个程序中也只有这个时候才知道下一个控制器是谁,所以在这里指定代理对象为contact控制器再好不过了

        addVC.delegate = self;

        // 跳转到添加联系人界面    [self.navigationController pushViewController:addVC animated:YES];

    }

    // 实现代理方法,记得让类遵守协议

    - (void)addViewController:(SLQAddViewController *)addVC DidClickBtnWithContact:(SLQContact *)contact

    {

        // 添加数据到数组

        [_contacts addObject:contact];

        

        // 刷洗表格

        [self.tableView reloadData];

    }

2、block传值

    1、在编辑控制器中对block进行生声明以及定义

    // blocl传值使用

    @classSLQContact;

    // 声明block别名,参数为要传递的数据。

    typedef void(^SLQEditViewControllerBolok)(SLQContact *);

 

    @interface SLQEditViewController : UIViewController

    /*模型*/

    @property (strong, nonatomic) SLQContact *contact;

    /*block 对象*/

    @property (strong, nonatomic) SLQEditViewControllerBolok block;

    @end

 

    2、在点击保存按钮后进行数据传递

    // 保存按钮事件

    - (IBAction)save:(id)sender

    {

        // 传递模型数据

        SLQContact *contact = [SLQContactcontactWithName:_nameField.textandPhone:_phoneField.text];

        // block实现传值,先检查是否有数据,如果有传递模型数据

        if(_block)

        {

            _block(contact);

        }

        // 回到上个界面

        [self.navigationControllerpopViewControllerAnimated:YES];

    }

    3、关键一点还是要在数据接收方也就是contact控制器中对block内容进行包装

      因为要通过代码跳转,同样需要知道目的控制器,跳转的地方就是选中cell的时候。

    // 选中cell后进入编辑界面

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

    {

        // 获取编辑控制器

        UIStoryboard *story  = [UIStoryboard storyboardWithName:@"Main" bundle:nil];

        // 获取目的控制器

        SLQEditViewController *editVC = [story instantiateViewControllerWithIdentifier:@"edit"];

        // 传递模型数据到edit控制器(这是一种顺序传值)

        editVC.contact = self.contacts[indexPath.row];

        // 使用block包装之后要进行的操作

        editVC.block = ^(SLQContact *contact){

            // 修改数据

            [self.contacts replaceObjectAtIndex:indexPath.row withObject:contact];

            // 刷新表格

            [self.tableView reloadData];

        };

        // 跳转到编辑界面

        [self.navigationControllerpushViewController:editVC animated:YES];

    }

3、顺序传值

顺序传递数据比价简单,只需要接收方有一个属性对要传递的数据进行接收就行。

上面在进入编辑控制界面时就要对数据进行传递,要把在联系人界面的数据传递到编辑控制器界面,然后对其进行修改。

    // 选中cell后进入编辑界面

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

    {

        // 获取编辑控制器

        UIStoryboard *story  = [UIStoryboard storyboardWithName:@"Main" bundle:nil];

        // 获取目的控制器

        SLQEditViewController *editVC = [story instantiateViewControllerWithIdentifier:@"edit"];

        // 传递模型数据到edit控制器(这是一种顺序传值)

        editVC.contact = self.contacts[indexPath.row];

        // 使用block包装之后要进行的操作

        editVC.block = ^(SLQContact *contact){

            // 修改数据

            [self.contacts replaceObjectAtIndex:indexPath.row withObject:contact];

            // 刷新表格

            [self.tableView reloadData];

        };

        // 跳转到编辑界面

        [self.navigationControllerpushViewController:editVC animated:YES];

    }

上面的代码这样写。是因为在编辑控制器中已经定义了一个模型对象接收传递的数据。

    @interface SLQEditViewController : UIViewController

    /*模型对象,接收传递过来的数据*/

    @property (strong, nonatomic) SLQContact *contact;

    /*block 对象*/

    @property (strong, nonatomic) SLQEditViewControllerBolok block;

    @end

同样传递的地方也是在控制器跳转之前进行数据的传递。

4、总结

传值的方是由到导航控制器的行走方向决定的。

顺序传值:

      由源控制器传递当目的控制器。

      接收方有一个属性接收传递数据,在控制器跳转之前进行传递

逆序传值:

      由源控制器传递当目的控制器。

      代理:

              在发送方对声明代理对象,然后定义代理协议,要传递的数据要放在代理方法的参数中,最后在触发事件后通知代理

              在接收方设置代理位接收方,实现代理方法

      block:

              在发送方对声明block,要传递的数据要放在block的参数中,最后在触发事件后调用block

              在接收方设置block的内容

 

IOS笔记047-代理传值和block传值

标签:

原文地址:http://www.cnblogs.com/chengzhengfu/p/4573926.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!