2016-01-01 45 views
3

我最近花了一些時間學習Swift編程語言,我喜歡它。爲了幫助我學習,我一直在使用XCode 7編寫幾個簡單的應用程序。其中一個應用程序是手電筒,其中一個功能是閃光燈。我決定使用NSTimer類來安排在設定的時間間隔內調用手電筒切換功能,從而給出一個很好的頻閃效果。我的計時器代碼第一條裂縫如下: -Swift - NSTimer爲用戶信息傳遞錯誤的值參數

NSTimer.scheduledTimerWithTimeInterval(0.5, target: self.torch, selector: "toggleTorch:", userInfo: false, repeats: true) 

正如你所看到的,我用我自己定製的火炬對象來處理閃光切換功能。我通過我已指定爲一個實例變量作爲目標PARAM火炬對象,然後我請在火炬類下面的函數,這是我通過作爲選擇: -

func toggleTorch(adjustingBrightness: Bool) -> Bool { 
    let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo) 

    defer { 
     device.unlockForConfiguration() 
    } 

    guard device.hasTorch else { 
     return false 
    } 
    do { 
     try device.lockForConfiguration() 

     if !adjustingBrightness && device.torchMode == AVCaptureTorchMode.On { 
      device.torchMode = AVCaptureTorchMode.Off 
     } 
     else if !adjustingBrightness && device.torchMode == AVCaptureTorchMode.Off { 
      try device.setTorchModeOnWithLevel(brightnessLevel) 
     }    
     else if adjustingBrightness && device.torchMode == AVCaptureTorchMode.On { 
      try device.setTorchModeOnWithLevel(brightnessLevel) 
     } 
    } catch { 
     return false 
    } 

    return true 
} 

我遇到的問題是,當定時器調用toggleTorch方法,它將true的值作爲參數傳遞,即使我已將false專門傳遞給定時器作爲userInfo參數。

所以我撓我的腦袋,想到「啊」我們試着在選擇器/方法參數中使用默認值false,並在計時器userInfo中傳遞nil參數。這樣我可以依靠每次調用默認值false。所以我的新選擇的簽名如下所示: -

func toggleTorch(adjustingBrightness: Bool = false) -> Bool 

而現在調用它的計時器已更改爲: -

NSTimer.scheduledTimerWithTimeInterval(0.5, target: self.torch, selector: "toggleTorch:", userInfo: nil, repeats: true) 

然而,儘管默認參數,無參數傳遞通過回事定時器,傳遞的值仍然是true。所以我鼓搗更多,並決定是否使用我的ViewController作爲目標對象會有所作爲。我把我的ViewController一個新的選擇,像這樣: -

func toggleTorch() { 
    torch.toggleTorch(false) 
} 

我再更新我的定時器來調用視圖控制器內的這種新方法: -

NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: "toggleTorch", userInfo: nil, repeats: true) 

「變戲法」現在工作正常,正確的布爾值false正在通過,因爲我已經通過了自己的值。這是爲什麼發生?對於信息,我一直在學習斯威夫特大約三週,所以我沒有專家

回答

2

NSTimer不會將userInfo信息作爲參數傳遞給選擇器。它將自身作爲參數傳遞,以便知道哪個計時器被調用。

您應按如下方式對其進行設置:

NSTimer.scheduledTimerWithTimeInterval(0.5, target: self.torch, selector: "strobeTimerFired:", userInfo: nil, repeats: true) 

而且有一個方法,在你的火炬對象如下:

func strobeTimerFired(timer: NSTimer) { 
    toggleTorch(false) 
} 

在這種情況下,你不需要訪問定時器對象在strobeTimerFired方法中,但最好還是包含它(可以跳過)。您可以添加其他檢查以確保觸發該方法的計時器是您期望的計時器。

如果您確實需要使用userInfo的東西,(不認爲你需要它在這種情況下),你可以在原來scheduledTimerWithTimeInterval召喚爲userInfo參數傳遞一個對象,然後你會訪問即在strobeTimerFired方法中訪問:timer.userInfo

+0

謝謝。我會嘗試這一點,並將其標記爲可接受的答案,它工作正常。它令我困惑,因爲用戶信息參數是一個可選AnyObject。如果它實際上被指定爲簽名中的NSTimer,我可能會認爲它是。蘋果課的參考資料沒有解釋得很好,但我仍然在學習。我相信這是一個很好的理由 –

+0

userInfo是一個可選的AnyObject。這不是NSTimer所在的地方。你可以通過userInfo傳遞任何東西,並在被調用的選擇器中使用它,而不是作爲被調用選擇器的參數。這總是調用選擇器的NSTimer對象。 –

+0

啊哈現在我明白了。謝謝戴夫。非常感激。祝你有個美好的新年! –