ReactiveCocoa基础知识内容2
引用网络上一些实例的代码,针对ReactiveCocoa的运用可以更加有帮助;
1:跟AF结合时的写法,返回RACSignal
- (RACSignal *)fetchQuestionWithTag:(NSString *)tag {
NSString *relativeURL = [NSString stringWithFormat:@"http://api.stackexchange.com/2.1/questions/?site=stackoverflow&order=desc&sort=hot&tagged=%@", tag];
RACSignal *signal =
[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
AFHTTPRequestOperation *operation = [
[AFHTTPRequestOperationManager manager]
GET:relativeURL
parameters:nil
success:^(AFHTTPRequestOperation *operation, NSDictionary *responseObject) {
[subscriber sendNext:responseObject[@"items"]];
[subscriber sendCompleted];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error){
[subscriber sendError:error];
}];
return [RACDisposable disposableWithBlock:^{
[operation cancel];
}];
}];
return signal;
}
2:RACCommand的运用,作为事件响应
定义一个ViewModel @interface SubscribeViewModel : NSObject @property(nonatomic, strong) RACCommand *subscribeCommand; // write to this property
@property(nonatomic, strong) NSString *email; // read from this property
@property(nonatomic, strong) NSString *statusMessage; @end
@property(nonatomic, strong) RACSignal *emailValidSignal;
实现代码:
- (RACCommand *)subscribeCommand {
if (!_subscribeCommand) {
@weakify(self);
_subscribeCommand = [[RACCommand alloc] initWithEnabled:self.emailValidSignal signalBlock:^RACSignal *(id input) {
@strongify(self);
return [SubscribeViewModel postEmail:self.email];
}];
}
return _subscribeCommand;
}
+ (RACSignal *)postEmail:(NSString *)email {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer new];
NSDictionary *body = @{@"email": email ?: @""};
return [[[manager rac_POST:kSubscribeURL parameters:body] logError] replayLazily];
}
- (RACSignal *)emailValidSignal {
if (!_emailValidSignal) {
_emailValidSignal = [RACObserve(self, email) map:^id(NSString *email) {
return @([email isValidEmail]);
}];
}
return _emailValidSignal;
}
调用绑定:
- (void)bindWithViewModel {
RAC(self.viewModel, email) = self.emailTextField.rac_textSignal;
self.subscribeButton.rac_command = self.viewModel.subscribeCommand;
RAC(self.statusLabel, text) = RACObserve(self.viewModel, statusMessage);
}
- (UITextField *)emailTextField {
if (!_emailTextField) {
_emailTextField = [UITextField new];
_emailTextField.borderStyle = UITextBorderStyleRoundedRect;
_emailTextField.font = [UIFont boldSystemFontOfSize:];
_emailTextField.placeholder = NSLocalizedString(@"Email address", nil);
_emailTextField.keyboardType = UIKeyboardTypeEmailAddress;
_emailTextField.autocapitalizationType = UITextAutocapitalizationTypeNone;
}
return _emailTextField;
}
- (UIButton *)subscribeButton {
if (!_subscribeButton) {
_subscribeButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[_subscribeButton setTitle:NSLocalizedString(@"Subscribe", nil) forState:UIControlStateNormal];
}
return _subscribeButton;
}
- (UILabel *)statusLabel {
if (!_statusLabel) {
_statusLabel = [UILabel new];
}
return _statusLabel;
}
说明:RACCommand类用于表示事件的执行,一般来说是在UI上的某些动作来触发这些事件,比如点击一个按钮。RACCommand的实例能够决定是否可以被执行,这个特性能反应在UI上,而且它能确保在其不可用时不会被执行。通常,当一个命令可以执行时,会将它的属性allowsConcurrentExecution设置为它的默认值:NO,从而确保在这个命令已经正在执行的时候,不会同时再执行新的操作。命令执行的返回值是一个RACSignal,因此我们能对该返回值进行next:,completed或error:,
3:关于RACObserve的用法
监听对象的成员变量变化,当成员变量值被改变时,触发做一些事情。 这种情况其实就是IOS KVO机制使用的场景,使用KVO实现,通常有三个步骤:1,给对象的成员变量添加监听;2,实现监听回调;3,取消监听;而通过RAC可以直接实现,RAC的回调是通过block实现的,类似于过程式编程,上下文也更容易理解一些。
a: 场景:当前类有一个成员变量 NSString *input,当它的值被改变时,发送一个请求。
[RACObserve(self, input)
subscribeNext:^(NSString* x){
request(x);//发送一个请求
}];
说明:每次input值被修改时,就会调用此block,并且把修改后的值做为参数传进来。
b:场景:在上面场景中,当用户输入的值以2开头时,才发请求.
[[RACObserve(self, input)
filter:^(NSString* value){
if ([value hasPrefix:@""]) {
return YES;
} else {
return NO;
}
}]
subscribeNext:^(NSString* x){
request(x);//发送一个请求
}];
c:上面场景是监听自己的成员变量,如果想监听UITextField输入值变化,框架也做了封装可以代替系统回调
[[self.priceInput.rac_textSignal
filter:^(NSString *str) {
if (str.integerValue > ) {
return YES;
} else {
return NO;
}
}]
subscribeNext:^(NSString *str) {
request(x);//发送一个请求
}];
d:场景:button监听 两个输入框有值和一个成员变量值,当输入框有输入且成员变量为真时,button为可点击状态
RAC(self.payButton,enabled) = [RACSignal
combineLatest:@[self.priceInput.rac_textSignal,
self.nameInput.rac_textSignal,
RACObserve(self, isConnected)
]
reduce:^(NSString *price, NSString *name, NSNumber *connect){
return @(price.length > && name.length > && [connect boolValue]);
}];
说明:同时监听多个变量变化,当这些变量满足一定条件时,使button为可点击状态
e:场景:满足上面条件时,直接发送请求
[[RACSignal
combineLatest:@[self.priceInput.rac_textSignal,
self.nameInput.rac_textSignal,
RACObserve(self, isConnected)
]
reduce:^(NSString *price, NSString *name, NSNumber *connect){
return @(price.length > && name.length > && ![connect boolValue]);
}]
subscribeNext:^(NSNumber *res){
if ([res boolValue]) {
NSLog(@"XXXXX send request");
}
}];
f:distinctUntilChanged直到收到不同值才响应,可以过滤掉那些不必要的网络请求等
@weakify(self);
//Start Binding our properties
RAC(self.nameField,text) = [RACObserve(self.viewModel, playerName) distinctUntilChanged];
[[self.nameField.rac_textSignal distinctUntilChanged] subscribeNext:^(NSString *x) {
//this creates a reference to self that when used with @weakify(self);
//makes sure self isn't retained
@strongify(self);
self.viewModel.playerName = x;
}];
4:RACScheduler为RAC调度类(主线程,子线程等)
显示网络下载的图片
RAC(self.imageView, image) = [[RACSignal startEagerlyWithScheduler:[RACScheduler schedulerWithPriority:RACSchedulerPriorityBackground]
block:^(id <RACSubscriber> subscriber) {
NSError *error;
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://ww3.sinaimg.cn/bmiddle/7128be06jw1ei4hfthoj3j20hs0bomyd.jpg"]
options:NSDataReadingMappedAlways
error:&error];
if(error) {
[subscriber sendError:error];
}
else {
[subscriber sendNext:[UIImage imageWithData:data]];
[subscriber sendCompleted];
}
}] deliverOn:[RACScheduler mainThreadScheduler]];
说明:这段代码会在后台线程立即发起一个请求,然后传递到主线程上更新UI,主线程上执行[RACScheduler mainThreadScheduler],信号传递:- (RACSignal *)deliverOn:(RACScheduler *)scheduler
5:控件结合的实例
a:对uibutton添加了一个rac_signalForControlEvents的方式,就不用利用addtarget的方式来再写一个方法来进行对uibutton添加点击事件了。
[[self.testBtn rac_signalForControlEvents:UIControlEventTouchUpInside]
subscribeNext:^(id x) {
TestViewController *testVC = [[TestViewController alloc] init];
[self.navigationController pushViewController:testVC animated:YES];
}];
b:在UIAlertView的使用
UIAlertView *chooseAlert = [[UIAlertView alloc] initWithTitle:@"选择图片上传"message:nil delegate:nil cancelButtonTitle:@"取消"otherButtonTitles:@"拍照上传", @"从相册选择", nil];
[chooseAlert show]; [[chooseAlert rac_buttonClickedSignal] subscribeNext:^(NSNumber *indexNumber) {
if ([indexNumber intValue] == ) {
[self chooseFromCamera];
} else if ([indexNumber intValue] == ) {
[self chooseFromAlbum];
}
}];
c:在UITextfield的使用,self是因为我继承了一个textfield先进行功能添加和封装。所以self就是代指一个textfield了。
[[self rac_signalForControlEvents:UIControlEventEditingDidBegin]
subscribeNext:^(NSNumber *editing) {
self.bottomBorder.backgroundColor = [UIColor blackColor].CGColor;
}];
[[self rac_signalForControlEvents:UIControlEventEditingDidEnd]
subscribeNext:^(NSNumber *editing) {
self.bottomBorder.backgroundColor = [UIColor grayColor].CGColor;
}];
说明:当选择这个框的时候,线会加粗变黑
d:监控UIPagecontrol改变
[RACObserve(self.imagePlayer.pageControl, currentPage) subscribeNext:^(id x) {
[self refreshSlideContent:self.imagePlayer.pageControl.currentPage];
}];
不错的实例代码:
ReactiveCocoa实用案例:http://www.saitjr.com/ios/ios-reactivecocoa-utility-demo.html
ReactiveCocoa基础知识内容2的更多相关文章
- ReactiveCocoa基础知识内容
本文记录一些关于学习ReactiveCocoa基础知识内容,对于ReactiveCocoa相关的概念如果不了解可以网上搜索:RACSignal有很多方法可以来订阅不同的事件类型,ReactiveCoc ...
- 前端三件套 HTML+CSS+JS基础知识内容笔记
HTML基础 目录 HTML基础 HTML5标签 doctype 标签 html标签 head标签 meta标签 title标签 body标签 文本和超链接标签 标题标签 段落标签 换行标签 水平标签 ...
- 第一天上午——HTML网页基础知识以及相关内容
今天上午学习了HTML基础知识以及相关内容,还有DW的基本使用方法. HTML(HyperText Markup Language):超文本标记语言,超文本:网页中除了包含文本文字之外,还包含了图片, ...
- python爬虫主要就是五个模块:爬虫启动入口模块,URL管理器存放已经爬虫的URL和待爬虫URL列表,html下载器,html解析器,html输出器 同时可以掌握到urllib2的使用、bs4(BeautifulSoup)页面解析器、re正则表达式、urlparse、python基础知识回顾(set集合操作)等相关内容。
本次python爬虫百步百科,里面详细分析了爬虫的步骤,对每一步代码都有详细的注释说明,可通过本案例掌握python爬虫的特点: 1.爬虫调度入口(crawler_main.py) # coding: ...
- .NET面试题系列[1] - .NET框架基础知识(1)
很明显,CLS是CTS的一个子集,而且是最小的子集. - 张子阳 .NET框架基础知识(1) 参考资料: http://www.tracefact.net/CLR-and-Framework/DotN ...
- RabbitMQ基础知识
RabbitMQ基础知识 一.背景 RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现.AMQP 的出现其实也是应了广大人民群众的需求,虽然 ...
- Java基础知识(壹)
写在前面的话 这篇博客,是很早之前自己的学习Java基础知识的,所记录的内容,仅仅是当时学习的一个总结随笔.现在分享出来,希望能帮助大家,如有不足的,希望大家支出. 后续会继续分享基础知识手记.希望能 ...
- selenium自动化基础知识
什么是自动化测试? 自动化测试分为:功能自动化和性能自动化 功能自动化即使用计算机通过编码的方式来替代手工测试,完成一些重复性比较高的测试,解放测试人员的测试压力.同时,如果系统有不份模块更改后,只要 ...
- APP测试入门篇之APP基础知识(001)
前言 最近两月比较多的事情混杂在一起,静不下心来写点东西,月初想发表一遍接口测试的总结,或者APP测试相关的内容,一晃就月底了,总结提炼一时半会也整不完.放几个早年总结内部培训PPT出来 ...
随机推荐
- Javascript动画效果(三)
Javascript动画效果(三) 前面我们已经介绍了速度动画.透明度动画.多物体运动和任意值变化,并且我们在Javascript动画效果(二)中介绍到我们封装了一个简单的插件雏形,接下来我们对前面的 ...
- 30天C#基础巩固------了解委托,string练习
---->了解委托. 生活中的例子:我要打官司,我需要找一个律师,法庭上面律师为当事人辩护,它真正执行的是当事人的陈词,这时律师 就相当于一个委托对象.当事人则委托律师为自己辩解. ...
- C语言学习018:strdup复制字符串数组
在C语言学习005:不能修改的字符串中我们知道字符串是存储在常量区域的,将它赋值给数组实际是将常量区的字符串副本拷贝到栈内存中,如果将这个数组赋值给指针,我们可以改变数组中的元素,就像下面那样 int ...
- .Net语言 APP开发平台——Smobiler学习日志:Poplist控件在APP中的应用场景以及代码
最前面的话:Smobiler是一个在VS环境中使用.Net语言来开发APP的开发平台,也许比Xamarin更方便 一.目标样式 我们要实现上图中的效果,需要如下的操作: 1.从工具栏上的”Smobil ...
- 从C#到Objective-C,循序渐进学习苹果开发(4)--代码块(block)和错误异常处理的理解
本随笔系列主要介绍从一个Windows平台从事C#开发到Mac平台苹果开发的一系列感想和体验历程,本系列文章是在起步阶段逐步积累的,希望带给大家更好,更真实的转换历程体验.本文继续上一篇随笔<从 ...
- Jquery请求Ajax的json数据
获得单个json对象 $.getJSON("test.js", { name: "John", time: "2pm" }, funct ...
- MVC之前的那点事儿系列(4):Http Pipeline详细分析(上)
文章内容 继续上一章节的内容,通过HttpApplicationFactory的GetApplicationInstance静态方法获取实例,然后执行该实例的BeginProcessRequest方法 ...
- LocalDB:微软的新生代轻量级数据库
什么是LocalDB 随着SQL Server 2012的发布,LocalDB跃入我们的视线,它可以被看做是SQL Server Express的轻量级版本.LocalDB专门为开发人员创建,它非常易 ...
- Android使用SAX解析XML(3)
主界面MainActivity.java: package com.hzhi.my_sax; import java.util.ArrayList; import android.os.Bundle; ...
- Myeclipse打开是 报:failed to create jvm的解决办法
一.方法1 1.打开文件 2.更改大小 二.办法2 关闭QQ或者杀毒软件