记一次解决跨控制器监听开关状态改变的尝试。
为了统一设置UITableViewCell里的内容,自定义了UITableViewCell类的一个基类,命名为SettingCell。SettingCell里显示的内容由数据模型SettingItem提供:在SettingCell里定义一个属性即可。
@property (nonatomic, strong) SettingItem *item;
再定义几个SettingItem的子类表示显示不同内容的Cell(如图1).由于所有开关状态的归档和解档都一样,故统一在父类SettingItem里实现。但是点击“手势密码”后跳转到下一个控制(如图2)后,需要单独监听手势密码开关的状态,这就涉及到了跨控制器监听开关状态改变事件的问题。我首先想到了代理模式。
图1 图2
首先在SettingCell.h里声明代理方法和属性:
1 #import
2
3 @classSettingItem, SettingCell;4
5 @protocol SettingCellDelegate
6
7 @optional8
9 //监听开关状态改变
10 - (void)settingCell:(SettingCell *)cell switchChanged:(UISwitch *)switchView;11
12 @end
13
14 @interfaceSettingCell : UITableViewCell15
16 //存放模型数据
17 @property (nonatomic, strong) SettingItem *item;18
19 @property (nonatomic, assign, getter =isLastRowInSection) BOOL lastRowInSection;20
21 + (instancetype)cellWithTableView:(UITableView *)tableView;22
23 //定义代理属性
24 @property (nonatomic, weak) id delegate;25
26 @end
然后,在SettingCell.m里初始化开关并注册ValueChanged事件,在switchStateChange:方法里调用代理方法传递开关状态:
1 - (UISwitch *)switchView2 {3 if (_switchView ==nil) {4 _switchView =[[UISwitch alloc] init];5 [_switchView addTarget:self action:@selector(switchStateChange:) forControlEvents:UIControlEventValueChanged];6 }7 return_switchView;8 }9
10 /**11 * 监听开关状态改变12 */
13 - (void)switchStateChange:(UISwitch *)switchView14 {15 //NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];16 //[defaults setBool:self.switchView.isOn forKey:self.item.title];17 //[defaults synchronize];
18 if ([self.delegaterespondsToSelector:@selector(settingCell:switchChanged:)]) {19 [self.delegatesettingCell:self switchChanged:switchView];20 }21
22 [CoreArchive setBool:self.switchView.isOn key:self.item.title];23 }
最后,在图2的控制器里实现代理方法:
1 - (void)settingCell:(SettingCell *)cell switchChanged:(UISwitch *)switchView2 {3 NSLog(@"手势密码开关状态改变了-------------------");4 }
但是发现点击开关后并没有发现打印结果,窘迫~
检查代理模式的使用方法后发现是没有设置SettingCell的代理为当前控制器(GestureViewController)。问题又来了,在图2的控制器里我根本拿不到SettingCell,无奈只好追本溯源,发现这个控制器又是继承自自定义的一个控制器(BaseSettingViewController),故在父类控制器里的Cell初始化方法里设置代理为当前控制器即可(下面代码第11行)。于是开心地看到打印结果鸟!
1 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath2 {3 //1.创建cell
4 SettingCell *cell =[SettingCell cellWithTableView:tableView];5
6 //2.给cell传递模型数据
7 SettingGroup *group =self.data[indexPath.section];8 cell.item =group.items[indexPath.row];9 cell.lastRowInSection = (group.items.count - 1 ==indexPath.row);10 //设置代理
11 cell.delegate =self;12 //3.返回cell
13 returncell;14 }
总结思路:
涉及到跨控制器数据访问时首先考虑代理模式;
当类的继承关系复杂时一定要缕清关系:什么事在基类里统一做,什么事在子类里单独做。