2015-11-05 53 views
9

我試圖調用一個函數在恢復網絡連接時和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() 
     } 

原因錯誤:「A C function pointer cannot be formed from a closure that captures context

我不知道如何檢查的updateOnConnection和呼叫狀態refreshWallpaper()在閉包中監視互聯網連接的變化。我該如何解決這個問題,還是應該使用完全不同的解決方法?

回答

10

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)


更新夫特3(Xcode的8個β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

我正在此錯誤夫特3(在一個Xcode 8測試版):「類型的值 '非管理型'在要分配給context.info的行中沒有成員「toOpaque」。即我無法編譯你的代碼。你知道爲什麼會出現這種情況嗎? – Drux

+1

@Drux:不同的Xcode 8版本之間的「不安全的指針」API有一些變化。我現在更新了當前Xcode 8 beta 6的代碼。 –

+0

Thx!令人驚訝的是Swift語法仍然會發生什麼實質性的變化。 – Drux