Swift:将数据传递给捕获上下文的闭包

标签 swift macos cocoa

我正在尝试在互联网连接恢复且 updateOnConnection 变量为真时调用一个函数。这是我的代码:

func checkForConnection() {
    let host = "reddit.com"
    var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
    let reachability = SCNetworkReachabilityCreateWithName(nil, host)!

    SCNetworkReachabilitySetCallback(reachability, { (_, flags, _) in
        if flags.rawValue == 0 { //internet is not connected

        } else { //internet became connected
            if self.updateOnConnection {
                self.refreshWallpaper()
            }
        }
    }, &context)

    SCNetworkReachabilityScheduleWithRunLoop(reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes)
}

我的问题是这些行:

        if self.updateOnConnection {
            self.refreshWallpaper()
        }

导致错误:“无法从捕获上下文的闭包中形成 C 函数指针

我不确定如何检查 updateOnConnection 的状态并在监视 Internet 连接变化的闭包中调用 refreshWallpaper()。我该如何解决这个问题,或者我应该使用完全不同的解决方法?

最佳答案

类似于How to use instance method as callback for function which takes only func or literal closure ,你必须转换 self 到一个空指针,将其存储在上下文中, 并将其转换回闭包中的对象指针:

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)
}

另见 How to cast self to UnsafeMutablePointer<Void> type in swift 有关此机制的更多详细信息。

备注:if flags.rawValue == 0可以稍微多表达一点 优雅的 if flags.isEmpty,但你实际上应该 检查是 if flags.contains(.Reachable)


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)
}

关于Swift:将数据传递给捕获上下文的闭包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33551191/

相关文章:

swift - 如何通过引用将 UnsafePointer<UInt8> 传递给 C API?

iOS/Swift/Firebase 身份验证 : Help Needed on Accessing "isNewUser"

macos - ./配置 : No such file or directory - build nginx-rtmp-module on Mac OS X

JAVAFx 构建失败

objective-c - 如何按字符串中的每个字符拆分 NSString?

cocoa - Cocoa 有布局/几何管理吗?

ios - 在 iOS 游戏中存储高分的安全方法?

ios - 为图表添加额外的左右偏移

php - 无法在 mac os MAMP PRO 上设置 php mongo 驱动程序

macos - 在 macOS 10.11+ 上过滤或搜索 NSCollectionView