Swift使用UnsafePointer <String>从UnsafeMutablePointer <Void>获取值

use*_*182 6 pointers reference dereference swift

我试图通过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)")
}
Run Code Online (Sandbox Code Playgroud)

但是,以下代码不起作用.

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)")
}
Run Code Online (Sandbox Code Playgroud)

一旦我到达以下行:

var pStr:String = UnsafePointer<String>(contextInfo).memory
Run Code Online (Sandbox Code Playgroud)

我一直收到以下错误:

Thread 1: EXC_BAD_ACCESS(code=1, address=0x0)
Run Code Online (Sandbox Code Playgroud)

任何有关这方面的帮助将不胜感激.

谢谢.

更新

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)")
    }
}
Run Code Online (Sandbox Code Playgroud)

我试图不使用全局变量,除非我必须.我可能不得不因为我能够执行上面的代码,似乎我不需要使用全局变量.

rin*_*aro 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()
Run Code Online (Sandbox Code Playgroud)
  • Unmanaged<NSString>.passRetained(str) 增加保留计数.
  • Unmanaged<NSString>.fromOpaque(...).takeRetainedValue() 递减它,并提取对象.

我认为,使用纯粹的 Swift String是不可能的.因为Stringstruct和被分配在堆栈内存中.也许它的缓冲区是在堆中分配的,但我们无法直接访问它.