1. UIControl

    • Listen to control click
    • From now on bid farewell toaddTargetbtnClick
    [[self.loginBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(UIButton *btn) { // btn, Self.loginbtn // do what you click here}];Copy the code
  2. UITextField

    • Listen for textField text changes
    • Say goodbye toUITextFieldDelegate
    [self.mytf.rac_textSignal subscribeNext:^(NSString* text) {// text = self.mytf.text // when text changes, this block is added}];Copy the code
  3. UILabel

    • Label attributestextBinding inUITextField
    RAC(self.mylab, text) = self.mytf.rac_textSignal; RAC(self.mylab, text) = self.mytf.rac_textSignal;Copy the code
  4. Listen for property changes

    • As soon as the name of the person changes, it enters the block
    • No more tedious KVO writing
    [RACObserve(self.per, name) subscribeNext:^(NSString *name) {// name = self.per. Name}];Copy the code
  5. Listen for notification message

    • As soon as the keyboard frame changes, it goes inside the block

    • The notification release has been done internally and does not need to be removed in dealloc

    [[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillChangeFrameNotification object:nil] // When self is about to dealloc, TakeUntil :self.rac_willDeallocSignal] subscribeNext:^(NSNotification *notification) {NSLog(@)"-- -- -- -- -- % @", notification.description);
    }];
    Copy the code
    • Sending notifications is the same as before
    [[NSNotificationCenter defaultCenter] postNotificationName:@"Notice Name" object:nil];
    Copy the code
  6. An array of

    • traverse
    NSArray *array = @[@1, @2, @3, @4, @5]; [array.rac_sequence.signal subscribeNext:^(id x) {// xCopy the code
    • filterfilterAnd gets the filtered array
    NSArray *filter = [[array.rac_sequence filter:^BOOL(id value) {
       return  [value integerValue] > 2;
    }] array];
    Copy the code
    • Matching, mappingmap, transforms the elements and gets a new array
    NSArray *map = [[array.rac_sequence map:^id(id value) {
            
       NSInteger a = [value integerValue] * [value integerValue];
       
       return [NSString stringWithFormat:@"%ld", a];
       
    }] array];
    Copy the code
  7. The dictionary

    • rac_keySequencerac_valueSequenceJust like an array
    • rac_sequenceNeed to beRACTupleUnpackUnpack the
    NSDictionary *dic = @{@"name": @"lion"The @"age": @}; [dic.rac_sequence.signal subscribeNext:^(id x) { RACTupleUnpack(NSString *key, NSString *value) = x; NSLog(@"\r\nkey: %@\r\nvalue: %@", key, value);
    }];
    Copy the code
  8. The most classic login interface, login button is clickable

    • First combine the two signals
    • And then parse the signal
    • Finally, bind the result to the signal
    RAC(self.loginBtn, enabled) = [RACSignal 
                                      combineLatest:@[self.usernameTF.rac_textSignal, self.passwordTF.rac_textSignal] 
                                      reduce:^id(NSString *username, NSString *password){
                                          return @(username.length > 6 && password.length > 8);
                                  }];
    Copy the code
  9. Throttling throttle

    • Indicates that no signal will be sent during the specified interval
    • Here to addthrottle, indicates that the search request will be executed only if the text has not changed within 0.5 seconds
    • You want to searchreactiveCocoaIf nothrottleFor every character entered, a search request will be made, which is obviously not what we want.
    [[[self.searchTF rac_textSignal] throttle:0.5] subscribeNext:^(id x) {NSLog(@)"Start search request ==%@", x);
    }];
    Copy the code
  10. A one-two punch:

  11. To determine whether the user name complies with the rule,

  12. After the user name is correct, check whether the password complies with the rules

  13. The password is correct, the request is authenticated, and the result of the request is returned after success

  14. Return to the main thread to update the UI based on the results

// 1. Check user name - (RACSignal *)validUsernameSignal {// Prevent cyclic reference @weakify(self); // Because it returns a signal, it needs to be createdreturn[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { @strongify(self); [[[[[self.usernameTF rac_textSignal] // skip, which means to ignore several times the signal is first loaded, and TF's first response, DistinctUntilChanged skip:2] // distinctUntilChanged Map :^id(NSString *value) {return@(value.length > 5); DistinctUntilChanged = distinctUntilChanged = distinctUntilChanged = distinctUntilChanged = distinctUntilChanged Bool :^(id x) {if ([x integerValue] == 1) {
              [subscriber sendNext:@"User name is correct"];
              [subscriber sendCompleted];
              NSLog(@"------- user name is correct");
          } else {
              NSLog(@"------- user name error"); }}];returnnil; }]; } / / 3. Request validation - (RACSignal *) loginSuccessSignalWithPassword: (nsstrings *) PSW {return[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {/** * And returns the result */ NSString * STR = @"User information Data";
     NSLog(@"---- login successful and return user information Data");
     
     NSDictionary *dic = @{@"data": str};
     
     [subscriber sendNext:dic];
     [subscriber sendCompleted];
     
     returnnil; }]; - (void)loginResult {// Determine the user name [[[[[[[self validUsernameSignal] //then, only the preceding signal sends the message, and the completion will continue // below carry on the password judgmentthen:^RACSignal *{
           returnself.passwordTF.rac_textSignal; }] // throttle = 0, // throttle = 0, // Filter :^BOOL(NSString *value) {return[value length] > 6; }] // the flattener map generates new signals based on the content of the source signal, and the flattener is often used to process signals within signals in signal nesting. To pass information along the flattenMap:^RACStream *(NSString *value) {return[self loginSuccessSignalWithPassword:value]; }] // deliverOn:[RACScheduler mainThreadScheduler]] Get the data sent by the signal"Get info \r\n%@, \r\n update UI", x);
  }];
}
Copy the code

Summary:

  • Although ReactiveCocoa is a big change in thinking, I prefer to use it as a new and easier syntax, and in the process of using it, you will naturally feel that it is different from your previous programming. When you use it a lot, you realize that this is functional and responsive programming.

  • Syntax is only the entrance to understanding programming ideas. A small step in thinking is a big step in programming.

  • Theory is practice, when you do not understand the theory, it is time to practice.