ReactiveCocoa代码实践之-UI组件的RAC信号操作

相关阅读:

ReactiveCocoa代码实践之-更多思考

ReactiveCocoa代码实践之-RAC网络请求重构这一节是自己对网络层的一些重构,本节是自己一些代码小实践做出的一些demo程序,基本涵盖大多数UI控件操作。

一.用UISlider实现调色板

假设我们现在做一个demo,上面有一个View用来展示颜色,下面有三个UISlider滑竿分别控制RGB的色值,随着不同滑竿的拖动上面view的颜色会随之改变。 可以先脑补一下不用RAC该怎么写。 如果使用RAC只需要将三个信号包装起来用适当的操作就能实现。

// 拖线的UI控件 @property (weak, nonatomic) IBOutlet UIView *topView; @property (weak, nonatomic) IBOutlet UISlider *slider; @property (weak, nonatomic) IBOutlet UISlider *slider; @property (weak, nonatomic) IBOutlet UISlider *slider; // viewDidLoad中 // 分别将三个控件的改变都包成一个信号。 RACSignal *s = [[self.slider rac_newValueChannelWithNilValue:@]startWith:@]; RACSignal *s = [[self.slider rac_newValueChannelWithNilValue:@]startWith:@]; RACSignal *s = [[self.slider rac_newValueChannelWithNilValue:@]startWith:@]; RACSignal *threeSignal = [RACSignal combineLatest:@[s,s,s] reduce:^id(NSNumber* value,NSNumber* value,NSNumber* value){ return @[value,value,value]; }]; // 监听这个"合成"后的信号,改变view的颜色 [threeSignal subscribeNext:^(NSArray *arr) { self.topView.backgroundColor = [UIColor colorWithRed:[arr[] doubleValue] green:[arr[] doubleValue] blue:[arr[] doubleValue] alpha:]; }];

上面的startWith:@0需要注意,如果不加这个初始值那必须在三个滑竿都动一下才能显示颜色。 上面使用的方法时UISlider专属的,也可以用下面的方法写,这个是UIControl的方法会支持更多其他UI控件。

RACSignal *s1 = [[[self.slider1 rac_signalForControlEvents:UIControlEventValueChanged] map:^id(id value) { return @(self.slider1.value); }] startWith:@0];

二.简洁代码实现登录逻辑

在UI控件中难点不多,但是值得注意的就是各种状态的多级管理,如果哪里疏忽了就很容易造成bug,这也就导致很多地方有判断结构,并且各种来回赋值。 假设现在需要做一个登录框,有账号密码和同意条款三项,必须满足账号密码大于2位且选择了同意,才允许注册。 旧的写法非常麻烦,还需要监听valueChange事件等。如果用RAC只需要写如下代码:

@property (weak, nonatomic) IBOutlet UITextField *accountTxt; @property (weak, nonatomic) IBOutlet UITextField *pwdTxt; @property (weak, nonatomic) IBOutlet SXSwitch *agreeSw; // 同意条款 @property (weak, nonatomic) IBOutlet UIButton *loginBtn; // 注册按钮 // viewDidLoad方法 self.loginBtn.enabled = NO; RAC(self.loginBtn , enabled) = [RACSignal combineLatest:@[self.accountTxt.rac_textSignal , self.pwdTxt.rac_textSignal, self.agreeSw.rac_newOnChannel] reduce:^(NSString *account, NSString *pwd, NSNumber *isOn){ return @((account.length > )&&(pwd.length >)&&[isOn boolValue]); }];

这其中combineLatest数组中用的都是控件专属的信号, 也可以使用RAC(self.agreeSw, on) 这种写法直接把某一个属性的状态用信号传过来。但是这里需要注意:假设你监听了A类的B属性时,只有走了B属性的set方法才会被监听捕获,如果是通过其他方法修改的属性值则无效。 比如UISwitch的来回拨动过程中并没有走on这个属性的set方法。

三.通过interval方法实现时钟

这是一种默认循环的方法,除非你通过控制Disposable把他禁了。 interval这个方法就是传入一个参数是间隔时间,然后内部每隔这一段时间就发一个[NSDate date]的对象,然后block内部把这个date设置一个格式以字符串的方法返回。

RAC(self, timeLabel.text) = [[[RACSignal interval: onScheduler:[RACScheduler currentScheduler]] startWith:[NSDate date]] map:^id (NSDate *value) { NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond fromDate:value]; return [NSString stringWithFormat:@"%ld:%ld:%ld", (long)dateComponents.hour, (long)dateComponents.minute, (long)dateComponents.second]; }];

四.其他控件事件操作

除了上面的UIButton,UISlider,UIControl的分类方法还有很多操作

UISegmentedControl (RACSignalSupport)分类就为此控件提供了便捷处理方法,相比于常规的监听seg的元素点击事件,再取出当前选中的index。RACSignal可以直接得到需要的值

[[self.seg rac_newSelectedSegmentIndexChannelWithNilValue:@]subscribeNext:^(id x) { // 返回的基本数据类型都被装包成NSNumber,可在此做一些判断操作 NSLog(@"selectIndex-%@",x); }];

UIDatePicker (RACSignalSupport)分类为时间选择框封装了一个操作,每当选框改变时返回NSDate类型

[[picker rac_newDateChannelWithNilValue:[NSDate date]]subscribeNext:^(NSDate *x) { NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; dateFormatter.dateFormat = @"HH:mm"; dateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"]; NSString *dateStr = [dateFormatter stringFromDate:x]; }];

如果在这里给控件赋值,每一次改动都会让展示控件的值更新,如果有的设计不希望这么频繁只有在点击确认后再将时间显示可以根据自己喜好自行赋值。

除此这些还有很多UI控件绑定的方法 UIAlertView (RACSignalSupport) 里面就提供了一些方法比如点击弹窗按钮可以在subscribeNext里统一处理各个按钮的点击事件。 但是现在UIAlertView已被UIAlertController取代所以,UIAlertView和UIActionSheet这里可以忽略不提。

五.生命周期相关操作

UITableView和UICollectionView的Cell都有重用的机制,如果给这个Cell绑定了一些监听,那这个Cell被重用它子控件的监听该何去何从?UITableViewCell (RACSignalSupport)、UICollectionReusableView (RACSignalSupport)这两个分类里提供了即将重用时的信号rac_prepareForReuseSignal

做过两个类似的场景,一个是tableView的cell回复按钮点击会跳到回复页,一个是collection的item内有个按钮点击就变颜色。

// UITableViewDataSource - (UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath { SXFeedbackCell * cell = [tableView dequeueReusableCellWithIdentifier:@"SXFeedbackCell"]; @weakify(self) [[[cell.replyButton rac_signalForControlEvents:UIControlEventTouchUpInside] takeUntil:cell.rac_prepareForReuseSignal] subscribeNext:^(UIButton *x) { @strongify(self) // 处理一些其他逻辑 [self.navigationController pushViewController:[SXReplyPage new] animated:YES]; }]; return cell; } // UICollectionViewDataSource - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { UICollectionViewCell * cell = [collectionView dequeueReusableCellWithIdentifier:@"SXDownloadCell"]; [[[cell.changeBtn rac_signalForControlEvents:UIControlEventTouchUpInside] takeUntil:cell.rac_prepareForReuseSignal] subscribeNext:^(UIButton *x) { cell.backgroundColor = [UIColor grayColor]; }]; return cell; }

其中takeUntil操作是监听某个事件直到什么时候结束。当这个cell即将重用时rac_prepareForReuseSignal到来会触发disposable信号结束监听。

非重用类型的控件的生命周期可以用rac_willDeallocSignal 信号监听,但是在开发中很少会用到此信号,因为大多是信号操作的内部代码里都帮你做了这个操作,即监听一个事件直到自己结束时停止监听。

// rac_textSignal源码 - (RACSignal *)rac_textSignal { @weakify(self); return [[[[[RACSignal defer:^{ @strongify(self); return [RACSignal return:self]; }] concat:[self rac_signalForControlEvents:UIControlEventAllEditingEvents]] map:^(UITextField *x) { return x.text; }] takeUntil:self.rac_willDeallocSignal] setNameWithFormat:@"%@ -rac_textSignal", self.rac_description]; } // rac_signalForControlEvents源码 - (RACSignal *)rac_signalForControlEvents:(UIControlEvents)controlEvents { @weakify(self); return [[RACSignal createSignal:^(id<RACSubscriber> subscriber) { @strongify(self); [self addTarget:subscriber action:@selector(sendNext:) forControlEvents:controlEvents]; [self.rac_deallocDisposable addDisposable:[RACDisposable disposableWithBlock:^{ [subscriber sendCompleted]; }]]; return [RACDisposable disposableWithBlock:^{ @strongify(self); [self removeTarget:subscriber action:@selector(sendNext:) forControlEvents:controlEvents]; }]; }] setNameWithFormat:@"%@ -rac_signalForControlEvents: %lx", self.rac_description, (unsigned long)controlEvents]; }

关于ReactiveCocoa代码实践之-UI组件的RAC信号操作就给大家介绍这么多,希望对大家有所帮助!

时间: 2024-08-31 23:53:55

ReactiveCocoa代码实践之-UI组件的RAC信号操作的相关文章

ReactiveCocoa代码实践之-UI组件的RAC信号操作_Android

相关阅读: ReactiveCocoa代码实践之-更多思考 ReactiveCocoa代码实践之-RAC网络请求重构这一节是自己对网络层的一些重构,本节是自己一些代码小实践做出的一些demo程序,基本涵盖大多数UI控件操作. 一.用UISlider实现调色板 假设我们现在做一个demo,上面有一个View用来展示颜色,下面有三个UISlider滑竿分别控制RGB的色值,随着不同滑竿的拖动上面view的颜色会随之改变. 可以先脑补一下不用RAC该怎么写. 如果使用RAC只需要将三个信号包装起来用适

ReactiveCocoa代码实践之-更多思考

相关阅读: ReactiveCocoa代码实践之-UI组件的RAC信号操作 ReactiveCocoa代码实践之-RAC网络请求重构 1. RACObserve()宏形参写法的区别 之前写代码考虑过 RACObserve(self.timeLabel , text) 和 RACObserve(self , timeLabel.text) 的区别. 因为这两种方法都是观察self.timeLabel.text的属性,并且都能实现功能.估计是作者原本用的其中一种后来对另一种也提供了支持,究竟有什么区

ReactiveCocoa代码实践之-RAC网络请求重构_Android

相关阅读: ReactiveCocoa代码实践之-UI组件的RAC信号操作 ReactiveCocoa代码实践之-更多思考 前言 •RAC相比以往的开发模式主要有以下优点:提供了统一的消息传递机制:提供了多种奇妙且高效的信号操作方法:配合MVVM设计模式和RAC宏绑定减少多端依赖. •RAC的理论知识非常深厚,包含有FRP,高阶函数,冷信号与热信号,RAC Operation,信号的生命周期等,这些文档里都有介绍. 但是由于RAC本身的特性,可能会听上去容易上手难. •本文还是从一个比较接地气的

ReactiveCocoa代码实践之-更多思考_Android

相关阅读: ReactiveCocoa代码实践之-UI组件的RAC信号操作 ReactiveCocoa代码实践之-RAC网络请求重构 1. RACObserve()宏形参写法的区别 之前写代码考虑过 RACObserve(self.timeLabel , text) 和 RACObserve(self , timeLabel.text) 的区别. 因为这两种方法都是观察self.timeLabel.text的属性,并且都能实现功能.估计是作者原本用的其中一种后来对另一种也提供了支持,究竟有什么区

XCoreRedux框架:Android UI组件化与Redux实践

XCoreRedux框架:Android UI组件化与Redux实践 @author: 莫川 https://github.com/nuptboyzhb/ XCoreRedux源码+Demo:https://github.com/nuptboyzhb/XCoreRedux 使用android studio打开该项目. 目录结构 demo 基于xcore框架写的一个小demo xcore XCoreRedux核心代码库 pics 文档的pic资源 前言 Android开发当中的Code Archi

《Java数字图像处理:编程技巧与应用实践》——第3章 基本Swing UI组件与图像显示 3.1 JPanel组件与BufferedImage对象的显示

第3章 基本Swing UI组件与图像显示 上一章介绍了BufferedImageOp的一些重要知识,实现了几个常见的图像特效,本章介绍如何通过Swing UI组件显示与刷新图像.首先会介绍JAVA Swing的顶层组件JFrame,然后介绍Swing中最重要和使用频率最高的组件JPanel,教会读者重写JComponent中的paintComponent()方法来实现图像的显示,最后会介绍Swing组件JButton捕获与监听用户行为时最重要的ActionListener接口的使用,以及在Sw

基于Web标准的UI组件 — 菜单(1)

web|web标准|菜单 UI Components Based on Web Standards - Menu (1) 菜单(Menu)是最基本最常见的网页UI元素之一,它的主要功能包括: 引导用户发现网站的内容: 协助用户执行某一特定的操作. 一个完整的菜单是一组菜单项(Menu Item)的集合,所有的菜单项在逻辑上应该是并列.平级的关系,它们指向相互之间没有隶属关系的内容或功能. 菜单项可以是链接,也可以是另一组菜单项的集合,即二级菜单(Sub-Menu). 菜单项的文案设计 明了:把意

iView 1.0 正式版 ,43 个 UI 组件助力中后台业务开发

iView 已经从最初的高质量 UI 组件库,逐步过渡到了从工程构建.主题定制.多语言.设计规范的一整套的前端解决方案.主要服务于中后台业务,目的就是让网站快速成型上线. 1.0 都有哪些新特性 先看一下目前支持的组件情况: 常用的组件包括了:Grid 栅格.提醒类(Message.Notice).模态 Modal.表格 Table.级联选择.输入框.表单验证.单选.多选.下拉选择.滑块.上传.日期时间选择.分页.导航菜单等. 除了基本组件外,1.0 还加了很多新东西: 常用布局 Layout

前端开发框架UI组件和Javascript插件

文章简介:支持响应式设计的流行前端开发框架. 在几年前,并没有真正意义上的前端开发.随着网络技术的发展,网站和 Web 应用程序变得越来越复杂,前端部分的工作独立出来逐渐成为现在的前端开发.如今,我们可以看到越来越多的公司在招聘前端开发岗位. 前端开发并不容易,除了掌握基本的 HTML.CSS 和 Javascript 之外,因为不同版本的浏览器和平台,你需要知道如何做一个跨浏览器的网站.而最新的发展趋势--响应式设计,它不仅使 Web 项目开发更难,也需要花费更多的开发时间. 不过,有很多优秀