Как бороться с обратными вызовами в ReactiveCocoa 5.0?

У меня есть служебный класс для обработки сокета, и в методах делегата сокета я мог знать текущее состояние сокета, например, didConnected, didReadData и так далее. Я не хочу писать дополнительный протокол с делегатом для отправки состояния сокета.

На самом деле в моем служебном классе есть 2 свойства, перечисление для различения текущего состояния сокета: didConnected, didReadData, didDisconnected, другое - это тип данных для хранения полученных данных из сокета. Это нравится это:

public enum SocketState {
    case unknown, didConnected, didReconnectedFailed, didSentHeartbeatPack, 
         didSentMessage, didReadData, didDisconnected
}
private var currentState: SocketState = .unknown
private var msgData = Data()

Став делегатом сокета, я реализовал несколько методов,

func socket(_ sock: GCDAsyncSocket, didConnectToHost host: String, port: UInt16) {}
func socket(_ sock: GCDAsyncSocket, didWriteDataWithTag tag: Int) {}
func socketDidDisconnect(_ sock: GCDAsyncSocket, withError err: Error?) {}

Что я собираюсь сделать, пока я изменяю значение currentState или я установил полученные данные как msgData, в моем контроллере я мог бы зафиксировать 2 значения, измененные одновременно.

Как это сделать с помощью ReactiveCocoa 5.0?

2 ответа

Решение

Я достиг своей цели, используя функцию "lateLatest", предоставляемую ReactiveSwift.

Прежде всего, объявите две переменные MutableProperty и одну SignalProducer, как показано ниже:

private var rac_state = MutableProperty<SocketState>(.unknown)
private var rac_msg = MutableProperty<Data>(Data())
public var rac_SocketStateChanged: SignalProducer<(SocketState, Data), NoError> {
    return SignalProducer.combineLatest(rac_state.producer, rac_msg.producer)
}

Затем измените rac_state.value или rac_mas.value в методах делегата сокета, например:

func socketDidDisconnect(_ sock: GCDAsyncSocket, withError err: Error?) {
    rac_state.value = .didDisconnected
}

Наконец, сделайте наблюдателя в контроллере для прослушивания комбинированного SignalProducer, вот код:

func configTCPListen() {
    tcpManager.rac_SocketStateChanged
        .startWithValues { [weak self = self] (tuple) in
            switch tuple.0 {
            case .didDisconnected:
                print("TCP has disConnected!")
            default: break
            }
    }
}

Может быть MutableProperty предоставленный ReactiveSwift может удовлетворить вас. Ваше намерение очень похоже на то, что механизм KVO может делать в Objective-C, а Swift - нет. Тем не мение, MutableProperty Класс реализует ту же функциональность, изменения которой кто-то может наблюдать.
Надеюсь, что приведенные ниже демоверсии помогут вам понять самый простой способ использования MutableProperty и его использование.

// definition
let currentState: MutableProperty<SocketState> = MutableProperty(.unknown)
let msgData: MutableProperty<Data> = MutableProperty(Data())

// observe changes
currentState.producer.startWithValues { state in
    // process(state)
}
msgData.producer.startWithValues { data in
    // doSomething(withData data)
}

Если удалить избыточный явный вывод типа, приведенные выше коды будут чистыми и простыми.

// definition
let currentState = MutableProperty(.unknown)
let msgData = MutableProperty(Data())

// observe changes
currentState.producer.startWithValues {
    // process($0)
}
msgData.producer.startWithValues {
    // doSomething(withData $0)
}
Другие вопросы по тегам