RAC常用的方法滑凉,搭配@weakify(self); @weakify(self);
- 通知
# RAC中的通知不需要手動remove observer,其內(nèi)部已經(jīng)實現(xiàn)
@weakify(self);
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:kNotificationName object:nil]
subscribeNext:^(NSNotification * _Nullable x) {
@strongify(self);
}];
- control
# control的通用方法
@weakify(self);
[[button rac_signalForControlEvents:UIControlEventTouchUpOutside] subscribeNext:^(__kindof UIControl * _Nullable x) {
@strongify(self);
}];
# 監(jiān)聽textfild的UIControlEventEditingChanged事件
# 方式一:
[[textFild rac_signalForControlEvents:UIControlEventEditingChanged] subscribeNext:^(__kindof UIControl * _Nullable x){
NSLog(@"change");
}];
# 方式二:
[[self.textFild rac_textSignal] subscribeNext:^(NSString *x) {
NSLog(@"%@",x);
}];
//這樣就是每次改變TextFild都輸出改變后的結(jié)果
- Gesturer
# 再比如給我們的某個label添加一個手勢動作贫橙,我們也可以用簡單的RAC代碼完成
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] init];
[[tap rac_gestureSignal] subscribeNext:^(__kindof UIGestureRecognizer * _Nullable x) {
NSLog(@"tap");
}];
[self.view addGestureRecognizer:tap];
- 代理
用RAC寫代理是有局限的贪婉,它只能實現(xiàn)返回值為void的代理方法,
RAC為我們提供了一個rac_signalForSelector: fromProtoc:方法幫我們實現(xiàn)代理
# alert方式一:
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"RAC" message:@"RAC TEST" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"other", nil];
[[self rac_signalForSelector:@selector(alertView:clickedButtonAtIndex:) fromProtocol:@protocol(UIAlertViewDelegate)] subscribeNext:^(RACTuple *tuple) {
# tuple封裝了方法的參數(shù),可以取出參數(shù)對應(yīng)的值
NSLog(@"%@",tuple.first);
#可以看出tuple.second是點擊Item的Index
NSLog(@"%@",tuple.second);
NSLog(@"%@",tuple.third);
}];
[alertView show];
#查看RACTuple
@interface RACTuple : NSObject <NSCoding, NSCopying, NSFastEnumeration>
@property (nonatomic, readonly) NSUInteger count;
/// These properties all return the object at that index or nil if the number of
/// objects is less than the index.
@property (nonatomic, readonly, nullable) id first;
@property (nonatomic, readonly, nullable) id second;
@property (nonatomic, readonly, nullable) id third;
@property (nonatomic, readonly, nullable) id fourth;
@property (nonatomic, readonly, nullable) id fifth;
@property (nonatomic, readonly, nullable) id last;
2021-03-19 12:24:29.114 RACStudyTest[5003:388870] <UIAlertView: 0x7ff260c90c70; frame = (0 0; 0 0); layer = <CALayer: 0x7ff260c91030>>
2021-03-19 12:24:29.115 RACStudyTest[5003:388870] 1
2021-03-19 12:24:29.115 RACStudyTest[5003:388870] (null)
# alert方式二
[[alertView rac_buttonClickedSignal] subscribeNext:^(id x) {
# 這里的x是點擊Item的Index
NSLog(@"%@",x);
}];
- kvo
RAC中得KVO大部分都是宏定義卢肃,所以代碼異常簡潔疲迂,簡單來說就是 RACObserve(TARGET, KEYPATH)這種形式,TARGET是監(jiān)聽目標莫湘,KEYPATH是要觀察的屬性值
@weakify(self);
[RACObserve(object, propertyChanged) subscribeNext:^(id propertyChangedValue) {
@strongify(self);
}];
[[RACSignal combineLatest:@[RACObserve(self.messageViewController, unReadMessageCount),RACObserve(self.friendsVc, unReadMessageCount),RACObserve(self, unReadSystemCount)]] subscribeNext:^(RACTuple *x) {
@strongify(self);
NSInteger first = ((NSNumber *)x.first).integerValue;
NSInteger second = ((NSNumber *)x.second).integerValue;
NSInteger third = ((NSNumber *)x.third).integerValue;
JHTabBarController *tabbarVC = (JHTabBarController *)self.tabBarController;
[tabbarVC.customTabBar hideBadgeOnItemIndex:3];//隱藏未讀小紅點
if (first>0||second>0||third>0) {
[tabbarVC.customTabBar showBadgeOnItemIndex:3 value:(first+second+third)];//顯示未讀小紅點
}
}];
RACSignal 封裝請求
- (RACSignal *)sendShareMessageWithModel:(JH_ChatRoomBaseModel *)messageModel {
@weakify(self);
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
@strongify(self);
[self addMessageModelToDatabase:messageModel];
//通過Socket向服務(wù)器發(fā)送消息
[self sendMessageToServerWithModel:messageModel];
// 給訂閱者發(fā)送消息
[subscriber sendNext:@(YES)];
[subscriber sendCompleted];
return nil;
}];
}
RAC相關(guān)類
RACSignal的使用
// 創(chuàng)建一個信號
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
NSLog(@"創(chuàng)建一個信號");
// 發(fā)送信號
[subscriber sendNext:@"發(fā)送一個信號"];
return nil;
}];
// 訂閱一個信號
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"訂閱一個信號");
NSLog(@"訂閱到的: %@", x);
}];
2017-07-22 17:37:09.294 RAC[66282:12633516] 創(chuàng)建一個信號
2017-07-22 17:37:09.295 RAC[66282:12633516] 訂閱一個信號
2017-07-22 17:37:09.295 RAC[66282:12633516] 訂閱到的: 發(fā)送一個信號
sendNext就把內(nèi)容傳遞到了Next的block中了
UITextField+RACSignalSupport.h
#import <UIKit/UIKit.h>
@class RACChannelTerminal<ValueType>;
@class RACSignal<__covariant ValueType>;
NS_ASSUME_NONNULL_BEGIN
#
@interface UITextField (RACSignalSupport)
#
- (RACSignal<NSString *> *)rac_textSignal;
# 用于雙向綁定
- (RACChannelTerminal<NSString *> *)rac_newTextChannel;
@end
NS_ASSUME_NONNULL_END
rac_textSignal
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 35)];
textField.center = self.view.center;
textField.backgroundColor = [UIColor yellowColor];
[[textField
rac_textSignal]
subscribeNext:^(NSString * _Nullable x) {
NSLog(@"%@", x);
}];
[self.view addSubview:textField];
2017-07-23 22:55:45.686 RAC[70205:14118946] 1
2017-07-23 22:55:46.139 RAC[70205:14118946] 11
2017-07-23 22:55:46.798 RAC[70205:14118946] 111
rac_newTextChannel
@interface RACChannelTerminal<ValueType> : RACSignal<ValueType> <RACSubscriber>
- (instancetype)init __attribute__((unavailable("Instantiate a RACChannel instead")));
// Redeclaration of the RACSubscriber method. Made in order to specify a generic type.
- (void)sendNext:(nullable ValueType)value;
@end
#rac_newTextChannel效果跟rac_textSignal一樣, 那么它有什么特別的用法呢?
[[textField
rac_newTextChannel]
subscribeNext:^(NSString * _Nullable x) {
NSLog(@"%@", x);
}];
#rac_newTextChannel雙向綁定
UITextField *textFieldA = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 35)];
textFieldA.center = self.view.center;
textFieldA.backgroundColor = [UIColor yellowColor];
[self.view addSubview:textFieldA];
UITextField *textFieldB = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 35)];
textFieldB.center = CGPointMake(self.view.center.x, self.view.center.y + 50);
textFieldB.backgroundColor = [UIColor yellowColor];
[self.view addSubview:textFieldB];
RACChannelTerminal *terminalA = [textFieldA rac_newTextChannel];
RACChannelTerminal *terminalB = [textFieldB rac_newTextChannel];
[terminalA subscribe:terminalB];
[terminalB subscribe:terminalA];
#運行可以看到, 改變textFieldA的值textFieldB的值也會跟著改變, 反過來也一樣.
#這里如果要實現(xiàn)雙向綁定, 其實還有一個簡單的方法:
RACChannelTo(textFieldA, text) = RACChannelTo(textFieldB, text);
如果我們不僅僅想讓兩個綁定對象之間的值簡單的相等而已呢? 比如textFieldA的值是123的時候textFieldB的值要為321要怎么處理呢?
這里我們先說一個一會用到的方法: map
(映射)
map
方法尤蒿,將會創(chuàng)建一個和原來一模一樣的信號,只不過新的信號傳遞的值變?yōu)榱薭lock(value)幅垮。
[[[textField
rac_textSignal]
map:^id _Nullable(NSString * _Nullable value) {
if ([value isEqualToString:@"11"]) {
return @"1";
} else {
return @"0";
}
}] subscribeNext:^(id _Nullable x) {
NSLog(@"%@", x);
}];
運行看看, 當(dāng)我們輸入1, 會打印0, 輸入11的時候會打印1, 這里就是把傳遞的值從textField的text轉(zhuǎn)變成為我們的1 和 0;
那么要實現(xiàn)上面的123 到 321可以這樣寫:
RACChannelTerminal *terminalA = [textFieldA rac_newTextChannel];
RACChannelTerminal *terminalB = [textFieldB rac_newTextChannel];
[[terminalA
map:^id _Nullable(id _Nullable value) {
if ([value isEqualToString:@"123"]) {
return @"321";
}
return value;
}]
subscribe:terminalB];
[terminalB subscribe:terminalA];
大家可以自己運行看看效果, 當(dāng)textFieldA輸入123的時候textFieldB會變?yōu)?21
RAC(self.sureBtn, enabled) = [RACSignal combineLatest:@[self.phoneTF.rac_textSignal, self.codeTF.rac_textSignal] reduce:^id (NSString *phoneNumber, NSString *code){
@strongify(self);
if (phoneNumber.length==11 && code.length==6) {
self.sureBtn.alpha = 1;
return @(YES);
} else {
self.sureBtn.alpha = 0.6;
return @(NO);
}
}];
UIActionSheet+RACSignalSupport.h
#import <UIKit/UIKit.h>
@class RACDelegateProxy;
@class RACSignal<__covariant ValueType>;
NS_ASSUME_NONNULL_BEGIN
@interface UIActionSheet (RACSignalSupport)
@property (nonatomic, strong, readonly) RACDelegateProxy *rac_delegateProxy;
- (RACSignal<NSNumber *> *)rac_buttonClickedSignal;
@end
rac_buttonClickedSignal
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"RAC ActionSheet" delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:@"OK" otherButtonTitles:@"Other", nil];
[[actionSheet
rac_buttonClickedSignal]
subscribeNext:^(NSNumber * _Nullable x) {
NSLog(@"%@", x);
}];
[actionSheet showInView:self.view];
#運行看看, x是actionSheet上按鈕的編號, 我們拿到編號就可以做響應(yīng)的事件處理了.
UIAlertView+RACSignalSupport.h
@interface UIAlertView (RACSignalSupport)
@property (nonatomic, strong, readonly) RACDelegateProxy *rac_delegateProxy;
- (RACSignal<NSNumber *> *)rac_buttonClickedSignal;
- (RACSignal<NSNumber *> *)rac_willDismissSignal;
@end
NS_ASSUME_NONNULL_END
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"RAC" message:@"RAC Alert" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];
[[alert
rac_buttonClickedSignal]
subscribeNext:^(NSNumber * _Nullable x) {
NSLog(@"click: x");
}];
[[alert
rac_willDismissSignal]
subscribeNext:^(NSNumber * _Nullable x) {
NSLog(@"dismiss: %@", x);
}];
[alert show];
UIControl+RACSignalSupport.h
#import <UIKit/UIKit.h>
@class RACSignal<__covariant ValueType>;
NS_ASSUME_NONNULL_BEGIN
@interface UIControl (RACSignalSupport)
- (RACSignal<__kindof UIControl *> *)rac_signalForControlEvents:(UIControlEvents)controlEvents;
@end
NS_ASSUME_NONNULL_END
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setFrame:CGRectMake(0, 0, 100, 35)];
[button setCenter:self.view.center];
[button setBackgroundColor:[UIColor yellowColor]];
[button setTitle:@"按鈕" forState:UIControlStateNormal];
[[button
rac_signalForControlEvents:UIControlEventTouchUpInside]
subscribeNext:^(__kindof UIControl * _Nullable x) {
NSLog(@"點擊了按鈕");
x.backgroundColor = [UIColor redColor];
}];
[self.view addSubview:button];
UIDatePicker+RACSignalSupport.h
#import <UIKit/UIKit.h>
@class RACChannelTerminal<ValueType>;
NS_ASSUME_NONNULL_BEGIN
@interface UIDatePicker (RACSignalSupport)
- (RACChannelTerminal<NSDate *> *)rac_newDateChannelWithNilValue:(nullable NSDate *)nilValue;
@end
NS_ASSUME_NONNULL_END
UIDatePicker *datePicker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 160)];
datePicker.center = self.view.center;
datePicker.backgroundColor = [UIColor redColor];
[self.view addSubview:datePicker];
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 180, 35)];
textField.center = CGPointMake(self.view.center.x, self.view.center.y - 100);
textField.backgroundColor = [UIColor yellowColor];
[self.view addSubview:textField];
RACChannelTerminal *datePickerTerminal = [datePicker rac_newDateChannelWithNilValue:[NSDate date]];
RACChannelTerminal *textFieldTerminal = [textField rac_newTextChannel];
[[datePickerTerminal
map:^id _Nullable(id _Nullable value) {
NSLog(@"%@", value);
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
return [dateFormatter stringFromDate:value];
}]
subscribe:textFieldTerminal];