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

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

@property (nonatomic, strong) SettingItem *item;

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

         

图1                                                             图2

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

 #import <UIKit/UIKit.h>

 @class SettingItem, SettingCell;

 @protocol SettingCellDelegate <NSObject>

 @optional

 // 监听开关状态改变
- (void)settingCell:(SettingCell *)cell switchChanged:(UISwitch *)switchView; @end @interface SettingCell : UITableViewCell // 存放模型数据
@property (nonatomic, strong) SettingItem *item; @property (nonatomic, assign, getter = isLastRowInSection) BOOL lastRowInSection; + (instancetype)cellWithTableView:(UITableView *)tableView; // 定义代理属性
@property (nonatomic, weak) id<SettingCellDelegate> delegate; @end

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

 - (UISwitch *)switchView
{
if (_switchView == nil) {
_switchView = [[UISwitch alloc] init];
[_switchView addTarget:self action:@selector(switchStateChange:) forControlEvents:UIControlEventValueChanged];
}
return _switchView;
} /**
* 监听开关状态改变
*/
- (void)switchStateChange:(UISwitch *)switchView
{
// NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
// [defaults setBool:self.switchView.isOn forKey:self.item.title];
// [defaults synchronize];
if ([self.delegate respondsToSelector:@selector(settingCell:switchChanged:)]) {
[self.delegate settingCell:self switchChanged:switchView];
} [CoreArchive setBool:self.switchView.isOn key:self.item.title];
}

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

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

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

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

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 1.创建cell
SettingCell *cell = [SettingCell cellWithTableView:tableView]; // 2.给cell传递模型数据
SettingGroup *group = self.data[indexPath.section];
cell.item = group.items[indexPath.row];
cell.lastRowInSection = (group.items.count - == indexPath.row);
// 设置代理
cell.delegate = self;
// 3.返回cell
return cell;
}

总结思路:

  • 涉及到跨控制器数据访问时首先考虑代理模式;
  • 当类的继承关系复杂时一定要缕清关系:什么事在基类里统一做,什么事在子类里单独做。

iOS:使用代理模式监听开关状态改变事件的更多相关文章

  1. 原生js监听input值改变事件

    哈哈哈,又来了,今天闲来无事,实验了下原生js监听input value值改变事件,下面就来说道说道: 本来写监听input值便获是用jquery的,之前的随笔写了,就是这个方法,地址:http:// ...

  2. ios电话拨打进行监听电话状态

    #import "ViewController.h" #import <CoreTelephony/CTCallCenter.h> #import <CoreTe ...

  3. js实现监听浏览器窗口大小改变事件

    window.onresize = function(){   }

  4. IOS-网络(监听网络状态)

    // // BWNetWorkTool.h // IOS_0131_检测网络状态 // // Created by ma c on 16/1/31. // Copyright © 2016年 博文科技 ...

  5. IOS-利用AFNetworking监听网络状态

    网络环境检测:检测用户当前所处的网络状态 效果图 1.当蜂窝和wifi同时关闭时候  显示为不可达(AFNetworkReachabilityStatusNotReachable)状态 2.打开蜂窝移 ...

  6. (原创)用Receiver和SystemService监听网络状态,注册Receiver的两种方式

    android中网络编程不可避免地要监听网络状态,wifi或者3G以及以太网,并根据当前状态做出相应决策. 在MyReceiver类中的onReceive方法中获得系统服务 ConnectivityM ...

  7. Android实时监听网络状态(2)

    在开发android应用时,涉及到要进行网络访问,时常需要进行网络状态的检查,以提供给用户必要的提醒.一般可以通过ConnectivityManager来完成该工作. ConnectivityMana ...

  8. Android实时监听网络状态

    Android实时监听网络状态(1)   其实手机在网络方面的的监听也比较重要,有时候我们必须实时监控这个程序的实时网络状态,android在网络断开与连接的时候都会发出广播,我们通过接收系统的广播就 ...

  9. Android监听电池状态

    监听电池状态只需要接收Intent.ACTION_BATTERY_CHANGED的广播即可,当电池状态发生变化时会发出广播. 1.运行状态如下图: (1)连接USB时的状态 (2)断开USB时的状态 ...

随机推荐

  1. GDB的深入研究

    GDB的深入研究 一.GDB代码调试 (一)GDB调试实例 在终端中编译一个示例C语言小程序,保存为文件 gdblianxi.c 中,用GCC编译. 在上面的命令行中,使用-o参数指定了编译生成的可执 ...

  2. Logstash学习-plugin安装

    Usage: bin/logstash-plugin [OPTIONS] SUBCOMMAND [ARG] ... Parameters: SUBCOMMAND subcommand [ARG] .. ...

  3. php如何在某个时间上加一天?一小时? 时间加减

    <?php date_default_timezone_set('PRC'); //默认时区 echo "今天:",date("Y-m-d",time() ...

  4. 每天一点Android干货-Activity的生命周期

    Activity Activity是这样一个程序组件,它为用户提供一个用于任务交互的画面. 一个应用程序通常由多个activity组成,它们彼此保持弱的绑定状态.典型的,当一个activity在一个应 ...

  5. noi 6047 分蛋糕

    题目链接:http://noi.openjudge.cn/ch0405/6047/ 和Uva1629很类似,不过,可能用记忆化难写一点,状态初始化懒得搞了.就用循环好了. 状态描叙也可以修改,那个题目 ...

  6. PHP优化笔记

    1.指定display_function内容,用来禁用危险参数 2.指定display_errors = Off 来关闭错误显示 3.这个和上一条有因果关系,关闭了错误前台显示,但是要记录错误信息就必 ...

  7. [LeetCode_3] Longest Substring Without Repeating Characters

    LeetCode: 3. Longest Substring Without Repeating Characters class Solution { public: int lengthOfLon ...

  8. JMeter入门使用指南

    初识JMeter 最近开始接触和使用JMeter进行性能测试,也是因为工作需要,不得不学习更多新技能,在此之前一直使用LR进行WEB系统的压力测试,但是在ZK开发的WEB系统,我选择使用JMeter. ...

  9. [原]调试ComFriendlyWaitMtaThreadProc崩溃

    项目里安装了UIA相关的钩子来监听UIA相关事件,退出的时候偶尔会崩溃在ComFriendlyWaitMtaThreadProc中,如下  从上图可以看出 是访问到无效的地址了,用!address 0 ...

  10. DllImport attribute的总结

    C#有没有方法可以直接都用已经存在的功能(比如Windows中的一些功能,C++中已经编写好的一些方法),而不需要重新编写代码? 答案是肯定,就是通过接下来要说的 DllImport . DllImp ...