本demo详见github
1.RAC+MVVM
RAC_MVVM.h
#import <UIKit/UIKit.h>
@interface RAC_MVVM : UIViewController
@end
RAC_MVVM.m
#import "RAC_MVVM.h"
#import <ReactiveObjC.h>
#import "loginViewModel.h"
@interface RAC_MVVM ()
@property (nonatomic,strong)UITextField *accountF;
@property (nonatomic,strong)UITextField *pwdF;
@property (nonatomic,strong)UIButton *loginBtn;
@property(nonatomic, strong)loginViewModel *loginVM;
@end
@implementation RAC_MVVM
- (loginViewModel *)loginVM {
if (!_loginVM) {
_loginVM = [[loginViewModel alloc] init];
}
return _loginVM;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.accountF = [[UITextField alloc]initWithFrame:CGRectMake(10, 100, 200, 40)];
self.accountF.borderStyle = UITextBorderStyleRoundedRect;
[self.view addSubview:self.accountF];
self.accountF.placeholder = @"账号输入";
self.pwdF = [[UITextField alloc]initWithFrame:CGRectMake(10, 200, 200, 40)];
[self.view addSubview:self.pwdF];
self.pwdF.borderStyle = UITextBorderStyleRoundedRect;
self.pwdF.placeholder = @"密码输入";
self.loginBtn = [[UIButton alloc]initWithFrame:CGRectMake(10, 300, 200, 40)];
[self.view addSubview:self.loginBtn];
[self bindViewModel];
[self loginEvent];
}
- (void)bindViewModel {
// 1.给视图模型的账号和密码绑定信号
RAC(self.loginVM, account) = self.accountF.rac_textSignal;
RAC(self.loginVM, pwd) = self.pwdF.rac_textSignal;
}
- (void)loginEvent {
@weakify(self);
// 1.处理文本框业务逻辑--- 设置按钮是否能点击
RAC(self.loginBtn, enabled) = self.loginVM.loginEnableSignal;
[RACObserve(self.loginBtn, enabled) subscribeNext:^(id _Nullable x) {
@strongify(self);
if([x boolValue]==1){
[self.loginBtn setTitle:@"可以点" forState:UIControlStateNormal];
[self.loginBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[self.loginBtn setBackgroundColor:[UIColor greenColor]];
}else{
[self.loginBtn setTitle:@"不可以点" forState:UIControlStateNormal];
[self.loginBtn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
[self.loginBtn setBackgroundColor:[UIColor greenColor]];
}
}];
// 2.监听登录按钮点击
[[self.loginBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
@strongify(self);
NSLog(@"点击登录按钮");
// 处理登录事件
[self.loginVM.loginCommand execute:nil];
}];
}
-(void)dealloc{
NSLog(@"%s",__FUNCTION__);
}
@end
loginViewModel.h
#import <Foundation/Foundation.h>
#import <ReactiveObjC.h>
@interface loginViewModel : NSObject
// 处理按钮是否允许点击
@property(nonatomic, strong, readonly) RACSignal *loginEnableSignal;
/**保存登录界面的账号和密码*/
@property(nonatomic, strong) NSString *account;
@property(nonatomic, strong) NSString *pwd;
//登录按钮的命令
@property(nonatomic, strong, readonly) RACCommand *loginCommand;
@end
loginViewModel.m
#import "loginViewModel.h"
#import <SVProgressHUD.h>
@implementation loginViewModel
-(instancetype)init{
if (self = [super init]) {
[self setup];
}
return self;
}
- (void)setup {
// 1. 处理登录点击的信号
_loginEnableSignal = [RACSignal combineLatest:@[RACObserve(self, account), RACObserve(self, pwd)] reduce:^id(NSString *account, NSString *pwd){
return @(account.length && pwd.length);
}];
// 2.处理登录点击命令
_loginCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
// block调用:执行命令就会调用
// block作用:事件处理
// 发送登录请求
NSLog(@"发送登录请求");
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)),dispatch_get_main_queue(), ^{
// 发送数据
[subscriber sendNext:@"发送登录的数据"];
[subscriber sendCompleted]; // 一定要记得写
});
return nil;
}];
}];
// 3.处理登录的请求返回的结果
// 创建登录命令
// 获取命令中的信号源
[_loginCommand.executionSignals.switchToLatest subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
// 4.处理登录执行过程
[[_loginCommand.executing skip:1] subscribeNext:^(id x) { // 跳过第一步("没有执行"这步)
if ([x boolValue] == YES) {
NSLog(@"--正在执行");
// 显示蒙版
[SVProgressHUD show];
}else { //执行完成
NSLog(@"执行完成");
// 取消蒙版
[SVProgressHUD dismiss];
}
}];
}
@end
2.RAC+MVVM-网络请求
RAC_MVVM_2.m
#import "RAC_MVVM_2.h"
#import "RequestViewModel.h"
#import <ReactiveObjC.h>
@interface RAC_MVVM_2()
//请求视图模型
@property(nonatomic, strong)RequestViewModel *requestVM;
@end
@implementation RAC_MVVM_2
- (RequestViewModel *)requestVM {
if (!_requestVM) {
_requestVM = [[RequestViewModel alloc] init];
}
return _requestVM;
}
-(void)viewDidLoad{
[super viewDidLoad];
RACSignal *signal = [self.requestVM.requestCommand execute:nil];
[signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
}
@end
RequestViewModel.h
#import <Foundation/Foundation.h>
#import <ReactiveObjC.h>
@interface RequestViewModel : NSObject
@property(nonatomic, strong, readonly)RACCommand *requestCommand;
@end
RequestViewModel.m
#import "RequestViewModel.h"
#import <AFNetworking.h>
@implementation RequestViewModel
- (instancetype)init {
if (self = [super init]) {
[self setup];
}
return self;
}
- (void)setup {
_requestCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
// 执行命令
// 发送请求
// 创建信号 把发送请求的代码包装到信号里面。
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:@"https://api.douban.com/v2/book/search" parameters:@{@"q":@"帅哥"} progress:^(NSProgress * _Nonnull downloadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
// 请求成功的时候调用
NSArray *dictArr = responseObject[@"books"];
// 遍历books字典数组,将其映射为模型数组
NSArray *modelArr = [[dictArr.rac_sequence map:^id(id value) {
return [[NSObject alloc] init];
}] array];
[subscriber sendNext:modelArr];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
}];
return nil;
}];
return signal;// 模型数组
}];
}
@end
友情链接:
网友评论