Swift gets value from UnsafeMutablePointer <Void> using UnsafePointer <String>
I am trying to pass a contextInfo type UnsafeMutablePointer<Void> to UISaveVideoAtPathToSavedPhotosAlbum and use it in a callback function. For some reason, I cannot access contextInfo as a string using UnsafePointer<String>(x).memory when I enter the callback function.
I am sure this is something simple, but I missed many hours trying to figure it out.
Below is the code I 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)") } As soon as I move to the next 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 noted that testStr should be top, 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 try not to use global variables unless needed. I may have to, but since I can execute the above code, it seems that I do not need to use a global variable.
As discussed in the OP comments, testStr already released.
Is there a way to force save a variable created in a function? Then release it later?
This is not impossible, but I do not know what is the best way to do this.
In any case, try this using the playground or OS X Command Line Tool:
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)increases the number of deductions.Unmanaged<NSString>.fromOpaque(...).takeRetainedValue()reduces it and retrieves the object.
I think using pure Swift String not possible. because String is a struct and is allocated on the stack. Perhaps its buffer has been allocated to the heap, but we cannot access it directly.