Swift 2-Unfememutable pointer to object

si j'ai une méthode comme:

func someMethod(contextPtr: UnsafeMutablePointer<Void>)

Comment puis-je obtenir l'objet du contextPtr ?

func someMethod(contextPtr: UnsafeMutablePointer<Void>){    
    let object:MyObject = contextPtr.memory
}

donne:

"Void" n'est pas convertible à "MyObject'

Quel est le secret de la sauce


plus de détails:

ce que je fais ici, c'est mettre en place une fonction de rappel globale pour SCNetworkReachability :

func callback(reachability:SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutablePointer<Void>) {

    let r:Reachability = info.memory
}

et ajouter ensuite le rappel comme suit:

var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
var s = self
withUnsafeMutablePointer(&s) {
    context.info = UnsafeMutablePointer("151930920")
}
SCNetworkReachabilitySetCallback(reachability, callback, &context)
21
demandé sur Ashley Mills 2015-06-11 19:54:06

2 réponses

cela devrait fonctionner: passer le pointeur de l'objet comme un pointeur opaque non géré au rappel:

context.info = UnsafeMutablePointer(Unmanaged.passUnretained(myObject).toOpaque())
SCNetworkReachabilitySetCallback(reachability, callback, &context) 

et récupérer dans le callback via:

func callback(reachability:SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutablePointer<Void>) {

    let myObject = Unmanaged<MyObject>.fromOpaque(COpaquePointer(info)).takeUnretainedValue()

}

bien sûr, cela suppose qu'une référence forte à l'objet existe tant que le rappel est installé, de sorte que l'objet n'est pas désalloué.

mise à jour: notez que les deux conversions de pointeur d'objet à nul pointeur et le dos peut être simplifié si vous êtes prêt à utiliser des fonctions" dangereuses":

context.info = unsafeAddressOf(myObject)
// ...
myObject = unsafeBitCast(info, MyObject.self)

le code d'assemblage généré est – pour autant que je puisse voir – identique.

mise à Jour 2: Voir aussi la manière de voter, de soi à UnsafeMutablePointer type de swift pour plus d'informations à propos de la fonction" passerelle " et de quelques fonctions d'aide qui peuvent être utilisées ici.


mise à jour de Swift 3 (Xcode 8 beta 6):

var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
context.info = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())

// ...

func callback(reachability:SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutableRawPointer?) {
    if let info = info {
        let myObject = Unmanaged<MyObject>.fromOpaque(info).takeUnretainedValue()
        // ...
    }
}
39
répondu Martin R 2017-05-23 12:18:20
struct S {
    var i: Int = 10
}
var first = S()

func foo(contextPtr: UnsafeMutablePointer<Void>){
    let pS = UnsafeMutablePointer<S>(contextPtr)
    pS.memory.i = 100
}
print(first.i) // 10
foo(&first)
print(first.i) // 100

si nous avons besoin passer comme Unsafemutable pointer self à la fonction async

import XCPlayground
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true

import Foundation
// can be struct, class ...
class C {
    let queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT)
    var s: String = ""
    func foo() {
        var c = self
        dispatch_async(queue) { () -> Void in
            f(&c)
        }

    }
}

func f(pV: UnsafeMutablePointer<Void>) {
    let pC = UnsafeMutablePointer<C>(pV)
    sleep(1)
    print(pC.memory.s)
}

var c1: C? = C()
c1!.s = "C1"
c1!.foo()        // C1
var c2: C? = C()
c2!.s = "C2"
c2!.foo()        // C2
c1 = nil
c2 = nil
print("test")
-1
répondu user3441734 2015-11-11 15:58:17