我正在尝试将contextInfo
类型的UnsafeMutablePointer<Void>
传递给UISaveVideoAtPathToSavedPhotosAlbum
并在回调函数中使用它。由于某些原因,当我在回调函数中时,我无法使用contextInfo
作为字符串访问UnsafePointer<String>(x).memory
。
我很确定这是一件很简单的事情,但我已经花了很多时间试图解决这个问题。
以下是我尝试过的一些代码。
以下代码有效。
var testStr:String = "hello"
takesAMutableVoidPointer(&testStr)
func takesAMutableVoidPointer(x: UnsafeMutablePointer<Void>){
var pStr:String = UnsafePointer<String>(x).memory
println("x = \(x)")
println("pStr = \(pStr)")
}
但是以下代码不起作用。
var testStr:String = "hello"
if UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(filePath){ //the filePath is compatible
println("Compatible")
//UISaveVideoAtPathToSavedPhotosAlbum(filePath, self, nil, nil)
UISaveVideoAtPathToSavedPhotosAlbum(filePath, self, "video:didFinishSavingWithError:contextInfo:", &testStr)
}
else{
println("Not Compatible")
}
func video(video: NSString, didFinishSavingWithError error:NSError, contextInfo:UnsafeMutablePointer<Void>){
var pStr:String = UnsafePointer<String>(contextInfo).memory
println("contextInfo = \(contextInfo)")
println("pStr = \(pStr)")
}
一旦我到达以下行:
var pStr:String = UnsafePointer<String>(contextInfo).memory
我一直收到以下错误:
Thread 1: EXC_BAD_ACCESS(code=1, address=0x0)
对此的任何帮助将不胜感激。
感谢。
更新
Rintaro评论说testStr需要达到顶级水平,但以下代码可以正常工作。
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var testStr:String = "hello"
takesAMutableVoidPointer(&testStr)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func takesAMutableVoidPointer(x: UnsafeMutablePointer<Void>){
var answer = UnsafePointer<String>(x).memory
println("x = \(x)")
println("answer = \(answer)")
}
}
我试图不使用全局变量,除非我必须这样做。我可能不得不因为我能够执行上面的代码,好像我不需要使用全局变量。
答案 0 :(得分:7)
正如OP评论中所讨论的,testStr
已被释放。
有没有办法强制保留在函数中创建的变量?然后稍后发布?
这不是不可能,但我不知道这是最好的方法。
无论如何,尝试使用Playground或OS X“命令行工具”模板:
import Foundation
func foo() {
var str:NSString = "Hello World"
let ptr = UnsafePointer<Void>(Unmanaged<NSString>.passRetained(str).toOpaque())
bar(ptr)
}
func bar(v:UnsafePointer<Void>) {
let at = dispatch_time(
DISPATCH_TIME_NOW,
Int64(2.0 * Double(NSEC_PER_SEC))
)
dispatch_after(at, dispatch_get_main_queue()) {
baz(v)
}
}
func baz(v:UnsafePointer<Void>) {
println("notified")
let str = Unmanaged<NSString>.fromOpaque(COpaquePointer(v)).takeRetainedValue()
println("info: \(str)")
}
foo()
println("started")
dispatch_main()
Unmanaged<NSString>.passRetained(str)
会增加保留计数。Unmanaged<NSString>.fromOpaque(...).takeRetainedValue()
递减它,并提取对象。我认为,使用 pure Swift String
是不可能的。因为String
是struct
并且在堆栈内存中分配。也许它的缓冲区是在堆中分配的,但我们无法直接访问它。