Heew’s iOS Blog

A personal blog accounting problems for iOS.

多控制器之间数据传递

app有很多界面,如果A界面修改了数据某个值,如何保证B界面的数据也能被修改

通常想法如下:

  • 给A控制器增加一个成员变量指向B
  • 创建B界面的时候就赋值给这个变量
  • 当A修改了数据以后,调用成员变量的方法更新B界面的数据

搭建界面如下

通讯录界面跳转通讯录界面跳转通讯录界面跳转

在A界面HYWAddController.h文件中增加变量指向B

1
2
3
@class HYWContact,HYWContactController;
/**拥有联系人控制器,以便传递模型 */
@property (nonatomic, strong) HYWContactController *contactVc;

在B界面HYWContactController.h文件中,增加模型属性,重写set方法,接收A传过来得数据

1
2
/**模型 */
@property (nonatomic, strong) HYWContact *contact;

在B界面HYWContactController.m文件中,创建B界面push的时候,将A赋值给B界面的变量,并且重写set方法

1
2
3
4
5
6
7
8
9
10
11
12
13
- (void)add
{
    HYWAddController *addVc = [[HYWAddController alloc] init];
    addVc.title = @"添加通讯录";
    addVc.contactVc = self;
    [self.navigationController pushViewController:addVc animated:YES];
}
- (void)setContact:(HYWContact *)contact
{
    _contact = contact;
    [self.contacts addObject:contact];
    [self.tableView reloadData];
}

A界面跳转的时候,修改模型,并通过成员变量调取B界面,并且调用set方法,进行赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
- (IBAction)addContact:(id)sender {
  // 修改数据
    HYWContact *contact = [[HYWContact alloc] init];
    contact.name = self.nameTextField.text;
    contact.phone = self.phoneTextField.text;
    contact.icon = @"180008225874";
    
    // 调取B界面,调用set方法更新数据
    self.contactVc.contact = contact;

  从A界面跳到B界面
    [self.navigationController popViewControllerAnimated:YES];
}

通讯录传递数据通讯录传递数据

这种想法比较简单,但是实现复杂,而且A界面和B界面耦合性太强,利用代理传递数据进行解耦

  • A界面增加代理属性,代理方法
  • 当数据更新后,通知代理更新了数据
  • 任何一个对象只要成为A的代理,就可以获得A传过来的数据

在A界面HYWAddController.h中增加代理属性和代理方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#import <UIKit/UIKit.h>
@class HYWAddController,HYWContact;

@protocol HYWAddControllerDelegate <NSObject>

@optional

- (void)addControllerDidClickAddButton:(HYWAddController *)addVc withContact:(HYWContact *)contact;
@end

@interface HYWAddController : UIViewController

/**代理 */
@property (nonatomic, weak) id <HYWAddControllerDelegate> delegate;


@end

当A跳转的时候,更新数据,并通知代理,数据作为参数传递出去

1
2
3
4
5
6
7
8
9
10
11
- (IBAction)addContact:(id)sender {
    HYWContact *contact = [[HYWContact alloc] init];
    contact.name = self.nameTextField.text;
    contact.phone = self.phoneTextField.text;
    contact.icon = @"180008225874";
    
    if ([self.delegate respondsToSelector:@selector(addControllerDidClickAddButton:withContact:)]) {
        [self.delegate addControllerDidClickAddButton:self withContact:contact];
    }
    [self.navigationController popViewControllerAnimated:YES];
}

在B界面HYWContactController.m文件中,设置为A的代理,并实现A的代理方法,后去传过来的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

@interface HYWContactController () <HYWAddControllerDelegate>


- (void)add
{
    HYWAddController *addVc = [[HYWAddController alloc] init];
    addVc.delegate = self;
    addVc.title = @"添加通讯录";
    [self.navigationController pushViewController:addVc animated:YES];
}

#pragma mark - HYWAddControllerDelegate 代理方法

- (void)addControllerDidClickAddButton:(HYWAddController *)addVc withContact:(HYWContact *)contact
{
    [self.contacts addObject:contact];
    [self.tableView reloadData];
}

通讯录数据传递通讯录数据传递

代理方法更简单,A传递数据,B成为代理就可以接受,不成为代理就与A没有关系,就算成为A的代理,不实现代理方法还是与A没有关系.成功地接触了A和B的耦合性