Search code examples
swiftswift3reactive-cocoareactive-cocoa-5

How to deal with callbacks in ReactiveCocoa 5.0?


I have an utility class to handle the socket, and in the socket delegate methods i could know the current state of the socket, e.g. didConnected, didReadData and so on. I do not want to write an extra protocol with a delegate to send the socket state indeed.

Actually, there are 2 properties in my utility class, an enum to differentiate the current state of the socket between: didConnected, didReadData, didDisconnected, the other is a Data type value to store the received data from socket. It likes that:

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

After become the delegate of the socket, I have implemented the several methods,

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

What I intend to do is while I change the value of the currentState, or I did set the received data to the msgData, in my controller I could capture the 2 values changed simultaneously.

How to make it by use ReactiveCocoa 5.0?


Solution

  • I have achieved my goal by use the function "combineLatest" provided by ReactiveSwift.

    First of all, announce two MutableProperty's variable, and one SignalProducer, likes below:

    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)
    }
    

    Then, change the rac_state.value or rac_mas.value in the socket delegate methods, likes that:

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

    Finally, make an observer in controller to listen the combined SignalProducer, here is the code:

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