ReactiveCocoa(RAC)响应式编程

2019-10-08  本文已影响0人  小凡凡520
一、简介

在iOS平台使用响应式编程(Functional Reactive Programming,简称FRP),有一个很好的开源项目ReactiveCocoa,ReactiveCocoa简称RAC,它是基于响应式编程(FRP)思想的Objective-C实践。

ReactiveCocoa是github开源的一个第三方框架,响应式编程的代表。通过函数式响应式编程的思想,实现的信号机制。使用ReactiveCocoa去搭建MVVM架构,使代码更加高聚合,低耦合。便捷的实现双向绑定的效果。

二、集成
pod 'ReactiveCocoa'
pod 'ReactiveObjC'
target 'xxxxxx' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for xxxxxx
  pod 'ReactiveObjC'
  pod 'ReactiveCocoa'
  pod 'ReactiveObjCBridge'

end

二、UIButton事件监听
import ReactiveCoccoa

bt.reactive.controlEvents(UIControl.Event.touchUpInside).observeValues { (_) in
   print("test")
}
三、TextField值变化事件
import ReactiveCoccoa


textFiled.reactive.continuousTextValues.observeValues { (str) in
    print(str)
}

textFiled.reactive.controlEvents(UIControl.Event.editingChanged).observeValues { (t) in
    print(t.text)
}

// 输入字符长度大于3
textFiled.reactive.continuousTextValues.filter { (str) -> Bool in
    let lenth = str.lengthOfBytes(using: String.Encoding.utf8)
    return lenth > 3
    }.observeValues { (text) in
        print(text)
}
四、RACSiganl信号类
import UIKit
import ReactiveObjC

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        // 创建信号
        let singal = RACSignal<AnyObject>.createSignal({ (sub) -> RACDisposable? in
            
            // 信号内部发送数据
            sub.sendNext(1)
            
            // 如果信号被取消,就必须返回一个RACDisposable
            return RACDisposable(block: {
                print("取消了")
            })
        })
        
        // 只要订阅信号,就会返回一个被动取消信号的类
        let disposable = singal.subscribeNext { (obj) in
            print(obj)
        }
        
        // 主动取消订阅
        disposable.dispose()
    }
}
五、RACSubject :信号提供者
import UIKit
import ReactiveObjC

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        // 创建信号
        let subject = RACSubject<AnyObject>()
        
        // 订阅信号
        subject.subscribeNext { (obj) in
            print(obj)
        }
        
        // 发送信号
        subject.sendNext(123 as AnyObject)
    }
}
六、RACReplaySubject:重复提供信号类
import UIKit
import ReactiveObjC

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        // 创建信号
        let replaySubject = RACReplaySubject<AnyObject>(capacity: 1)
        
        // 第一个订阅信号
        replaySubject.subscribeNext { (obj) in
            print("test1 === \(obj)")
        }
        
        // 第二个订阅信号
        replaySubject.subscribeNext { (obj) in
            print("test2 === \(obj)")
        }
        
        replaySubject.sendNext(123 as AnyObject)
    }
}

七、RACSequence:RAC中的集合类
import UIKit
import ReactiveObjC

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        // 必须用OC类
        let numbers:NSArray = [1,2,3,4,5]
        numbers.rac_sequence.signal().subscribeNext { (obj) in
            print(obj)
        }
        
        // 必须用OC类
        let dict:NSDictionary = [
            "name":"chenfan",
            "age":"666"
        ]
        dict.rac_sequence.signal().subscribeNext { (obj) in
            print(obj?.first)
            print(obj?.second)
        }
    }
}
八、常见用法
// Student.m
#import "Student.h"

@implementation Student
    
    - (void)test {
        NSLog(@"sds");
    }

@end

-----------------------------------------------------

import UIKit
import ReactiveObjC

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        // 注意:Student类必须是OC类才有用!!!!!!!!!
        let student = Student()
        
        // 先注册
        student.rac_signal(for: #selector(Student.test)).subscribeNext { (t) in
            print("test")
        }
        // 后发送指令
        student.test()
    }
}
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface Student : NSObject
 
    @property (nonatomic) NSString * name;

@end

NS_ASSUME_NONNULL_END

-----------------------------------------------------

import UIKit
import ReactiveObjC

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        // 注意:Student类必须是OC类
        let p = Student()
        
        // 监听
        p.rac_values(forKeyPath: NSStringFromSelector(#selector(getter: Student.name)), observer: self).subscribeNext { (obj) in
            print(obj)
        }
        
        // 变更
        p.name = "ssssss"
    }
}
import UIKit
import ReactiveObjC

class ViewController: UIViewController {
    @IBOutlet weak var bt: UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        bt.rac_signal(for: UIControl.Event.touchUpInside).subscribeNext { (control) in
            print("test")
        }
    }
}
import UIKit
import ReactiveObjC

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        NotificationCenter.default.rac_addObserver(forName: UIResponder.keyboardWillShowNotification.rawValue, object: nil).subscribeNext { (noti) in
            print("noti?.name")
        }
    }
}
import UIKit
import ReactiveObjC

class ViewController: UIViewController {
    
    @IBOutlet weak var textFiled: UITextField!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        textFiled.rac_textSignal().subscribeNext { (str) in
            print(str)
        }
    }
}
import UIKit
import ReactiveObjC

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        RACSignal<AnyObject>.interval(2 as Double, on: RACScheduler.mainThread()).subscribeNext { (date) in
            print(date)
        }
    }
}
九、RAC操作方法之映射:flattenMap,Map
import UIKit
import ReactiveObjC

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        // 创建信号
        let subject = RACSubject<AnyObject>()
        
        // 绑定信号
        let bindSignal = subject.flattenMap { (obj) -> RACSignal<AnyObject>? in
            // 修改源信号
            return RACReturnSignal.return("obj" as AnyObject)
        }
        
        // 订阅绑定信号
        bindSignal.subscribeNext { (obj) in
            print(obj)
        }
        
        subject.sendNext(456 as AnyObject)
    }
}
import UIKit
import ReactiveObjC

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        let signalOfsignals = RACSubject<AnyObject>()
        let signal = RACSubject<AnyObject>()
        let bindSignal = signalOfsignals.flattenMap { (obj) -> RACSignal<AnyObject>? in
            return obj as? RACSignal<AnyObject>
        }
        bindSignal.subscribeNext { (obj) in
            print(obj)
        }
        
        signalOfsignals.sendNext(signal)
        signal.sendNext(123 as AnyObject)
    }
}
import UIKit
import ReactiveObjC

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        let subject = RACSubject<AnyObject>()
        let bindSignal = subject.map { (obj) -> Any? in
            return "123"
        }
        bindSignal.subscribeNext { (obj) in
            print(obj)
        }
        subject.sendNext(456 as AnyObject)
    }
}
十、ReactiveCocoa操作方法之组合
import UIKit
import ReactiveObjC

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        let siganlA = RACSignal<AnyObject>.createSignal { (sub) -> RACDisposable? in
            sub.sendNext("上部分数据")
            sub.sendCompleted()
            return nil
        }
        
        let siganlB = RACSignal<AnyObject>.createSignal { (sub) -> RACDisposable? in
            sub.sendNext("下部分数据")
            return nil
        }
        
        let concatSignal = siganlA.concat(siganlB)
        
        concatSignal.subscribeNext { (obj) in
            print(obj)
        }
    }
}
import UIKit
import ReactiveObjC

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        let siganlA = RACSignal<AnyObject>.createSignal { (sub) -> RACDisposable? in
            sub.sendNext("上部分数据")
            sub.sendCompleted()
            return nil
        }
        
        let siganlB = RACSignal<AnyObject>.createSignal { (sub) -> RACDisposable? in
            sub.sendNext("下部分数据")
            return nil
        }
        
        let thenSiganl = siganlA.then { () -> RACSignal<AnyObject> in
            return siganlB
        }
        thenSiganl.subscribeNext { (obj) in
            print(obj)
        }
    }
}
import UIKit
import ReactiveObjC

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        let signalA = RACSubject<AnyObject>()
        let signalB = RACSubject<AnyObject>()
        
        let mergeSiganl = signalA.merge(signalB)
        mergeSiganl.subscribeNext { (obj) in
            print(obj)
        }
        
        signalB.sendNext("下部分" as AnyObject)
        signalA.sendNext("上部分" as AnyObject)
    }
}
import UIKit
import ReactiveObjC

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        let signalA = RACSubject<AnyObject>()
        let signalB = RACSubject<AnyObject>()
        
        let zipSignal = signalA.zip(with: signalB)
        zipSignal.subscribeNext { (obj) in
            print(obj)
        }
        
        signalA.sendNext(1 as AnyObject)
        signalB.sendNext(2 as AnyObject)
    }
}
十一、ReactiveCocoa操作方法之过滤
import UIKit
import ReactiveObjC

class ViewController: UIViewController {
    
    @IBOutlet weak var text1: UITextField!
    @IBOutlet weak var text2: UITextField!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        text1.rac_textSignal().filter { (str) -> Bool in
            return (str?.length ?? 0) > 3
            }.subscribeNext { (str) in
                print(str)
        }
    }
}
import UIKit
import ReactiveObjC

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        let subject = RACSubject<AnyObject>()
        let ignoreSignal = subject.ignore("1" as AnyObject)
        
        ignoreSignal.subscribeNext { (obj) in
            print(obj)
        }
        
        subject.sendNext("13" as AnyObject)
    }
}
import UIKit
import ReactiveObjC

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        let subject = RACSubject<AnyObject>()
        subject.distinctUntilChanged().subscribeNext { (obj) in
            print(obj)
        }
        
        subject.sendNext(1 as AnyObject)
        subject.sendNext(1 as AnyObject)
        subject.sendNext(2 as AnyObject)
        subject.sendNext(1 as AnyObject)
    }
}
import UIKit
import ReactiveObjC

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        let subject = RACSubject<AnyObject>()
        subject.skip(2).subscribeNext { (obj) in
            print(obj)
        }
        
        subject.sendNext(1 as AnyObject)
        subject.sendNext(2 as AnyObject)
        subject.sendNext(3 as AnyObject)
    }
}
十二、RAC常见宏
#import "ViewController.h"
#import <ReactiveObjC/ReactiveObjC.h>

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *lb;
@property (weak, nonatomic) IBOutlet UITextField *text1;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    RAC(self.lb, text) = self.text1.rac_textSignal;
}


@end

#import "ViewController.h"
#import <ReactiveObjC/ReactiveObjC.h>

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *lb;
@property (weak, nonatomic) IBOutlet UITextField *text1;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    
    [RACObserve(self.text1, frame) subscribeNext:^(id  _Nullable x) {
        NSLog(@"test %@",x);
    }];
    
    self.text1.frame = CGRectMake(0, 0, 100, 100);
}


@end

上一篇下一篇

猜你喜欢

热点阅读