Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 闭包捕获上下文_Swift_Callback_Closures - Fatal编程技术网

Swift 闭包捕获上下文

Swift 闭包捕获上下文,swift,callback,closures,Swift,Callback,Closures,当我尝试更改闭包中的变量时,会出现以下错误: 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 = { (readStr

当我尝试更改闭包中的变量时,会出现以下错误:

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
    // 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)
是否有解决方法,或者是否仍然可以更改闭包中的变量

我的代码:

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)
let回调:@convention(c)(readStream:CFWriteStream!,事件:cfstreamventtype,数据:UnsafeMutablePointer)->Void={
(读取流、事件、数据)->Void in
切换事件{
案例cfstreamventtype.error发生:
self.isError=true
打破
案例CfStreamVentType.EndEnCounted:
self.isrunlop=false
打破
案例cfstreamventtype.hasbytes可用:
打破
案例cfstreamventtype.OpenCompleted:
打破
案例CFStreamVentType.CanAcceptBytes:
self.bytesWrite=CFWriteStreamWrite(读流、self.buffer、self.leftOverSize)
打破
违约:
打破
}
}
let registeredEvents:CFOptionFlags=
CFStreamEventType.CanAcceptBytes.rawValue|
cfstreamventtype.HasBytesAvailable.rawValue|
CFStreamEventType.ErrorOccurrend.rawValue|
cfstreamventtype.endencounted.rawValue|
cfstreamventtype.None.rawValue
var context=CFStreamClientContext(版本:CFIndex(0),信息:nil,保留:nil,发布:nil,副本描述:nil)
let stream=CFWriteStreamCreateWithFTPURL(nil,uploadURL)。takeUnrepainedValue()
CFWriteStreamSetClient(流、registeredEvents、回调和上下文)

我假设您希望使用此回调将其作为第三个参数(
clientCB
)传递给

由于该参数具有以下类型定义

typedef void (*CFWriteStreamClientCallBack) ( CFWriteStreamRef stream, CFStreamEventType eventType, void *clientCallBackInfo );
您只能使用全局函数或不从周围上下文捕获任何变量(如
self
)的闭包

在这种情况下,您可以将
self
传递到
CFStreamClientContext
结构的
info
字段(CFWriteStreamSetClient的第四个参数),并使用该信息在闭包中重建
self

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
    // 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)
let回调:@convention(c)(readStream:CFWriteStream!,事件:cfstreamventtype,数据:UnsafeMutablePointer)->Void={
(读取流、事件、数据)->Void in
//假设您的类名是Client
let client=unsafeBitCast(data.memory,client.self)
切换事件{
案例cfstreamventtype.error发生:
client.isError=true
案例CfStreamVentType.EndEnCounted:
client.isrunlop=false
案例cfstreamventtype.hasbytes可用:
打破
案例cfstreamventtype.OpenCompleted:
打破
案例CFStreamVentType.CanAcceptBytes:
client.bytesWrite=CFWriteStreamWrite(readStream、client.buffer、client.leftOverSize)
违约:
打破
}
}
var context=CFStreamClientContext(版本:0,信息:unsafeBitCast(self,UnsafeMutablePointer.self),retain:nil,release:nil,copyDescription:nil)
CFWriteStreamSetClient(流、0、回调和上下文)

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

回调必须是一个全局函数或一个不捕获上下文的闭包。类似的问题:或者。我如何知道是否有错误?您必须将
self
转换为空指针,将其作为用户数据传递给回调,然后在回调中将其转换回对象指针。另请参见。我一直收到以下错误:
命令失败,原因是信号:分段错误:11
。在哪一行?如何调用
CFWriteStreamSetClient
?@HovyTech这似乎是一个swift编译器问题,请参阅。但是,您将
nil
传递给了
CFStreamClientContext
的第二个参数,请查看我关于代码应该是什么样子的更新答案(假设Apple修复了编译器崩溃)