Post

Introduction to RAC Core Classes

Introduction to RAC core classes

Introduction to RAC Core Classes

Introduction to RAC Core Classes

RACTuple

SuperclassNSObject 
SubclassesNone 
MeaningRAC tuple class 
Protocols<NSCopying> <NSCoding> <NSFastEnumeration> 
PropertiesNSUInteger countNumber of elements
id first;First element in the tuple 
id second;Second element in the tuple 
id thirdThird element in the tuple 
id fourthFourth element in the tuple 
id fifthFifth element in the tuple 
id lastLast 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

SuperclassNSObject
SubclassesRACImmediateScheduler
RACQueueScheduler 
RACSubscriptionScheduler 
RACTestScheduler 
MeaningRAC scheduler class
ProtocolsNone
PropertiesNone

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

SuperclassNSObject 
SubclassesNone 
Protocols<NSCopying> 
PropertiesRACEventType eventTypeEvent type
BOOL finishedWhether finished 
NSError *errorError information 
id valueAssociated 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

SuperclassNSObject
SubclassesNone
MeaningRAC delegate proxy class
ProtocolsNone
PropertiesRACDelegateProxy *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).

This post is licensed under CC BY 4.0 by the author.