转载

iOS开发:使用代理模式监听开关状态改变事件

记一次解决跨控制器监听开关状态改变的尝试。

为了统一设置UITableViewCell里的内容,自定义了UITableViewCell类的一个基类,命名为SettingCell。SettingCell里显示的内容由数据模型SettingItem提供:在SettingCell里定义一个属性即可。

 @property (nonatomic, strong) SettingItem *item; 

再定义几个SettingItem的子类表示显示不同内容的Cell(如图1).由于所有开关状态的归档和解档都一样,故统一在父类SettingItem里实现。但是点击“手势密码”后跳转到下一个控制(如图2)后,需要单独监听手势密码开关的状态,这就涉及到了跨控制器监听开关状态改变事件的问题。我首先想到了代理模式。

iOS开发:使用代理模式监听开关状态改变事件 iOS开发:使用代理模式监听开关状态改变事件

图1                                                             图2

首先在SettingCell.h里声明代理方法和属性:

  1 #import <UIKit/UIKit.h>  2   3 @class SettingItem, SettingCell;  4   5 @protocol SettingCellDelegate <NSObject>  6   7 @optional  8   9 // 监听开关状态改变 10 - (void)settingCell:(SettingCell *)cell switchChanged:(UISwitch *)switchView; 11  12 @end 13  14 @interface SettingCell : UITableViewCell 15  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<SettingCellDelegate> delegate; 25  26 @end 

然后,在SettingCell.m里初始化开关并注册 ValueChanged事件,在switchStateChange:方法里调用代理方法传递开关状态:

  1 - (UISwitch *)switchView  2 {  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 *)switchView 14 { 15 //    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 16 //    [defaults setBool:self.switchView.isOn forKey:self.item.title]; 17 //    [defaults synchronize]; 18     if ([self.delegate respondsToSelector:@selector(settingCell:switchChanged:)]) { 19         [self.delegate settingCell:self switchChanged:switchView]; 20     } 21      22     [CoreArchive setBool:self.switchView.isOn key:self.item.title]; 23 } 

最后,在图2的控制器里实现代理方法:

 1 - (void)settingCell:(SettingCell *)cell switchChanged:(UISwitch *)switchView 2 { 3     NSLog(@"手势密码开关状态改变了-------------------"); 4 } 

但是发现点击开关后并没有发现打印结果,窘迫~

检查代理模式的使用方法后发现是没有设置SettingCell的代理为当前控制器(GestureViewController)。问题又来了,在图2的控制器里我根本拿不到SettingCell,无奈只好追本溯源,发现这个控制器又是继承自自定义的一个控制器(BaseSettingViewController),故在父类控制器里的Cell初始化方法里设置代理为当前控制器即可(下面代码第11行)。于是开心地看到打印结果鸟!

  1 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath  2 {  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     return cell; 14 } 

iOS开发:使用代理模式监听开关状态改变事件

总结思路:

  • 涉及到跨控制器数据访问时首先考虑代理模式;
  • 当类的继承关系复杂时一定要缕清关系:什么事在基类里统一做,什么事在子类里单独做。
原文  http://www.cnblogs.com/yif1991/p/5162603.html
正文到此结束
Loading...