• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

ios - 如何在属于 Observable 的属性上过滤 Observable?

[复制链接]
菜鸟教程小白 发表于 2022-12-12 12:16:32 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

问题是我有一个协议(protocol),其中包含我想要在可用时对其进行排序的属性。当我试图让一切都变得 super react 时。

protocol DeviceConnectionProtocol {
...
    var id : Observable<String> { get }
...
}

而我的情况是,无论 url/name/etc 是否更改,我都想找到我连接的最后一个设备。

  class DeviceFinder {

    let rx_DeviceList = Variable([DeviceConnectionProtocol]())
    let disposeBag = DisposeBag()

    init() {
        SMOIPConnection.FindDevices().subscribe(onNext : { smoip in
            self.rx_DeviceList.value.append(smoip)
        }).addDisposableTo(disposeBag)

        MockDevice.FindDevices().subscribe(onNext : { mock in
            self.rx_DeviceList.value.append(mock)
        }).addDisposableTo(disposeBag)

    }

}

...

这是我目前的排序功能。但它不可行,因为 device.id.map 返回一个 Observable 而不是过滤操作所需的 Bool

struct LastConnectedDevice {

    private static let lastConnectedKeyForID = "lastConnected"

    static func get() -> Observable<DeviceConnectionProtocol>{
    let lastID = UserDefaults.standard.string(forKey: lastConnectedKeyForID)
       return DeviceFinder().rx_DeviceList.asObservable().flatMap{list in
            return Observable.from(list)
            }.filter { (device : DeviceConnectionProtocol) -> Bool in
                return device.id.map{ id in
                    return id == lastID
                }
        }
    }
}



Best Answer-推荐答案


诊断

根据我对您问题的理解,您在执行过滤操作时遇到了困难,因为该属性是 Observable 而不是 Int。这意味着您不能只使用等号运算符检查 ID,因为您 need to get out of the Rx monad .

继续使用 Rx Monad

对于更优雅的 FRP 解决方案:

  1. 定义您的可观察设备。
  2. 定义可观察的设备 ID。
  3. Zip他们在一起。
  4. Filter通过 checking最后一个设备 ID。
  5. 返回你想要的数据类型(DeviceConnectionProtocol)。
  6. 使用最后一个设备执行必要的代码。

这是 RxSwift 代码。我的一些类定义可以在下面的代码块中看到。

// Observable<DeviceConnectionProtocol>
let devices = rx_DeviceList
    .asObservable()
    .flatMap { array in Observable.from(array) } 

// Observable<Int>
let deviceIDs = devices
    .flatMap { device in device.id } 

Observable.zip(devices, deviceIDs) { $0 } 

    // data type of (DeviceConnectionProtocol, Int)
    .filter { $0.1 == lastID }
    .map { $0.0 }
    .subscribe(onNext: lastDeviceSelected)

Monad 只是一种表达范式、处理方式或思维方式的方式。您可以随时退出 RxMonad,这意味着离开数据流并返回到命令式代码。这是程序员更习惯的。


退出 Rx Monad 的简单方法

这是一个(有些困惑的)解决方案。 TL;DR 转到 如何同步退出 RxMonad 部分。

import RxSwift

protocol DeviceConnectionProtocol {
    var id : Observable<String> { get }
}


class Person : DeviceConnectionProtocol {
    var myName: String! = nil

    init(name: String) {
        self.myName = name
    }

    var id: Observable<String> {
        return Observable.create { [unowned self] obx in
            obx.onNext(self.myName)
            return Disposables.create()
        }
    }
}
let rx_DeviceList = Variable([DeviceConnectionProtocol]())
let disposeBag = DisposeBag()

let lastID = "Hillary"

func lastDeviceSelected(device: DeviceConnectionProtocol) {
    if let person = device as? Person {
        print(person.myName + " was found!")
    }
}

rx_DeviceList
    .asObservable()
    .flatMap { array in Observable.from(array) }
    .filter{ (device: DeviceConnectionProtocol) -> Bool in

        // How to exit the RxMonad synchronously

        // Have a result variable
        var currentID = ""

        // Subscribe on the observable on the default schedulers (main thread) and assign result
        device.id.subscribe(onNext: { (id: String) in currentID = id })

        // Return result
        return lastID == currentID
    }
    .subscribe(onNext: lastDeviceSelected)

rx_DeviceList.value = [Person(name: "Donald"), Person(name: "Goofy"), Person(name: "Hillary")]

结果:

Hillary was found!

请注意,结束的序列(例如 [1,2,3,4,5])能够使用 takeLast 运算符,但出于某种原因,您的情况是不同的,它不起作用。

引用和注释

  1. 这是 Github Gist如果你想要在 Rx Playground 上运行的整个代码。

  2. zip 运算符在 RxMarbles 上可视化.

  3. zip 运算符 documentation .

  4. filter 运算符在 RxMarbles 上可视化.

  5. 过滤器操作符documentation .

  6. 这是一个 Swift 3 解决方案。

关于ios - 如何在属于 Observable 的属性上过滤 Observable?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40405811/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap