美文网首页
ReactiveCocoa(RAC)响应式编程

ReactiveCocoa(RAC)响应式编程

作者: 小凡凡520 | 来源:发表于2019-10-08 09:22 被阅读0次
一、简介

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

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

二、集成
  • swift项目
pod 'ReactiveCocoa'
  • OC项目
pod 'ReactiveObjC'
  • swift与OC混编
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()
    }
}
  • KVO
#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")
        }
    }
}
  • 监听textfield的输入内容
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)
        }
    }
}
  • Timer定时器
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
  • flattenMap:把源信号的内容映射成一个新的信号,信号可以是任意类型
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)
    }
}
  • flattenMap实现:信号中信号取值
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)
    }
}
  • 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.map { (obj) -> Any? in
            return "123"
        }
        bindSignal.subscribeNext { (obj) in
            print(obj)
        }
        subject.sendNext(456 as AnyObject)
    }
}
十、ReactiveCocoa操作方法之组合
  • concat: 按一定顺序拼接信号,当多个信号发出的时候,有顺序的接收信号
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)
        }
    }
}
  • then: 用于连接两个信号,当第一个信号完成,才会连接then返回的信号
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)
        }
    }
}
  • merge:把多个信号合并为一个信号,任何一个信号有新值的时候就会调用
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)
    }
}
  • zipWith:把两个信号压缩成一个信号,只有当两个信号同时发出信号内容时,并且把两个信号的内容合并成一个元组,才会触发压缩流的next事件
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操作方法之过滤
  • filter:过滤信号,使用它可以获取满足条件的信号
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)
        }
    }
}
  • ignore:忽略完某些值的信号
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)
    }
}
  • distinctUntilChanged:当上一次的值和当前的值有明显的变化就会发出信号,否则会被忽略掉。
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)
    }
}
  • skip:(NSUInteger):跳过几个信号,不接受
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常见宏
  • RAC (swift 中不可用)
#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

  • RACObserve (swift 中不可用)
#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

相关文章

  • iOS 常用的第三方库

    ReactiveCocoa 、RxSwift : 响应式编程RAC Alamofire 、 AFNetworkin...

  • RAC(ReactiveCocoa)介绍(一)——基本介绍

    最近接触学习到了RAC(ReactiveCocoa),RAC是函数式+响应式编程结合,首先得去理解何为响应式函...

  • RAC(ReactiveCocoa)——基本使用(附简单Demo

    最近接触学习到了RAC(ReactiveCocoa),RAC是函数式+响应式编程结合,首先得去理解何为响应式函数编...

  • RAC API使用

    RAC的定义 ReactiveCocoa(简称:RAC),其具有函数式编程和响应式编程的特性,是github开源的...

  • ReactiveCocoa

    ReactiveCocoa(简称RAC),结合了函数式编程和响应式编程的编程风格,所以ReativeCocoa被描...

  • ReactiveCocoa(RAC)-iOS

    简介 ReactiveCocoa(简称为RAC),RAC具有函数响应式编程特性,由Matt Diephouse开源...

  • RAC

    IOS响应式编程框架ReactiveCocoa(RAC)使用示例 感觉RAC响应起来太乱,不太实用,但是平时自己的...

  • RAC 的初级使用

    RAC的定义: ReactiveCocoa 可以说是结合了函数式编程和响应式编程的框架,也可称其为函数响应式编程(...

  • RAC基础

    最近接触学习到了RAC(ReactiveCocoa),RAC是函数式+响应式编程结合 我们在iOS开发中,页面之间...

  • RAC简单用法

    RAC浅浅析ReactiveCocoa 可以说是结合了函数式编程和响应式编程的框架,也可称其为函数响应式编程(FR...

网友评论

      本文标题:ReactiveCocoa(RAC)响应式编程

      本文链接:https://www.haomeiwen.com/subject/sspbbftx.html