iOS:使用代理模式监听开关状态改变事件
记一次解决跨控制器监听开关状态改变的尝试。
为了统一设置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:使用代理模式监听开关状态改变事件的更多相关文章
- 原生js监听input值改变事件
哈哈哈,又来了,今天闲来无事,实验了下原生js监听input value值改变事件,下面就来说道说道: 本来写监听input值便获是用jquery的,之前的随笔写了,就是这个方法,地址:http:// ...
- ios电话拨打进行监听电话状态
#import "ViewController.h" #import <CoreTelephony/CTCallCenter.h> #import <CoreTe ...
- js实现监听浏览器窗口大小改变事件
window.onresize = function(){ }
- IOS-网络(监听网络状态)
// // BWNetWorkTool.h // IOS_0131_检测网络状态 // // Created by ma c on 16/1/31. // Copyright © 2016年 博文科技 ...
- IOS-利用AFNetworking监听网络状态
网络环境检测:检测用户当前所处的网络状态 效果图 1.当蜂窝和wifi同时关闭时候 显示为不可达(AFNetworkReachabilityStatusNotReachable)状态 2.打开蜂窝移 ...
- (原创)用Receiver和SystemService监听网络状态,注册Receiver的两种方式
android中网络编程不可避免地要监听网络状态,wifi或者3G以及以太网,并根据当前状态做出相应决策. 在MyReceiver类中的onReceive方法中获得系统服务 ConnectivityM ...
- Android实时监听网络状态(2)
在开发android应用时,涉及到要进行网络访问,时常需要进行网络状态的检查,以提供给用户必要的提醒.一般可以通过ConnectivityManager来完成该工作. ConnectivityMana ...
- Android实时监听网络状态
Android实时监听网络状态(1) 其实手机在网络方面的的监听也比较重要,有时候我们必须实时监控这个程序的实时网络状态,android在网络断开与连接的时候都会发出广播,我们通过接收系统的广播就 ...
- Android监听电池状态
监听电池状态只需要接收Intent.ACTION_BATTERY_CHANGED的广播即可,当电池状态发生变化时会发出广播. 1.运行状态如下图: (1)连接USB时的状态 (2)断开USB时的状态 ...
随机推荐
- 突击战UVa11729Commando War
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=117&page= ...
- java中的23中设计模式(转)
设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
- Masonry的使用
1.//添加了这个宏,就不用带mas_前缀了 #define MAS_SHORTHAND //添加了这个宏,equalTo就等于mas_equalTo #define MAS_SHORYHAND_G ...
- laravel框架总结(十三) -- redis使用
一切的前提都是已经安装好了redis服务器,并且能启动(我只总结了mac的安装方法:传送门) 我自己使用的是mac系统,有个教程可以参考下,传送门: 1.安装PHP PRedis 1>PRedi ...
- windows server 2012 r2 远程桌面连接指南
具体详情请阅览文档 http://pan.baidu.com/s/1jHTCpW6 windows server 2012 r2 远程桌面连接指南 - 作者 rick·bao - 日期 2016-0 ...
- Redis单机版本的安装
我的是centos-6.5的环境,安装redis的单机版本 1.下载redis源文件redis-3.0.0.tar.gz到一个目录,我的下载目录是/software 2.编译安装源文件的先觉条件是安装 ...
- mysql 数据库 表字段添加表情兼容
项目中的几个需要支持Emoji表情符号,手机自带的表情,其实添加也很简单: 1 修改数据库 配置my.cnf init-connect='SET NAMES utf8mb4' ...
- 1019: [SHOI2008]汉诺塔
1019: [SHOI2008]汉诺塔 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 1495 Solved: 916[Submit][Status] ...
- Java - 安全的退出线程
stop() 存在的问题 使用 stop() 来退出线程是不安全的.它会解除由线程获取的所有锁,可能导致数据不一致. 举个例子: public class StopTest { public stat ...
- dispatch a action with a timeout
程序入口文件添加依赖: import { createStore, applyMiddleware } from 'redux' import thunk from 'redux-thunk' // ...