当我尝试更改闭包中的变量时,我收到此错误: A C function pointer cannot be formed from a closure that captures context 是否有解决方法或是否仍然可以更改闭包内的变量? 我的代码: let callback: @co
A C function pointer cannot be formed from a closure that captures context
是否有解决方法或是否仍然可以更改闭包内的变量?
我的代码:
let callback: @convention(c) (readStream: CFWriteStream!, event: CFStreamEventType, data: UnsafeMutablePointer<Void>) -> Void = {
(readStream, event, data) -> Void in
switch event {
case CFStreamEventType.ErrorOccurred:
self.isError = true
break
case CFStreamEventType.EndEncountered:
self.isRunLoop = false
break
case CFStreamEventType.HasBytesAvailable:
break
case CFStreamEventType.OpenCompleted:
break
case CFStreamEventType.CanAcceptBytes:
self.bytesWritten = CFWriteStreamWrite(readStream, self.buffer, self.leftOverSize)
break
default:
break
}
}
let registeredEvents: CFOptionFlags =
CFStreamEventType.CanAcceptBytes.rawValue |
CFStreamEventType.HasBytesAvailable.rawValue |
CFStreamEventType.ErrorOccurred.rawValue |
CFStreamEventType.EndEncountered.rawValue |
CFStreamEventType.None.rawValue
var context = CFStreamClientContext(version: CFIndex(0), info: nil, retain: nil, release: nil, copyDescription: nil)
let stream = CFWriteStreamCreateWithFTPURL(nil, uploadURL).takeUnretainedValue()
CFWriteStreamSetClient(stream, registeredEvents, callback, &context)
我假设你想使用这个回调将它作为第三个参数(clientCB)传递给
CFWriteStreamSetClient.
由于该参数具有以下类型定义
typedef void (*CFWriteStreamClientCallBack) ( CFWriteStreamRef stream, CFStreamEventType eventType, void *clientCallBackInfo );
您只能使用全局函数或不从周围上下文捕获任何变量(如self)的闭包.
在这种情况下你可以做的是将self传递给CFStreamClientContext结构的info字段(CFWriteStreamSetClient的第4个参数),并使用该信息在闭包内重构self:
let callback: @convention(c) (readStream: CFWriteStream!, event: CFStreamEventType, data: UnsafeMutablePointer<Void>) -> Void = {
(readStream, event, data) -> Void in
// assuming your class name is Client
let client = unsafeBitCast(data.memory, Client.self)
switch event {
case CFStreamEventType.ErrorOccurred:
client.isError = true
case CFStreamEventType.EndEncountered:
client.isRunLoop = false
case CFStreamEventType.HasBytesAvailable:
break
case CFStreamEventType.OpenCompleted:
break
case CFStreamEventType.CanAcceptBytes:
client.bytesWritten = CFWriteStreamWrite(readStream, client.buffer, client.leftOverSize)
default:
break
}
}
var context = CFStreamClientContext(version: 0, info: unsafeBitCast(self, UnsafeMutablePointer<Void>.self), retain: nil, release: nil, copyDescription: nil)
CFWriteStreamSetClient(stream, 0, callback, &context)
注意.与Objective-C一样,您需要确保在流之前不会销毁self,否则如果流接收到新事件,您可能会遇到崩溃.
