我正在尝试在 macOS 上的 Swift 中实现“带进度的文件复制”。 经过大量搜索,我刚刚找到 rustle's implement in Objective-C . 它工作得很好。 但我希望它“swift ”。 我尝试了一些简化的代码:
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
var copyfileCallback: copyfile_callback_t = {(what, stage, state, sourcePath, destPath, context) -> Int32 in
return COPYFILE_CONTINUE
}
@IBOutlet weak var window: NSWindow!
func applicationDidFinishLaunching(_ aNotification: Notification) {
let src = NSURL(fileURLWithPath: "Source_File_Path").fileSystemRepresentation
let dst = NSURL(fileURLWithPath: "Destination_File_Path").fileSystemRepresentation
let flag: copyfile_flags_t = UInt32(COPYFILE_ALL)
let state = copyfile_state_alloc()
// If I implement this, the copyfile() method will complain "EXC_BAD_ACCESS(code=2..." error
copyfile_state_set(state, UInt32(COPYFILE_STATE_STATUS_CB), ©fileCallback)
copyfile(src, dst, state, flag)
}
}
基本函数 copyfile()
工作正常。但是,如果我通过向 copyfile_state_set()
提供一个 copyfileCallback
闭包指针来实现回调函数,那么 copyfile()
只会提示“Bad_Access.. ”。
我想也许闭包是在 C api 尝试访问它之前发布的。
但我不知道如何解决这个问题......
任何线索将不胜感激。
最佳答案
错误在这里:
copyfile_state_set(state, UInt32(COPYFILE_STATE_STATUS_CB), ©fileCallback)
因为是将 copyfileCallback
变量的地址 传递给函数,而不是函数指针本身。在 C 中,您可以将任意函数作为 void *
参数传递。在 Swift 中,您必须显式地将函数转换为指针:
let state = copyfile_state_alloc()
copyfile_state_set(state, UInt32(COPYFILE_STATE_STATUS_CB),
unsafeBitCast(copyfileCallback, to: UnsafeRawPointer.self))
并且不要忘记在复制操作之后最终释放内存:
copyfile_state_free(state)
备注:在Swift中推荐使用(值叠加类型)URL
代替NSURL
:
let srcURL = URL(fileURLWithPath: "Source_File_Path")
let destURL = URL(fileURLWithPath: "Destination_File_Path")
let result = srcURL.withUnsafeFileSystemRepresentation { srcFile in
destURL.withUnsafeFileSystemRepresentation { destFile in
copyfile(srcFile, destFile, state, flag)
}
}
关于swift - 从 Cocoa 中的 C api 调用 Swift 闭包时出现访问错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55218788/