ReactiveCocoa basic knowledge, reactivecocoa

Source: Internet
Author: User

ReactiveCocoa basic knowledge, reactivecocoa

This article records some basic knowledge about ReactiveCocoa. If you do not know ReactiveCocoa related concepts, you can search online. RACSignal has many ways to subscribe to different event types, the ReactiveCocoa framework uses category to add signal to many basic UIKit controls.

1. Create a page layout first (preparation phase)

@interface ViewController ()@property(strong,nonatomic)UITextField *nameTextField;@property(strong,nonatomic)UILabel *contentLabel;@property(strong,nonatomic)UIButton *saveBtn;@end
If (self. nameTextField = nil) {self. nameTextField = [[UITextField alloc] init]; self. nameTextField. backgroundColor = [UIColor grayColor]; [self. view addSubview: self. nameTextField]; [self. nameTextField mas_makeConstraints: ^ (MASConstraintMaker * make) {make. top. mas_pointer to (self. view. mas_top ). with. offset (64); make. left. mas_pointer to (self. view. mas_left ). with. offset (0); make. right. mas_pointer to (self. view. mas_right ). with. offset (0); make. height. mas_defaults to (@ 40);}];} if (self. contentLabel = nil) {self. contentLabel = [[UILabel alloc] init]; self. contentLabel. backgroundColor = [UIColor blueColor]; [self. view addSubview: self. contentLabel]; [self. contentLabel mas_makeConstraints: ^ (MASConstraintMaker * make) {make. top. mas_pointer to (self. nameTextField. mas_bottom ). with. offset (10); make. left. mas_pointer to (self. view. mas_left ). with. offset (0); make. right. mas_pointer to (self. view. mas_right ). with. offset (0); make. height. mas_defaults to (@ 100);}];} if (self. saveBtn = nil) {self. saveBtn = [[UIButton alloc] init]; self. saveBtn. backgroundColor = [UIColor blackColor]; [self. saveBtn setTitle: @ "Submit" forState: UIControlStateNormal]; [self. view addSubview: self. saveBtn]; [self. saveBtn mas_makeConstraints: ^ (MASConstraintMaker * make) {make. top. mas_pointer to (self. contentLabel. mas_bottom ). with. offset (20); make. left. mas_pointer to (self. view. mas_left ). with. offset (30); make. right. mas_pointer to (self. view. mas_right ). with. offset (-30); make. height. mas_equalTo (@ 40);}];}

Note: saveBtn is the call code without adding events. You can use ReactiveCocoa to register events for it and bind corresponding operations;

Ii. ReactiveCocoa small instance (these are directly bound to viewDidLoad after the control is created)

1: rac_textSignal of UITextField, which generates a signal when the text changes

    [self.nameTextField.rac_textSignal subscribeNext:^(id x) {        self.contentLabel.text=x;    }];

Effect: the input will immediately display the changed value, saving the previous listening operations;

2: filter condition Filtering

    [[self.nameTextField.rac_textSignal filter:^BOOL(id value) {        NSString *text=value;        return text.length>3;    }] subscribeNext:^(id x) {        self.contentLabel.text=x;    }];

Effect: only the input string with a length greater than 3 is displayed as the string content;

3: Split statement,Rac_textSignalAndFilterAllRACSignal

    RACSignal *nameRacSignal=self.nameTextField.rac_textSignal;    RACSignal *filteredName=[nameRacSignal filter:^BOOL(id value) {        NSString *text=value;        return text.length>3;    }];    [filteredName subscribeNext:^(id x) {        self.contentLabel.text=x;    }];

Effect: the effect is the same as that in instance 2, but is defined separately;

4: All the above id types can be matched according to the actual situation

    [[self.nameTextField.rac_textSignal      filter:^BOOL(NSString *text){          return text.length > 3;      }]     subscribeNext:^(id x){          self.contentLabel.text=x;     }];

Effect: here, the filter is of the NSString type. Other types can also be compared, such as int bool. The effect is as follows:

5: map changes the current value and passes it to the next

[[Self. nameTextField. rac_textSignal map: ^ id (NSString * text) {return @ (text. length) ;}] filter: ^ BOOL (NSNumber * length) {return [length intValue]> 3 ;}] subscribeNext: ^ (id x) {// remember to display the NSNumber self. contentLabel. text = [NSString stringWithFormat: @ "% @", x] ;}];

Effect: The result is displayed as follows:, 8, 9 ....., the string content is no longer displayed and has been modified by map to length. Therefore, the filter parameter is also changed. It can be used to convert it into an object.

6: verify the validity and modify the corresponding attributes (For details, refer to, macro definition RAC)

RACSignal * validUsernameSignal = [self. nameTextField. rac_textSignal map: ^ id (NSString * text) {return @ ([self isValidUsername: text]) ;}]; [[validUsernameSignal map: ^ id (NSNumber * userNameValid) {return [userNameValid boolValue]? [UIColor redColor]: [UIColor yellowColor];}] subscribeNext: ^ (UIColor * color) {self. contentLabel. backgroundColor = color;}]; The method code is as follows:-(BOOL) isValidUsername :( NSString *) userName {if ([userName isw.tostring: @ "wjy"]) {return true ;} else {return false ;}}

Effect: the background effect is changed only when the input string is wjy;

7: Application of macro RAC

    RACSignal *validUsernameSignal =        [self.nameTextField.rac_textSignal         map:^id(NSString *text) {             return @([self isValidUsername:text]);         }];    RAC(self.contentLabel,backgroundColor)=[validUsernameSignal                                            map:^id(NSNumber *userNameValid){                                                return[userNameValid boolValue] ? [UIColor redColor]:[UIColor yellowColor];                                            }];

Effect: This is a simplified method, which is directly implemented using the macro RAC. You can remove the subscribeNext: block from the current pipeline and use the RAC macro instead.

Note: RAC macros allow direct application of signal output to object attributes. The RAC macro has two parameters: the first is the object that needs to set the attribute value, and the second is the attribute name. Each time a signal generates a next event, the passed value is applied to this attribute.

8: Aggregation signal (reference)

RACSignal *validUsernameSignal = [self.usernameTextField.rac_textSignal map:^id(NSString *text) { return @([self isValidUsername:text]); }]; RACSignal *validPasswordSignal = [self.passwordTextField.rac_textSignal  map:^id(NSString *text) {  return @([self isValidPassword:text]); }];
RACSignal *signUpActiveSignal =  [RACSignal combineLatest:@[validUsernameSignal, validPasswordSignal]                    reduce:^id(NSNumber*usernameValid, NSNumber *passwordValid){                      return @([usernameValid boolValue]&&[passwordValid boolValue]);                    }];
[signUpActiveSignal subscribeNext:^(NSNumber*signupActive){   self.signInButton.enabled =[signupActive boolValue]; }];

Note: This method of RACsignal can aggregate any number of signals. The parameters of reduce block are related to each source signal. ReactiveCocoa has a tool class RACBlockTrampoline that internally processes variable parameters of reduce blocks.

Effect: The above code is used.CombineLatest: reduce:MethodValidUsernameSignalAndValidPasswordSignalThe generated latest values are aggregated and a new signal is generated. Each time either of the two source signals generates a new value, the reduce block will execute and the return value of the block will be sent to the next signal.

9: UIButton event rac_signalForControlEvents

    [[self.saveBtn      rac_signalForControlEvents:UIControlEventTouchUpInside]     subscribeNext:^(id x) {         NSLog(@"button clicked");     }];

Effect: Click Event Response

10: doNext

    [[[self.saveBtn      rac_signalForControlEvents:UIControlEventTouchUpInside]     doNext:^(id x) {         self.contentLabel.backgroundColor=[UIColor greenColor];     } ]     subscribeNext:^(id x) {         NSLog(@"button clicked");         self.contentLabel.backgroundColor=[UIColor redColor];     }];

Note: doNext is directly behind the button click event. In addition, doNext: block does not return values. Because it is an additional operation and does not change the event itself, the function is as follows: The doNext: block above sets the button as unclickable to hide the logon Failure prompt. In subscribeNext: block, set the button to clickable and decide whether to display the failure prompt Based on the logon result. The instance is as follows:

Instance: [[[self. saveBtn rac_signalForControlEvents: UIControlEventTouchUpInside] doNext: ^ (id x) {self. signInButton. enabled = NO; self. signInFailureText. hidden = YES;}] flattenMap: ^ id (id x) {return [self signInSignal];}] subscribeNext: ^ (NSNumber * signedIn) {self. signInButton. enabled = YES; BOOL success = [signedIn boolValue]; self. signInFailureText. hidden = success; if (success) {[self defined mseguewithidentifier: @ "signInSuccess" sender: self] ;}}];

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.