5

我试图弄清楚是否可以使用 ReactiveSwift 和 RAC5 实现适合我需要的网络请求处理。

从 RACSignal 迁移到 ReactiveSwift 或 RAC5主题下,有人告诉我它可以使用 SignalProducer 完成,但深入研究它并没有给我预期的结果

所以,我想要:
1. 每次 textField 发送请求中的文本更改(按关键字搜索)。
2.一旦用户关闭当前的ViewController,当前的请求应该会自动取消
3.一旦关键字改变,可以取消请求

这是我所拥有的

self.textField.reactive.continuousTextValues.skipNil().filter({ (value) -> Bool in
        return value.characters.count > 0
    }).observeValues { [unowned self] (value) in
        self.fetchSignalDisposable?.dispose()
        self.fetchSignal = self.producerFor(keyword: value).on(started: {
            print("started")
        }, failed: { (error) in
            print("error")
        }, completed: {
            print("completed")
        }, value: { [unowned self] (items) in
            print("value")
            self.items.append(contentsOf: items)
            self.tableView.reloadData()
        })
        self.fetchSignalDisposable = self.fetchSignal!.start()
    }

这是生产者初始化程序

return SignalProducer<Any, NSError> { (observer, disposable) in
        let task: URLSessionDataTask? = NetworkClient.fetchRequestWith(uri: "test", parameters: ["keyword" : keyword], success: { response in
            observer.send(value: response)
            observer.sendCompleted()
        }, failure: { error in
            observer.send(error: error)
            observer.sendCompleted()
        })
        disposable += {
            task?.cancel()
        }
    }

注意:
1. 有时我想有一个“两个处理程序块”,它会在成功和错误时被调用,所以像隐藏加载指示器这样的事情可以在那个块下完成。

这里有几个问题/问题:
1. 一旦我关闭 VC(解除操作),observeValue 处理程序就会再调用一次。它可以通过添加来修复.skipRepeats(),但我想这只是一种解决方法,而不是一个确切的解决方案。
如果我关闭 VC 2 completed,即使我在调用 3 后立即手动调用它,我也不希望这个观察者处于活动状态send(error: error)
。如果请求仍在加载并且我关闭 VC,它不会自动处理,这对我来说看起来很奇怪。我认为一旦 viewController 失去对 signalProducer 的引用,就会自动调用 dispose 块。即使调用VCself.fetchSignalDisposable?.dispose()deinit方法也不会取消请求。它仍然完成请求和调用value导致错误访问错误崩溃的处理程序

我的个人需求是:
1. 在请求成功和失败的情况下都将调用某种“两者”块2. 关闭 VC 3
后,必须删除 textFields 文本值的所有观察者,并且不再处于活动状态。
关闭VC时必须立即取消网络请求

PS:当然,感谢所有阅读这篇巨文并花时间帮助我的人!

4

1 回答 1

5

ReactiveSwift 自述文件中的“发出网络请求”示例就是这类事情的一个很好的例子。而不是observeValues在你的文本字段信号上使用,通常你会.flatMap(.latest)像这样直接将它连接到你的 SignalProducer (注意我没有检查这个代码,但希望它能让你理解):

self.textField.reactive.continuousTextValues
    .skipNil()
    .filter { (value) -> Bool in
        return value.characters.count > 0
    }
    .flatMap(.latest) { [unowned self] value in
        return self.producerFor(keyword: value)
            // Handling the error here prevents errors from terminating
            // the outer signal. Now a request can fail while allowing
            // subsequent requests to continue.
            .flatMapError { error in
                print("Network error occurred: \(error)")
                return SignalProducer.empty
            }
    }
    .observe(on: UIScheduler())
    .observe { [unowned self] event in
        switch event {
        case let .value(items):
            print("value")
            self.items.append(contentsOf: items)
            self.tableView.reloadData()

        case let .failed(error):
            print("error")

        case .completed, .interrupted:
            print("completed")
        }
    }

指定.latest会导致先前的网络请求在新请求开始时自动取消,因此无需在全局变量中跟踪当前请求。

至于管理生命周期,如果不了解更广泛的代码结构,很难说最好的事情是什么。通常我会在我的信号中添加类似的东西,以在被释放.take(during: self.reactive.lifetime)时终止订阅self,可能就在调用observe.

错误事件终止信号。发生错误后无需发送已完成的事件,观察者也不会看到它。基本上,完成表示信号成功终止,而错误表示信号终止失败。

于 2017-04-19T12:52:24.267 回答