Swift: Pass data to a closure that captures context

后端 未结 1 1449
悲哀的现实
悲哀的现实 2020-12-03 05:08

I am trying to call a function when the internet connection is restored and the updateOnConnection variable is true. Here is my code:

func check         


        
1条回答
  •  独厮守ぢ
    2020-12-03 05:38

    Similar as in How to use instance method as callback for function which takes only func or literal closure, you have to convert self to a void pointer, store that in the context, and convert it back to an object pointer in the closure:

    func checkForConnection() {
    
        let host = "reddit.com"
        var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
        context.info = UnsafeMutablePointer(Unmanaged.passUnretained(self).toOpaque())
    
        let reachability = SCNetworkReachabilityCreateWithName(nil, host)!
    
        SCNetworkReachabilitySetCallback(reachability, { (_, flags, info) in
            if flags.rawValue == 0 { //internet is not connected
    
            } else { //internet became connected
                let mySelf = Unmanaged.fromOpaque(COpaquePointer(info)).takeUnretainedValue()
    
                if mySelf.updateOnConnection {
                    mySelf.refreshWallpaper()
                }
            }
            }, &context)
    
        SCNetworkReachabilityScheduleWithRunLoop(reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes)
    }
    

    See also How to cast self to UnsafeMutablePointer type in swift for more details about this mechanism.

    Remark: if flags.rawValue == 0 can be expressed slightly more elegant as if flags.isEmpty, but what you actually should check is if flags.contains(.Reachable).


    Update for Swift 3 (Xcode 8 beta 6):

    func checkForConnection() {
    
        let host = "reddit.com"
        var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
        context.info = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())
    
        let reachability = SCNetworkReachabilityCreateWithName(nil, host)!
    
        SCNetworkReachabilitySetCallback(reachability, { (_, flags, info) in
            if let info = info {
                if flags.rawValue == 0 { //internet is not connected
    
                } else { //internet became connected
                    let mySelf = Unmanaged.fromOpaque(info).takeUnretainedValue()
                    // ...
                }
            }
        }, &context)
    
        SCNetworkReachabilityScheduleWithRunLoop(reachability, CFRunLoopGetMain(), CFRunLoopMode.commonModes.rawValue)
    }
    

    0 讨论(0)
提交回复
热议问题