首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RxSwift和Bonjour发现的嵌套订阅

RxSwift和Bonjour发现的嵌套订阅
EN

Stack Overflow用户
提问于 2016-03-08 04:11:31
回答 1查看 828关注 0票数 0

我对Rx非常陌生,一直在尝试开发一个解决服务的Bonjour发现客户端。这很简单,但我想尝试使用RxSwift。

由于发现的NSNetService对象需要在解析之前被持久化,所以我不得不进行嵌套的订阅调用,外部调用用于发现,而内部的on调用用于resolution...but,这告诉我这不是最好的方法。

代码语言:javascript
复制
import UIKit
import RxSwift

class BonjourClient: NSObject {

    let disposeBag = DisposeBag()
    var servicesArray = [NSNetService]()

    func startBrowsing() {
        let browser = NSNetServiceBrowser()
        browser.rx_netServiceBrowserDidFindServiceMoreComing
            .subscribeNext { (service: NSNetService) in
                        self.servicesArray.append(service)
                        self.servicesArray.last!.rx_netServiceDidResolveAddress
                            .subscribeNext { (sender: NSNetService) in
                                print("Resolved \(sender.name)")
                                let data = sender.TXTRecordData()
                                let dict: [String: NSData?] = NSNetService.dictionaryFromTXTRecordData(data!)
                                for (key, value) in dict {
                                    print("\(key) : \(String(data: value!, encoding: NSUTF8StringEncoding)!)")
                                }
                        }.addDisposableTo(self.disposeBag)
                        self.servicesArray.last!.resolveWithTimeout(5)
                }.addDisposableTo(disposeBag)
        browser.searchForServicesOfType("_amzn-wplay._tcp.", inDomain: "local.")
        NSRunLoop.currentRunLoop().run()
    }

}

我的代理类如下:

代码语言:javascript
复制
import UIKit
import RxSwift
import RxCocoa

class RxNSNetServiceBrowserDelegateProxy: DelegateProxy, NSNetServiceBrowserDelegate, DelegateProxyType {

    static func currentDelegateFor(object: AnyObject) -> AnyObject? {
        let browser: NSNetServiceBrowser = object as! NSNetServiceBrowser
        return browser.delegate
    }

    static func setCurrentDelegate(delegate: AnyObject?, toObject object: AnyObject) {
        let browser: NSNetServiceBrowser = object as! NSNetServiceBrowser
        browser.delegate = delegate as? NSNetServiceBrowserDelegate
    }

}

class RxNSNetServiceDelegateProxy: DelegateProxy, NSNetServiceDelegate, DelegateProxyType {

    static func currentDelegateFor(object: AnyObject) -> AnyObject? {
        let service: NSNetService = object as! NSNetService
        return service.delegate
    }

    static func setCurrentDelegate(delegate: AnyObject?, toObject object: AnyObject) {
        let service: NSNetService = object as! NSNetService
        service.delegate = delegate as? NSNetServiceDelegate
    }

}

extension NSNetServiceBrowser {

    public var rx_delegate: DelegateProxy {
        return proxyForObject(RxNSNetServiceBrowserDelegateProxy.self, self)
    }

    public var rx_netServiceBrowserDidFindServiceMoreComing: Observable<NSNetService> {
        return rx_delegate.observe("netServiceBrowser:didFindService:moreComing:")
            .map { params in
                let service = params[1] as! NSNetService
                return service
        }
    }

}

extension NSNetService {

    public var rx_delegate: DelegateProxy {
        return proxyForObject(RxNSNetServiceDelegateProxy.self, self)
    }

    public var rx_netServiceDidResolveAddress: Observable<NSNetService> {
        return rx_delegate.observe("netServiceDidResolveAddress:")
            .map { params in
                return params[0] as! NSNetService

        }
    }
}

如果我在browser.rx_netServiceBrowserDidFindServiceMoreComing调用之后使用browser.rx_netServiceBrowserDidFindServiceMoreComing而不是subscribeNext,服务将不会解析,因为我无法将它保存到flatMap内部的数组中,原因主要是因为我从未接触过Rx。我一定要使用嵌套调用吗?

我的问题的简短版本是上述作品,但似乎令我费解。任何想法都将不胜感激。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-03-14 11:10:28

您可以使用scan来避免嵌套订阅。它将把每个NSNetServicerx_netServiceBrowserDidFindServiceMoreComing添加到数组中。请注意,在这种情况下,您不需要将servicesArray作为成员变量存储,除非您出于另一个原因需要它。

然后您可以使用flatMap,如下所示:

代码语言:javascript
复制
browser.rx_netServiceBrowserDidFindServiceMoreComing
    .scan([NSNetService]()) { (services: [NSNetService], service: NSNetService)  in
        return services + [service]
    }.flatMap { (services: [NSNetService]) in
        return services.last!.rx_resolveWithTimeout(5)
    }.subscribeNext { (sender: NSNetService) in
        print("Resolved \(sender.name)")
        let data = sender.TXTRecordData()
        let dict: [String: NSData?] = NSNetService.dictionaryFromTXTRecordData(data!)
        for (key, value) in dict {
            print("\(key) : \(String(data: value!, encoding: NSUTF8StringEncoding)!)")
        }
}.addDisposableTo(disposeBag)

这需要在NSNetService扩展中添加一个方法,因为您必须从flatMap返回一个Observable

代码语言:javascript
复制
extension NSNetService {
//existing methods omitted
 public func rx_resolveWithTimeout(timeout: NSTimeInterval) -> Observable<NSNetService> {
        self.resolveWithTimeout(timeout)
        return rx_netServiceDidResolveAddress.filter {
            $0 == self
        }
    }
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35858805

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档