Swift: Pass data to a closure that captures context

后端 未结 1 1446
悲哀的现实
悲哀的现实 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<ViewController>.fromOpaque(COpaquePointer(info)).takeUnretainedValue()
    
                if mySelf.updateOnConnection {
                    mySelf.refreshWallpaper()
                }
            }
            }, &context)
    
        SCNetworkReachabilityScheduleWithRunLoop(reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes)
    }
    

    See also How to cast self to UnsafeMutablePointer<Void> 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<ViewController>.fromOpaque(info).takeUnretainedValue()
                    // ...
                }
            }
        }, &context)
    
        SCNetworkReachabilityScheduleWithRunLoop(reachability, CFRunLoopGetMain(), CFRunLoopMode.commonModes.rawValue)
    }
    
    0 讨论(0)
提交回复
热议问题