函数响应式编程及ReactiveObjC学习笔记 (四)
今天我们继续看其他的类别
UIImagePickerController+RACSignalSupport.h
#import <UIKit/UIKit.h> @class RACDelegateProxy; @class RACSignal<__covariant ValueType>; NS_ASSUME_NONNULL_BEGIN @interface UIImagePickerController (RACSignalSupport) @property (nonatomic, strong, readonly) RACDelegateProxy *rac_delegateProxy; - (RACSignal<NSDictionary *> *)rac_imageSelectedSignal; @end NS_ASSUME_NONNULL_END
可以看到它有一个代理属性, 一个信号
再看下它有帮我们代理哪些方法
- (RACSignal *)rac_imageSelectedSignal { RACSignal *pickerCancelledSignal = [[self.rac_delegateProxy signalForSelector:@selector(imagePickerControllerDidCancel:)] merge:self.rac_willDeallocSignal]; RACSignal *imagePickerSignal = [[[[self.rac_delegateProxy signalForSelector:@selector(imagePickerController:didFinishPickingMediaWithInfo:)] reduceEach:^(UIImagePickerController *pickerController, NSDictionary *userInfo) { return userInfo; }] takeUntil:pickerCancelledSignal] setNameWithFormat:@"%@ -rac_imageSelectedSignal", RACDescription(self)]; RACUseDelegateProxy(self); return imagePickerSignal; }
一个取消按钮的代理, 一个选择完毕的代理,
我们用来试试看
// 创建一个RACDelegateProxy RACDelegateProxy *imgPickerDelegateProxy = [[RACDelegateProxy alloc] initWithProtocol:@protocol(UIImagePickerControllerDelegate)]; // 绑定取消代理事件 [[imgPickerDelegateProxy rac_signalForSelector:@selector(imagePickerControllerDidCancel:)] subscribeNext:^(RACTuple * _Nullable x) { NSLog(@"取消代理: %@", x); UIImagePickerController *imgPicker = x[0]; [imgPicker dismissViewControllerAnimated:YES completion:nil]; }]; // 绑定选择完毕事件 [[imgPickerDelegateProxy rac_signalForSelector:@selector(imagePickerController:didFinishPickingImage:editingInfo:)] subscribeNext:^(RACTuple * _Nullable x) { NSLog(@"选择完成: %@", x); self.view.backgroundColor = [UIColor colorWithPatternImage:x[1]]; UIImagePickerController *imgPicker = x[0]; [imgPicker dismissViewControllerAnimated:YES completion:nil]; }]; // 创建UIImagePickerController UIImagePickerController *imgPickerController = [[UIImagePickerController alloc] init]; imgPickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; imgPickerController.allowsEditing = YES; // 设置代理为我们创建的delegateProxy // 这里注意一般UIImagePickerController需要实现UIImagePickerDelegate & UINavigationControllerDelegate, 但这里用RAC自带的方法只能设置一个代理 // 不过其实RAC其实也只为UIImagePickerController处理了UIImagePickerControllerDelegate而已, 所以这里会有警告先不管它 // 后面我们再想想其他方式, 是重新写一个UIImagePickerController分类还是重写方法什么的 imgPickerController.delegate = (id<UIImagePickerControllerDelegate>)imgPickerDelegateProxy; // retain delegateProxy objc_setAssociatedObject(imgPickerController, _cmd, imgPickerDelegateProxy, OBJC_ASSOCIATION_RETAIN_NONATOMIC); [self presentViewController:imgPickerController animated:YES completion:nil];
这里大家需要注意下红色字体部分,
点击取消返回的x是imgPickerController本身, 转义后直接拿来dismiss即可
选择图片后x是一个数组, 第一个是imgPickerComtroller, 第二个是选择的image
UISegmentedControl+RACSignalSupport.h
#import <UIKit/UIKit.h> @class RACChannelTerminal<ValueType>; NS_ASSUME_NONNULL_BEGIN @interface UISegmentedControl (RACSignalSupport) - (RACChannelTerminal<NSNumber *> *)rac_newSelectedSegmentIndexChannelWithNilValue:(nullable NSNumber *)nilValue; @end NS_ASSUME_NONNULL_END
可以把分段选择器的选择结果直接绑定给其他空间, 或者拿去做别的 实例代码如下:
// 创建一个UISegementController UISegmentedControl *segmentController = [[UISegmentedControl alloc] initWithItems:@[@"One", @"Two"]]; segmentController.frame = CGRectMake(0, 0, 160, 40); segmentController.center = self.view.center; [self.view addSubview:segmentController]; // 创建一个UITextField UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 200, 40)]; textField.center = CGPointMake(self.view.center.x, self.view.center.y + 100); textField.layer.borderWidth = 1; textField.layer.borderColor = [UIColor blueColor].CGColor; [self.view addSubview:textField]; // 获取segement的channelTerminal RACChannelTerminal *segmentTerminal = [segmentController rac_newSelectedSegmentIndexChannelWithNilValue:0]; // 获取textField的channelTerminal RACChannelTerminal *textFieldTerminal = [textField rac_newTextChannel]; // 把segementdeterminal结果处理后绑定给textfieldTerminal [[segmentTerminal map:^id _Nullable(id _Nullable value) { if ([value isEqual: @(1)]) { return @"选择了: Two"; } else { return @"选择了: One"; } }] subscribe:textFieldTerminal];
UISlider+RACSignalSupport.h
#import <UIKit/UIKit.h> @class RACChannelTerminal<ValueType>; NS_ASSUME_NONNULL_BEGIN @interface UISlider (RACSignalSupport) - (RACChannelTerminal<NSNumber *> *)rac_newValueChannelWithNilValue:(nullable NSNumber *)nilValue; @end NS_ASSUME_NONNULL_END
跟UISegement一样, 我们直接给上代码:
// 创建一个UISlider UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(0, 0, 200, 35)]; slider.center = self.view.center; [self.view addSubview:slider]; // 创建一个UITextField UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 200, 40)]; textField.center = CGPointMake(self.view.center.x, self.view.center.y + 100); textField.layer.borderWidth = 1; textField.layer.borderColor = [UIColor blueColor].CGColor; [self.view addSubview:textField]; // 获取slider的channelTerminal RACChannelTerminal *sliderTerminal = [slider rac_newValueChannelWithNilValue:0]; // 获取textField的channelTerminal RACChannelTerminal *textFieldTerminal = [textField rac_newTextChannel]; [[sliderTerminal map:^id _Nullable(id _Nullable value) { return [NSString stringWithFormat:@"%@", value]; }] subscribe:textFieldTerminal];
运行截图:
UIStepper+RACSignalSupport.h
#import <UIKit/UIKit.h> @class RACChannelTerminal<ValueType>; NS_ASSUME_NONNULL_BEGIN @interface UIStepper (RACSignalSupport) - (RACChannelTerminal<NSNumber *> *)rac_newValueChannelWithNilValue:(nullable NSNumber *)nilValue; @end NS_ASSUME_NONNULL_END
也是只有一个RACChannelTerminal, 我们直接上代码:
// 创建一个UIStepper UIStepper *stepper = [[UIStepper alloc] initWithFrame:CGRectMake(0, 0, 80, 35)]; stepper.center = self.view.center; [self.view addSubview:stepper]; // 创建一个UITextField UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 200, 40)]; textField.center = CGPointMake(self.view.center.x, self.view.center.y + 100); textField.layer.borderWidth = 1; textField.layer.borderColor = [UIColor blueColor].CGColor; [self.view addSubview:textField]; // 获取stepper的channelTerminal RACChannelTerminal *stepperTerminal = [stepper rac_newValueChannelWithNilValue:0]; // 获取textField的channelTerminal RACChannelTerminal *textFieldTerminal = [textField rac_newTextChannel]; [[stepperTerminal map:^id _Nullable(id _Nullable value) { return [NSString stringWithFormat:@"%@", value]; }] subscribe:textFieldTerminal];
运行截图:
UISwitch+RACSignalSupport.h
#import <UIKit/UIKit.h> @class RACChannelTerminal<ValueType>; NS_ASSUME_NONNULL_BEGIN @interface UISwitch (RACSignalSupport) - (RACChannelTerminal<NSNumber *> *)rac_newOnChannel; @end NS_ASSUME_NONNULL_END
示例:
// 创建一个UISwitch UISwitch *aswitch = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 60, 35)]; aswitch.center = self.view.center; [self.view addSubview:aswitch]; // 创建一个UITextField UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 200, 40)]; textField.center = CGPointMake(self.view.center.x, self.view.center.y + 100); textField.layer.borderWidth = 1; textField.layer.borderColor = [UIColor blueColor].CGColor; [self.view addSubview:textField]; // 获取aswitch的channelTerminal RACChannelTerminal *aswitchTerminal = [aswitch rac_newOnChannel]; // 获取textField的channelTerminal RACChannelTerminal *textFieldTerminal = [textField rac_newTextChannel]; [[aswitchTerminal map:^id _Nullable(id _Nullable value) { if ([value boolValue]) { return @"1"; } return @"0"; }] subscribe:textFieldTerminal];
UITableViewCell+RACSignalSupport.h
#import <UIKit/UIKit.h> @class RACSignal<__covariant ValueType>; @class RACUnit; NS_ASSUME_NONNULL_BEGIN @interface UITableViewCell (RACSignalSupport) @property (nonatomic, strong, readonly) RACSignal<RACUnit *> *rac_prepareForReuseSignal; @end NS_ASSUME_NONNULL_END
有一个rac_prepareForReuseSignal属性, 看字面意思就很清除准备复用时调用
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"]; if (!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"]; } cell.textLabel.text = @"cell"; [[cell rac_prepareForReuseSignal] subscribeNext:^(RACUnit * _Nullable x) { NSLog(@"开始复用"); }]; return cell; }
UITableViewHeaderFooterView+RACSignalSupport.h
#import <UIKit/UIKit.h> @class RACSignal<__covariant ValueType>; @class RACUnit; NS_ASSUME_NONNULL_BEGIN // This category is only applicable to iOS >= 6.0. @interface UITableViewHeaderFooterView (RACSignalSupport) @property (nonatomic, strong, readonly) RACSignal<RACUnit *> *rac_prepareForReuseSignal; @end NS_ASSUME_NONNULL_END
这个也是一样就不举例了
今天先看这些, 后面我们再继续