当前位置 : 主页 > 手机开发 > 其它 >

关闭捕获上下文Swift

来源:互联网 收集:自由互联 发布时间:2021-06-11
当我尝试更改闭包中的变量时,我收到此错误: 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,否则如果流接收到新事件,您可能会遇到崩溃.

网友评论