Swift получить значение от UnsafeMutablePointer с помощью UnsafePointer
Я пытаюсь передать 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)
Любая помощь в этом была бы очень признательна.
Спасибо.
Обновить
Ринтаро прокомментировал, что 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)")
}
}
Я стараюсь не использовать глобальные переменные без крайней необходимости. Возможно, мне придется это сделать, но поскольку я могу выполнить приведенный выше код, похоже, что я это делаю. не нужно использовать глобальную переменную.1 ответ:
Как обсуждалось в комментариях 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()
уменьшает его и извлекает объект.Я думаю, что использование чистого Swift
String
невозможно. потому чтоString
являетсяstruct
и выделяется в стековой памяти. Может быть, буфер его расположен в куче, но мы не можем получить к нему прямой доступ.