如何制作自定义完成处理程序?

时间:2018-03-22 00:06:18

标签: swift

如何为以下功能创建自定义完成处理程序?这是通过红蜘蛛写入websocket,如果不是零,我想收到回复。

open func write(string: String, completion: (() -> ())? = nil) {
  guard isConnected else { return }
  dequeueWrite(string.data(using: String.Encoding.utf8)!, code: .textFrame, writeCompletion: completion)
}

这里是deqeueWrite func:

private func dequeueWrite(_ data: Data, code: OpCode, writeCompletion: (() -> ())? = nil) {
    let operation = BlockOperation()
    operation.addExecutionBlock { [weak self, weak operation] in
        //stream isn't ready, let's wait
        guard let s = self else { return }
        guard let sOperation = operation else { return }
        var offset = 2
        var firstByte:UInt8 = s.FinMask | code.rawValue
        var data = data
        if [.textFrame, .binaryFrame].contains(code), let compressor = s.compressionState.compressor {
            do {
                data = try compressor.compress(data)
                if s.compressionState.clientNoContextTakeover {
                    try compressor.reset()
                }
                firstByte |= s.RSV1Mask
            } catch {
                // TODO: report error?  We can just send the uncompressed frame.
            }
        }
        let dataLength = data.count
        let frame = NSMutableData(capacity: dataLength + s.MaxFrameSize)
        let buffer = UnsafeMutableRawPointer(frame!.mutableBytes).assumingMemoryBound(to: UInt8.self)
        buffer[0] = firstByte
        if dataLength < 126 {
            buffer[1] = CUnsignedChar(dataLength)
        } else if dataLength <= Int(UInt16.max) {
            buffer[1] = 126
            WebSocket.writeUint16(buffer, offset: offset, value: UInt16(dataLength))
            offset += MemoryLayout<UInt16>.size
        } else {
            buffer[1] = 127
            WebSocket.writeUint64(buffer, offset: offset, value: UInt64(dataLength))
            offset += MemoryLayout<UInt64>.size
        }
        buffer[1] |= s.MaskMask
        let maskKey = UnsafeMutablePointer<UInt8>(buffer + offset)
        _ = SecRandomCopyBytes(kSecRandomDefault, Int(MemoryLayout<UInt32>.size), maskKey)
        offset += MemoryLayout<UInt32>.size

        for i in 0..<dataLength {
            buffer[offset] = data[i] ^ maskKey[i % MemoryLayout<UInt32>.size]
            offset += 1
        }
        var total = 0
        while !sOperation.isCancelled {
            let stream = s.stream
            let writeBuffer = UnsafeRawPointer(frame!.bytes+total).assumingMemoryBound(to: UInt8.self)
            let len = stream.write(data: Data(bytes: writeBuffer, count: offset-total))
            if len <= 0 {
                var error: Error?
                    let errCode = InternalErrorCode.outputStreamWriteError.rawValue
                    error = s.errorWithDetail("output stream error during write", code: errCode)
                s.doDisconnect(error)
                break
            } else {
                total += len
            }
            if total >= offset {
                if let queue = self?.callbackQueue, let callback = writeCompletion {
                    queue.async {
                        callback()
                    }
                }

                break
            }
        }
    }
    writeQueue.addOperation(operation)
}

所以现在我可以这样调用这个函数:

socket.write(string: frameJSONSring) { () -> Void in

}

但我想在该处理程序中做出响应,以便我可以从套接字中读取响应数据(如果有的话)。显然我可以在调用时将自定义响应处理程序作为参数传递:

socket.write(string: frameJSONSring) { (CUSTOM_HANDLER_HERE) -> Void in

}

1 个答案:

答案 0 :(得分:1)

open func write(string: String, completion: ((Int) -> ())?) {
  guard isConnected else { return }
  let someParameter = 5
  dequeueWrite(string.data(using: String.Encoding.utf8)!, code: .textFrame, writeCompletion: completion(someParameter))
}

请注意我:

  • 添加了Int作为传递给处理程序的参数。
  • completion更改为completion(someParameter)

然后您可以像这样使用它:

socket.write(string: frameJSONSring) { number in    
  print(number)
}

您可以将Int替换为您喜欢的任何其他类型。

也不需要= nil。如果某些内容是可选的,那么它已经默认nil