RXswift,重复观察直到完成

时间:2018-06-05 10:21:13

标签: ios swift rx-swift

我正在尝试将固件上传到BLE设备。因此,我推送一些数据,等待确认,然后推送更多,依此类推。 但我正在努力重复观察者直到观察者返回完成。

这是观察者,所以如果没有更多的数据包要发送,它应该完成并停止重复。

let transferImage = Observable<Void>.create { (obs) -> Disposable in
        guard let nextPacket = dataSendingTracker.getNextPacket() else {
            obs.onCompleted()
            return Disposables.create()
        }

        return self.instrument()
            .flatMap{ $0.sendFWpacket(packet: nextPacket) }
            .subscribe(onNext: { () in
                obs.onNext(())
            }, onError: { (error) in
                obs.onError(error)
            })
    }

关于如何实现这一目标的任何建议?

2 个答案:

答案 0 :(得分:0)

尝试这样的事情,但我认为这种丑陋的方式......不是Rx解决方案

transferImage.takeWhile将在getNextPacket返回nil或此情况下整数小于零时停止。

     func test() {
    let transferImage = Observable<Int>.create { (obs) -> Disposable in
        if let nextPacket = self.getNextPacket() {
            obs.onNext(nextPacket)

        } else{
            obs.onNext(-1)
            obs.onCompleted()

        }
        return Disposables.create()
    }

    transferImage.takeWhile{$0 > 0}.subscribe(onNext: { nextPacket in
        print(nextPacket)
        let completed = self.sendFWpacket()
        if !completed {
            self.test()
        }

    }, onError: { error in
        print(error)
    }, onCompleted: {
        print("onCompleted")
    }) {
        print("disposed")
        }.disposed(by: disposeBag)

}

func sendFWpacket()-> Bool {
    return false
}

func getNextPacket() ->  Int? {
    return 1
}

答案 1 :(得分:0)

假设你有一个写一个数据块的函数,比如这个测试函数:

func writeDataBlock(offset: Int, blockSize: Int) -> Observable<Int> {
    let writtenBytesCount = min(Int(arc4random_uniform(5) + 5), blockSize)
    return Observable<Int>.just(writtenBytesCount)
}

实际上,这个函数也会使用一些数据缓冲区,并尝试在给定的偏移处从该数据中推送给定大小的块,并返回完成时写入的字节数。在这里,您可以使用transferImage中的逻辑。

然后可以使用递归来编写完整的传递函数,如下所示:

func writeAllDataRec(offset: Int, totalSize: Int, observer: AnyObserver<String>) {
    guard offset < totalSize else {
        observer.onNext("writeAllData completed")
        observer.onCompleted()
        return
    }

    var subscriber: Disposable?
    let blockSize = min(10, totalSize - offset)
    subscriber = writeDataBlock(offset: offset, blockSize: blockSize).subscribe { ev in
        switch ev {
        case let .next(writtenBytesCount):
            debugPrint("writeNextBlock from offset: \(offset); writtenBytesCount = \(writtenBytesCount)")
            let newOffset = offset + writtenBytesCount
            writeAllDataRec(offset: newOffset, totalSize: totalSize, observer: observer)
        case .completed:
            subscriber?.dispose()
            //debugPrint("writeAllData block completed")
        case let .error(err):
            subscriber?.dispose()
            observer.onError(err)
            observer.onCompleted()
        }
    }
}

func writeAllData(totalSize: Int) -> Observable<String> {
    return Observable<String>.create { (observer) -> Disposable in
        writeAllDataRec(offset: 0, totalSize: totalSize, observer: observer)
        return Disposables.create()
    }
}

可以这样测试:

var subscriber: Disposable?
...
    self.subscriber = writeAllData(totalSize: 100).subscribe(onNext: { (message) in
        print("\(message)")
    })

在这个解决方案中,我假设您的下一个数据块取决于先前写入了多少数据,并且没有共享的全局状态。

这可以用RxJS expand的逻辑简化很多,但不幸的是这个函数在RxSwift(4.1.2)中不存在。