处理

时间:2017-04-19 08:32:58

标签: ios swift reactive-cocoa racsignal reactive-swift

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

在主题Migrate from RACSignal to ReactiveSwift or 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()
        }
    }

备注:
有时我想要有一个&#34;两个处理程序块&#34;这将在成功和错误上被调用,因此隐藏加载指示符之类的东西可以在该块下完成。

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

崩溃

我的个人需求是:
1.有某种&#34;两者&#34;在成功和失败的请求案件之后将被调用的块 2.所有观察者的textFields&#39;关闭VC后,必须删除文本值并且不再处于活动状态 3.当我关闭VC时,必须取消网络请求

P.S。:当然,感谢所有阅读这篇文章的人,并花时间帮助我!

1 个答案:

答案 0 :(得分:4)

&#34;制作网络请求&#34; ReactiveSwift readme中的示例就是这类事物的一个很好的例子。不要在文本字段信号上使用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的内容,可能就在调用<div class="fb-comments" data-href="http://www.yourpage.org/" data-numposts="20" data-width="100%" data-order-by="reverse_time" data-colorscheme="light"></div> 之前。

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