背景:

我在Swift 1.2(通过桥接头)上成功在项目上使用了GCDAsyncSocket

现在的挑战是它需要某种队列,因为它所连接的系统一次只能处理并返回一个命令。

因此,如果它背对背调用方法,例如:

getSystemInfo()
getSystemStatus()

由于系统正在忙于处理委托,因此仅通过委托回调返回getSystemInfo(),但是getSystemStatus()已成功发送asynchronously,但未被控制器处理。我希望它能够使调用背靠背进行,并在控制器完成处理并返回上一个响应后使它们排队和处理,从而使过程基本同步。

问题:

如您在下面的示例代码中的didConnectToHost委托回调中看到的那样,当它连接到控制器时,它先调用getSystemInfo(),然后再调用getSystemStatus(),从系统信息中获取结果后,它应该调用getSystemStatus()

我一直在看NSConditionNSOperation,甚至是GCD,但是我不确定实现这一点的最优雅的方法是什么。我不想在混合中加入另一个队列处理器,因为已经为GCDAsyncSocket设置了队列。什么是最好,最优雅的处理方式?

伪类代码:
public class SendNet: NSObject, GCDAsyncSocketDelegate {

    var socket:GCDAsyncSocket! = nil

    func setupConnection(){

            var error : NSError?
            if (socket == nil) {
                socket = GCDAsyncSocket(delegate: self, delegateQueue: dispatch_get_main_queue())
            } else {
                socket.disconnect()
            }


            if (!socket.connectToHost(host, onPort: port, withTimeout: 5.0, error: &error)){
                println("Error: \(error)")
            } else {
                println("Connecting...")
            }
    }

    public func socket(socket : GCDAsyncSocket, didConnectToHost host:String, port p:UInt16) {

       println("Connected to \(host) on port \(p).")

       self.socket = socket

       getSystemInfo()
       getSystemStatus()

    }

    func send(msgBytes: [UInt8]) {

        var msgData = NSData(bytes: msgBytes, length: msgBytes)
        socket.writeData(msgData, withTimeout: -1.0, tag: 0)
        socket.readDataWithTimeout(-1.0, tag: 0)

    }

    func getSystemInfo() {

        var sendBytes:[UInt8] = [0x0, 0x1, 0x2, 0x3]
        send(sendBytes)

    }

    func getSystemStatus() {

        var sendBytes:[UInt8] = [0x4, 0x5, 0x6, 0x7]
        send(sendBytes)

    }


    public func socket(socket : GCDAsyncSocket!, didReadData data:NSData!, withTag tag:Int){

         var msgData = NSMutableData()
         msgData.setData(data)

         var msgType:UInt16 = 0
         msgData.getBytes(&msgType, range: NSRange(location: 2,length: 1))

         println(msgType)

      }
}

任何建议都会很棒-谢谢!

最佳答案

因此,我决定为此使用NSOperation。

使用以下代码创建了一个名为SyncRequest.swift的类文件:

import Foundation

class SyncRequest : NSOperation {

 var socket:GCDAsyncSocket! = nil
 var msgData:NSData! = nil

 override var concurrent: Bool {
   return false
 }

 override var asynchronous: Bool {
   return false
 }

 private var _executing: Bool = false
 override var executing: Bool {
    get {
        return _executing
    }
    set {
        if (_executing != newValue) {
            self.willChangeValueForKey("isExecuting")
            _executing = newValue
            self.didChangeValueForKey("isExecuting")
        }
    }
}

private var _finished: Bool = false;
override var finished: Bool {
    get {
        return _finished
    }
    set {
        if (_finished != newValue) {
            self.willChangeValueForKey("isFinished")
            _finished = newValue
            self.didChangeValueForKey("isFinished")
        }
    }
}

/// Complete the operation
func completeOperation() {
    executing = false
    finished  = true
}

override func start() {
    if (cancelled) {
        finished = true
        return
    }

    executing = true

    main()
}


 override func main() -> (){
    println("starting...")

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "didReadData:", name: "DidReadData", object: nil)

    sendData()
}


    func sendData() {
        socket.writeData(msgData, withTimeout: -1.0, tag: 0)
        println("Sending: \(msgData)")
        socket.readDataWithTimeout(-1.0, tag: 0)
    }


    func didReadData(notif: NSNotification) {
        println("Data Received!")

        NSNotificationCenter.defaultCenter().removeObserver(self, name: "DidReadData", object: nil)

        completeOperation()

    }

}

然后,当我需要向控制器发送东西时,请执行以下操作:
// sync the request to the controller
let queue = NSOperationQueue() // sync request queue
let requestOperation = SyncRequest()
requestOperation.socket = socket // pass the socket  to send through
requestOperation.msgData = msgData // pass the msgData to send
queue.maxConcurrentOperationCount = 1
queue.addOperation(requestOperation)

当数据来自处理GCDAsyncSocket的“didReadData”委托的地方时,请不要忘记发送NSNotification。
public func socket(socket : GCDAsyncSocket!, didReadData data:NSData!, withTag tag:Int){

  ...
  NSNotificationCenter.defaultCenter().postNotificationName("DidReadData", object: data)
  ...

}

07-28 06:55