我对Rx非常陌生,一直在尝试开发一个解决服务的Bonjour发现客户端。这很简单,但我想尝试使用RxSwift。
由于发现的NSNetService对象需要在解析之前被持久化,所以我不得不进行嵌套的订阅调用,外部调用用于发现,而内部的on调用用于resolution...but,这告诉我这不是最好的方法。
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()
}
}我的代理类如下:
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。我一定要使用嵌套调用吗?
我的问题的简短版本是上述作品,但似乎令我费解。任何想法都将不胜感激。
发布于 2016-03-14 11:10:28
您可以使用scan来避免嵌套订阅。它将把每个NSNetService从rx_netServiceBrowserDidFindServiceMoreComing添加到数组中。请注意,在这种情况下,您不需要将servicesArray作为成员变量存储,除非您出于另一个原因需要它。
然后您可以使用flatMap,如下所示:
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
extension NSNetService {
//existing methods omitted
public func rx_resolveWithTimeout(timeout: NSTimeInterval) -> Observable<NSNetService> {
self.resolveWithTimeout(timeout)
return rx_netServiceDidResolveAddress.filter {
$0 == self
}
}
}https://stackoverflow.com/questions/35858805
复制相似问题