Swift получить значение от UnsafeMutablePointer с помощью UnsafePointer

Я пытаюсь передать contextInfo типаUnsafeMutablePointer<Void> to 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)")
    }
}

Я пытаюсь не использовать глобальные переменные, если мне не нужно. Я возможно, придется, но поскольку я могу выполнить приведенный выше код, кажется, что мне не нужно использовать глобальную переменную.

1 ответов


как обсуждалось в комментариях OP,testStr уже освобожден.

есть ли способ принудительно сохранить переменную, которая была создана в функции? Тогда отпустите его позже?

это не невозможно, но я не знаю, что это лучший способ сделать это.

в любом случае, попробуйте это с игровой площадкой или 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() уменьшает его и извлекает объект.

Я думаю, используя чисто Свифт String - это невозможно. потому что String is struct и выделяется память в стеке. Возможно, буфер его выделяется в куче, но мы не можем получить к нему прямой доступ.