Swift get value from UnsafeMutablePointer<Void> using UnsafePointer<String>

六眼飞鱼酱① 提交于 2019-12-09 06:53:11

问题


I am trying to pass contextInfo of typeUnsafeMutablePointer<Void> to UISaveVideoAtPathToSavedPhotosAlbum and use it in the callback function. For some reason I am unable to access contextInfo as a string using UnsafePointer<String>(x).memory when I am in the callback function.

I am pretty sure it is something simple I am missing but have spent way to many hours trying to figure this out.

Below is some code that I have tried.

The following code works.

var testStr:String = "hello"
takesAMutableVoidPointer(&testStr)

func takesAMutableVoidPointer(x: UnsafeMutablePointer<Void>){
    var pStr:String = UnsafePointer<String>(x).memory
    println("x = \(x)")
    println("pStr = \(pStr)")
}

However the following code does not work.

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)")
}

Once I get to the following line:

var pStr:String = UnsafePointer<String>(contextInfo).memory

I keep getting the following error:

Thread 1: EXC_BAD_ACCESS(code=1, address=0x0)

Any help with this would be greatly appreciated.

Thanks.

Update

Rintaro commented that testStr needs to be top level but the following code works.

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)")
    }
}

I am trying not to use global variables unless I have to. I may have to but since I am able to execute the above code, it seems as though I do not need to use a global variable.


回答1:


As discussed in OP comments, testStr has already been freed.

Is there any way to force the retaining of a variable that has been created in a function? Then release it later?

It's not impossible, but I don't know this is the best way to do that.

Anyway, try this with Playground or OS X "Command Line Tool" template:

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) increments the retain count.
  • Unmanaged<NSString>.fromOpaque(...).takeRetainedValue() decrements it, and extract the object.

I think, using pure Swift String is impossible. because String is struct and is allocated in stack memory. Maybe the buffer of it is allocated in heap, but we cannot access it directly.



来源:https://stackoverflow.com/questions/26776662/swift-get-value-from-unsafemutablepointervoid-using-unsafepointerstring

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!