当我尝试更改闭包中的变量时,我收到此错误: 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,否则如果流接收到新事件,您可能会遇到崩溃.