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

标签 swift

如何为以下函数创建自定义完成处理程序?这是通过 Starscream 写入 websocket,如果它不是 nil,我希望收到响应。

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

这里是 deqeueWrite 函数:

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

}

最佳答案

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

关于swift - 如何制作自定义完成处理程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49418489/

相关文章:

swift - 如何链接另一个 xcode 项目生成的 Swift 模块?

swift - 将锻炼参数上传到 Strava - Swift

ios - 加大节点的攻丝面积。 ios swift

swift - 一次多次调用 DispatchSemaphore 的 wait() 是否安全?

swift - 使用隐式解包选项但测试 nil 与可选绑定(bind)是否存在技术缺点?

ios - 在 IOS 中显示警报时,键盘不会从 View 中退出

ios - 使用 Swift 将 JSON 字符串转为 NSDictionary

arrays - 如何在同一个 for 循环中运行三个单独的数组?

swift - 如何获取两个 "places"中的firebase数据?

swift - 如何使用全局变量,以便可以使用Swift 4在不同的函数中识别它们?