zoukankan      html  css  js  c++  java
  • iOS:使用代理模式监听开关状态改变事件

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

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

    @property (nonatomic, strong) SettingItem *item;

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

                                           

                                                            图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 }

    总结思路:

    • 涉及到跨控制器数据访问时首先考虑代理模式;
    • 当类的继承关系复杂时一定要缕清关系:什么事在基类里统一做,什么事在子类里单独做。
  • 相关阅读:
    Caffe_Example之训练mnist
    监督学习和无监督学习
    linux 命令cp拷贝
    Caffe solver.prototxt学习
    caffe下python环境的编译
    ubuntu 绘制lenet网络结构图遇到的问题汇总
    1-6 能否形成三角形
    Python的四个内置数据类型list, tuple, dict, set
    Python 函数(二)
    Python 函数(一)
  • 原文地址:https://www.cnblogs.com/yif1991/p/5162603.html
Copyright © 2011-2022 走看看