web-dev-qa-db-ja.com

Swift 2-オブジェクトに対するUnsafeMutablePointer <Void>

私のような方法がある場合:

func someMethod(contextPtr: UnsafeMutablePointer<Void>)

contextPtrからオブジェクトを取得するにはどうすればよいですか?

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

与える:

「Void」は「MyObject」に変換できません

秘密のソースは何ですか


もっと詳しく:

ここで実際に行っているのは、SCNetworkReachabilityのグローバルコールバック関数を設定することです。

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

    let r:Reachability = info.memory
}

次に、次のようにコールバックを追加します。

var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
var s = self
withUnsafeMutablePointer(&s) {
    context.info = UnsafeMutablePointer($0)
}
SCNetworkReachabilitySetCallback(reachability, callback, &context)
25
Ashley Mills

これは機能するはずです。オブジェクトポインターを不透明なアンマネージポインターとしてコールバックに渡します。

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

コールバックで取得します:

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

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

}

もちろん、これは、コールバックがインストールされている限り、オブジェクトへの強い参照が存在し、オブジェクトの割り当てが解除されないことを前提としています。

更新:「安全でない」関数を使用する場合は、オブジェクトポインタからvoidポインタへの変換とその逆の変換の両方を簡略化できることに注意してください。

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

生成されたアセンブリコードは–私が見る限り–同一です。

更新2:参照 SwiftでUnsafeMutablePointer <Void>型に自分自身をキャストする方法 「ブリッジング」といくつかのヘルパー関数の詳細についてここで使用されます。


Swift 3アップデート(Xcode 8ベータ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()
        // ...
    }
}
43
Martin R