foreplay
Personally, I highly recommend ReactiveCocoa, which is just like Chinese Tai chi. Tai Chi gives birth to two instruments, two instruments give birth to four images, four images give birth to eight diagrams, and the eight diagrams give birth to everything. ReactiveCocoa is a highly abstract programming framework. It’s really abstract. At first you don’t know what it does.
I won’t talk about the principles of ReactiveCocoa here, because abstraction is something that can’t be explained clearly. I’m not going to mention the concept. I’m just showing you how much fun I have with it. Forty-eight hands of code
Examine the value
Don’t move. I’ll know when you move.
1. @weakify(self);
2. [RACObserve(self, value) subscribeNext:^(NSString* x) {
3. @strongify(self);
NSLog(@” you moved “); 4.
5.}];
unilateral
You sing, I dance.
The size of the textField’s content is implied as a BOOL and is bound to the confirmButton enable attribute.
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(idsubscriber) {
[subscriber sendNext:@” sing “];
[subscriber sendCompleted];
returnnil;
}];
RAC(self, value) = [signalA map:^id(NSString* value) {
If ([value isEqualToString:@” sing “]) {
Return @ “dance”;
}
return@””;
}];
bilateral
If you go west, he goes east; if he goes left, you go right.
RACChannelTerminal *channelA = RACChannelTo(self, valueA);
RACChannelTerminal *channelB = RACChannelTo(self, valueB);
[[channelA map:^id(NSString *value) {
If ([value isEqualToString:@” west “]) {
Return @ “east”;
}
return value;
}] subscribe:channelB];
[[channelB map:^id(NSString *value) {
If ([value isEqualToString:@” left “]) {
Return @ “right”;
}
return value;
}] subscribe:channelA];
[[RACObserve(self, valueA) filter:^BOOL(id value) {
return value ? YES : NO;
}] subscribeNext:^(NSString* x) {
NSLog(@” you go to %@”, x);
}];
[[RACObserve(self, valueB) filter:^BOOL(id value) {
return value ? YES : NO;
}] subscribeNext:^(NSString* x) {
NSLog(@” he goes to %@”, x);
}];
Self. valueA = @” west “;
Self. valueB = @” left “;
[2440:99901] You are heading west
[2440:99901] He goes east
[2440:99901] He left
[2440:99901] You go to the right
The agent
You’re a programmer. Help me write an app.
@protocol Programmer
– (void)makeAnApp;
@end
RACSignal *ProgrammerSignal =
[self rac_signalForSelector:@selector(makeAnApp)
fromProtocol:@protocol(Programmer)];
[ProgrammerSignal subscribeNext:^(RACTuple* x) {
NSLog(@” Took a month, app wrote it “);
}];
[self makeAnApp];
radio
Knowing your channel, I can hear you.
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:@” Code channel “object:nil] subscribeNext:^(NSNotification* x) {
NSLog(@” tip: %@”, x.usserinfo [@” tip “]);
}];
[[NSNotificationCenter defaultCenter] postNotificationName:@” Code path channel “object:nil userInfo:@{@” tip “:@” write by heart “}];
2015-08-15 20:41:15.786 Test[2734:111505
The connection
Life is one story after another.
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(idsubscriber) {
[subscriber sendNext:@” I’m in love “];
[subscriber sendCompleted];
returnnil;
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(idsubscriber) {
[subscriber sendNext:@” I’m married “];
[subscriber sendCompleted];
returnnil;
}];
[[signalA concat:signalB] subscribeNext:^(id x) {
NSLog(@”%@”,x);
}];
[1845.64122] I’m in love
[1845.64122] I’m married
merge
All sewage should flow into sewage treatment plants to be treated.
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(idsubscriber) {
[subscriber sendNext:@” paper factory sewage “];
return nil;
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(idsubscriber) {
[subscriber sendNext:@” Electroplating plant sewage “];
return nil;
}];
[[RACSignal merge:@[signalA, signalB]] subscribeNext:^(id x) {
NSLog (@ “% @”, x);
}];
22015-08-15 12:10:05.371 Test[1770:60147] Treatment of wastewater from paper factory
Test[1770:60147] Treatment of wastewater from electroplating plant
combination
You are red, I am yellow, we are red and yellow, you are white, I do not change, we are white and yellow.
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(idsubscriber) {
[the subscriber sendNext: @ “red”);
[the subscriber sendNext: @ “white”];
return nil;
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(idsubscriber) {
[the subscriber sendNext: @ “white”];
return nil;
}];
[[RACSignal combineLatest:@[signalA, signalB]] subscribeNext:^(RACTuple* x) {
RACTupleUnpack(NSString *stringA, NSString *stringB) = x;
NSLog(@” We are %@%@ “, stringA, stringB);
}];
[1808:62042] We are red and yellow
[1808:62042] We are white and yellow
The compression
You are red, I am yellow, we are red and yellow, you are white, I haven’t changed, oh, let’s wait until I change.
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(idsubscriber) {
[the subscriber sendNext: @ “red”);
[the subscriber sendNext: @ “white”];
return nil;
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(idsubscriber) {
[the subscriber sendNext: @ “white”];
return nil;
}];
[[signalA zipWith:signalB] subscribeNext:^(RACTuple* x) {
RACTupleUnpack(NSString *stringA, NSString *stringB) = x;
NSLog(@” We are %@%@ “, stringA, stringB);
}];
[2660:108483] We are red and white
mapping
I can turn everything INTO gold.
RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(idsubscriber) {
[the subscriber sendNext: @ “stone”);
returnnil;
}] map:^id(NSString* value) {
If ([value isEqualToString:@” “]) {
Return @ “gold”;
}
returnvalue;
}];
[signal subscribeNext:^(id x) {
NSLog(@”%@”, x);
}];
The 2015-08-16 20:00:12. 853 Test (740-15871)
Sugar adds water to sugar water.
RACSignal *sugarSignal = [RACSignal createSignal:^RACDisposable *(idsubscriber) {
[the subscriber sendNext: @ “sugar”];
returnnil;
}];
RACSignal *waterSignal = [RACSignal createSignal:^RACDisposable *(idsubscriber) {
[the subscriber sendNext: @ “water”];
returnnil;
}];
[[RACSignal combineLatest:@[sugarSignal, waterSignal] reduce:^id (NSString* sugar, NSString*water){
return[sugar stringByAppendingString:water];
}] subscribeNext:^(id x) {
NSLog(@”%@”, x);
}];
[807:19177] Sugar water
filter
Under 18, no entry.
[[[RACSignal createSignal:^RACDisposable *(idsubscriber) {
[subscriber sendNext:@(15)];
[subscriber sendNext:@(17)];
[subscriber sendNext:@(21)];
[subscriber sendNext:@(14)];
[subscriber sendNext:@(30)];
returnnil;
}] filter:^BOOL(NSNumber* value) {
returnvalue.integerValue >= 18;
}] subscribeNext:^(id x) {
NSLog(@”%@”, x);
}];
The 2015-08-16 20:11:20. 071 Test (860-21214) 21
The 2015-08-16 20:11:20. 071 Test [860-21214] 30
flat
Whisk eggs, fry eggs, serve.
[[[[RACSignal createSignal:^RACDisposable *(idsubscriber) {
NSLog(@” whisk “);
[subscriber sendNext:@” egg “];
[subscriber sendCompleted];
return nil;
}] flattenMap:^RACStream *(NSString* value) {
return [RACSignal createSignal:^RACDisposable *(idsubscriber) {
NSLog(@” put %@ in the pan “,value);
[subscriber sendNext:@” fried egg “];
[subscriber sendCompleted];
return nil;
}];
}] flattenMap:^RACStream *(NSString* value) {
return [RACSignal createSignal:^RACDisposable *(idsubscriber) {
NSLog(@” put %@ on a disk “, value);
[subscriber sendNext:@” Serve “];
[subscriber sendCompleted];
return nil;
}];
}] subscribeNext:^(id x) {
NSLog(@”%@”, x);
}];
2015-08-16 20:39:34.786 Test[1226:34386] Beat egg mixture
Pour the eggs into the pan and fry them
Put the fried eggs on a plate
2015-08-16 20:39:34.787 Test[1226:34386] serve
order
There are only three steps to getting an elephant in the fridge: open the fridge door, put the elephant in the fridge, and close the fridge door.
[[[[RACSignal createSignal:^RACDisposable *(idsubscriber) {
NSLog(@” open refrigerator door “);
[subscriber sendCompleted];
returnnil;
}] then:^RACSignal *{
return[RACSignal createSignal:^RACDisposable *(idsubscriber) {
NSLog(@” Put an elephant in a fridge “);
[subscriber sendCompleted];
returnnil;
}];
}] then:^RACSignal *{
return[RACSignal createSignal:^RACDisposable *(idsubscriber) {
NSLog(@” close the fridge door “);
[subscriber sendCompleted];
returnnil;
}];
}] subscribeCompleted:^{
NSLog(@” Stuffed elephant in freezer “);
}];
[1334:37870] Open the refrigerator door
[1334:37870] Put an elephant in a refrigerator
[1334:37870] Close the refrigerator door
[1334:37870] Stuffed the elephant in the refrigerator
The command
I order you to surrender immediately.
RACCommand *aCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
return[RACSignal createSignal:^RACDisposable *(idsubscriber) {
NSLog(@” I surrender “);
[subscriber sendCompleted];
returnnil;
}];
}];
[aCommand execute:nil];
delay
Wait up. I’ll be there in 10 seconds.
[[[RACSignal createSignal:^RACDisposable *(idsubscriber) {
NSLog(@” Wait for me, I’ll be there in 10 seconds “);
[subscriber sendNext:nil];
[subscriber sendCompleted];
returnnil;
}] delay:10] subscribeNext:^(id x) {
NSLog(@” I’m here “);
}];
Wait for me. I’ll be there in 10 seconds
[1619:45924] Here I am
The replay
Make once, watch many times.
RACSignal *replaySignal = [[RACSignal createSignal:^RACDisposable *(idsubscriber) {
NSLog(@” The big director made a movie called My Boyfriend is a Programmer “);
[subscriber sendNext:@” My boyfriend is a programmer “];
returnnil;
}] replay];
[replaySignal subscribeNext:^(id x) {
NSLog(@” xiao Ming saw %@”, x);
}];
[replaySignal subscribeNext:^(id x) {
NSLog(at sign “red also saw % at sign “, x);
}];
[1854:54712] A great director made a film called my Boyfriend is a Programmer.
[1854:54712] [2015-08-16 21:18:38.004] Test[1854:54712]
[1854:54712] Xiao Hong also watched my Boyfriend is a Programmer
set
timing
Take the medicine every eight hours.
[[RACSignal interval:60*60*8 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(id x) {
NSLog (@ “medicine”);
}];
timeout
I’ve been waiting for you for an hour. You still haven’t shown up. I’m leaving.
[[[RACSignal createSignal:^RACDisposable *(idsubscriber) {
[[[RACSignal createSignal:^RACDisposable *(idsubscriber) {
NSLog(@” I’m almost there “);
[subscriber sendNext:nil];
[subscriber sendCompleted];
returnnil;
}] delay:60*70] subscribeNext:^(id x) {
[subscriber sendNext:nil];
[subscriber sendCompleted];
}];
returnnil;
}] timeout:60*60 onScheduler:[RACScheduler mainThreadScheduler]] subscribeError:^(NSError *error) {
NSLog(@” Been waiting for you for an hour, you haven’t come, I’m leaving “);
}];
[2041:64720] I’m almost there
[2041:64720] I’ve been waiting for you for an hour. You still haven’t come. I’m leaving now
retry
It may take hundreds of failures before success.
__block int failedCount = 0;
[[[RACSignal createSignal:^RACDisposable *(idsubscriber) {
if (failedCount < 100) {
failedCount++;
NSLog(@” I failed “);
[subscriber sendError:nil];
}else{
NSLog(@” after hundreds of failures “);
[subscriber sendNext:nil];
}
return nil;
}] retry] subscribeNext:^(id x) {
NSLog(@” Finally made it “);
}];
[2411:77080] I failed the Test
[2411:77080] I failed the Test
[2411:77080] I failed the Test
[2411:77080] I failed the Test
[2411:77080] I failed
[2411:77080] I failed
[2411:77080] I failed
[2411:77080] I failed
.
[2411:77080] I failed
[2411:77080] I failed
[2411:77080] I failed
[2411:77080] I failed
[2411:77080] I failed the Test
[2411:77080] I failed the Test
[2411:77080] I failed the Test
165 Test[2411:77080] after hundreds of failures
Test[2411:77080
The throttle
Sorry, only one person can pass through here at a second.
[[[RACSignal createSignal:^RACDisposable *(idsubscriber) {
[subscriber sendNext:@” passenger A”];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@” passenger B”];
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@” passenger C”];
[subscriber sendNext:@” passenger D”];
[subscriber sendNext:@” passenger E”];
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@” passenger F”];
});
returnnil;
}] throttle:1] subscribeNext:^(id x) {
NSLog(at sign “% at sign passed “,x);
}];
2015-08-16 22:08:45.677 Test[2618:83764] Passenger A
[2618:83764] Passenger B
2015-08-16 22:08:47.822 Test[2618:83764] Passenger E
2015-08-16 22:08:48.920 Test[2618:83764
conditions
Till the end of the world do us part.
[[[RACSignal createSignal:^RACDisposable *(idsubscriber) {
[[RACSignal interval:1 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(id x) {
Subscriber sendNext:@” Till the end of the world to part us “];
}];
returnnil;
}] takeUntil:[RACSignal createSignal:^RACDisposable *(idsubscriber) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@” The end of the world “);
[subscriber sendNext:@” The end of the world “];
});
returnnil;
}]] subscribeNext:^(id x) {
NSLog(@”%@”, x);
}];
Till the end of the world do us part
Till the end of the world do us part
Till the end of the world do us part
Till the end of the world do us part
Till the end of the world do us part
The end of the world had come