微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

关闭捕获上下文Swift

当我尝试更改闭包中的变量时,我收到此错误

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!,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),copyDescription: nil)
CFWriteStreamSetClient(stream,&context)

注意.与Objective-C一样,您需要确保在流之前不会销毁self,否则如果流接收到新事件,您可能会遇到崩溃.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐