Introduction to RAC Core Classes
Introduction to RAC core classes
Introduction to RAC Core Classes
RACTuple
| Superclass | NSObject | |
|---|---|---|
| Subclasses | None | |
| Meaning | RAC tuple class | |
| Protocols | <NSCopying> <NSCoding> <NSFastEnumeration> | |
| Properties | NSUInteger count | Number of elements |
id first; | First element in the tuple | |
id second; | Second element in the tuple | |
id third | Third element in the tuple | |
id fourth | Fourth element in the tuple | |
id fifth | Fifth element in the tuple | |
id last | Last element in the tuple |
Example
1
2
3
4
[[self rac_signalForSelector:@selector(tabBarController:didSelectViewController:) fromProtocol:@protocol(UITabBarControllerDelegate)] subscribeNext:^(RACTuple *tuple) {
NSLog(@"%@", tuple.first);
NSLog(@"%@", tuple.second);
}];
1
2
3
[[RACSignal combineLatest:@[self.textView.rac_textSignal]] subscribeNext:^(id x) {
NSLog(@"%@", [x class]);
}];
Methods
1. Initialize a RACTuple from an array
1
+ (instancetype)tupleWithObjectsFromArray:(NSArray *)array;
2. Initialize a RACTuple from an array
1
+ (instancetype)tupleWithObjectsFromArray:(NSArray *)array convertNullsToNils:(BOOL)convert;
If convert is set to YES, NSNull values will be converted to RACTupleNil.
3. Initialize a RACTuple from a variable list of objects
1
+ (instancetype)tupleWithObjects:(id)object, ... NS_REQUIRES_NIL_TERMINATION;
4. Return all elements as an array
1
- (NSArray *)allObjects;
5. Add an element
1
- (instancetype)tupleByAddingObject:(id)obj;
RACScheduler
| Superclass | NSObject |
|---|---|
| Subclasses | RACImmediateScheduler |
RACQueueScheduler | |
RACSubscriptionScheduler | |
RACTestScheduler | |
| Meaning | RAC scheduler class |
| Protocols | None |
| Properties | None |
Example Display an image downloaded from the network
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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]];
Start a request immediately on a background thread, then deliver it to the main thread to update the UI.
Signal delivery
1
2
3
- (RACSignal *)deliverOn:(RACScheduler *)scheduler;
The returned RACSignal is subscribed to immediately.
1
+ (RACSignal *)startEagerlyWithScheduler:(RACScheduler *)scheduler block:(void (^)(id<RACSubscriber> subscriber))block;
Methods
1. Return the main thread scheduler
1
+ (RACScheduler *)mainThreadScheduler;
2. Return the current scheduler
1
+ (RACScheduler *)currentScheduler;
3. Return the default scheduler
1
+ (RACScheduler *)scheduler;
Equivalent to
1
[RACScheduler schedulerWithPriority:RACSchedulerPriorityDefault];
4. Return an asynchronous concurrent scheduler with the specified priority
1
+ (RACScheduler *)schedulerWithPriority:(RACSchedulerPriority)priority;
This actually calls
1
[[RACTargetQueueScheduler alloc] initWithName:name targetQueue:dispatch_get_global_queue(priority, 0)];
In fact, the superclass of RACTargetQueueScheduler is RACQueueScheduler, which has the following method:
1
2
3
4
5
6
7
8
9
- (RACDisposable *)schedule:(void (^)(void))block {
NSCParameterAssert(block != NULL);
RACDisposable *disposable = [[RACDisposable alloc] init];
dispatch_async(self.queue, ^{
if (disposable.disposed) return;
[self performAsCurrentScheduler:block];
});
return disposable;
}
You can see that it ultimately uses dispatch_async for asynchronous execution. __
RACEvent
| Superclass | NSObject | |
|---|---|---|
| Subclasses | None | |
| Protocols | <NSCopying> | |
| Properties | RACEventType eventType | Event type |
BOOL finished | Whether finished | |
NSError *error | Error information | |
id value | Associated value |
RACEventType includes
1
2
3
4
5
typedef enum : NSUInteger {
RACEventTypeCompleted,
RACEventTypeError,
RACEventTypeNext
} RACEventType;
Example
1
2
3
4
5
6
7
8
9
10
11
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"1"];
[subscriber sendNext:@"43"];
[subscriber sendNext:@"3"];
[subscriber sendCompleted];
return nil;
}];
[[signal materialize] subscribeNext:^(RACEvent *event) {
NSLog(@"value--%@ eventType--%d", event.value, event.eventType);
}];
- (RACSignal *)materialize; delivers the information received by the signal in the form of a RACEvent.
1
2
3
4
2014-07-03 14:05:24.972 RAC-Demo[6528:60b] value--1 eventType--2
2014-07-03 14:05:24.973 RAC-Demo[6528:60b] value--2 eventType--2
2014-07-03 14:05:24.974 RAC-Demo[6528:60b] value--3 eventType--2
2014-07-03 14:05:24.974 RAC-Demo[6528:60b] value--(null) eventType--0
RACDelegateProxy
| Superclass | NSObject |
|---|---|
| Subclasses | None |
| Meaning | RAC delegate proxy class |
| Protocols | None |
| Properties | RACDelegateProxy *rac_delegateProxy; |
This class may not be used very often in day-to-day work. For example, when there are multiple UITextField instances in a screen, but each needs different behavior in delegate methods, or some methods need to be implemented while others do not.
1
2
3
4
5
6
7
8
9
RACDelegateProxy *delegateProxy = [[RACDelegateProxy alloc]initWithProtocol:@protocol(UITextFieldDelegate)];
[[delegateProxy rac_signalForSelector:@selector(textFieldShouldReturn:)] subscribeNext:^(RACTuple *args) {
UITextField *field = [args first];
[field resignFirstResponder];
}];
self.textfield.delegate = (id<UITextFieldDelegate>)delegateProxy;
objc_setAssociatedObject(self.textfield, _cmd, delegateProxy, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
The code snippet above explicitly specifies that self.textfield’s - (BOOL)textFieldShouldReturn:(UITextField *)textField; method will be executed. It is also important to note that delegateProxy may be released unexpectedly and cause a crash, so it needs to be retained. That is what the last line does. Although this class is not especially useful in most real-world usage, it is used internally by RAC in places such as UITextView (RACSignalSupport) and UIAlertView (RACSignalSupport).