当我尝试更改闭包中的变量时,我收到此错误:
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)
答案 0 :(得分:5)
我假设您要使用此回调将其作为第三个参数(clientCB
)传递给CFWriteStreamSetClient。
由于该参数具有以下类型定义
typedef void (*CFWriteStreamClientCallBack) ( CFWriteStreamRef stream, CFStreamEventType eventType, void *clientCallBackInfo );
你只能使用全局函数或不能从周围上下文中捕获任何变量(如self
)的闭包。
在这种情况下,您可以执行的操作是将self
传递给info
结构的CFStreamClientContext
字段(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
,否则如果流接收到新事件,您可能会遇到崩溃。