2016-08-30 4 views
-2

私は数ヶ月間スイフトを学び、マルチタイマーを作っていきたいと思っています。新人ミスを許してください!私は、ユーザーからの入力データを受け取り、カウントダウンを処理するタイマークラスを作成しました。これはすべて正常に動作しているようですが、開始ボタンをクリックしたときに残っている時間だけを表示するラベルが更新されます。次のように 私のタイマークラスのコードは次のとおりです。UILabelは時間データの変更に伴って更新されないようです

class TimerClass: NSObject { 

    var timer = NSTimer() 
    var startTimeCounter:NSTimeInterval = 0 
    var hours = Int?() 
    var minutes = Int?() 
    var seconds = Int?() 
    var timeString = String() 
    var firstCheck:Bool = true 

    func getTime() { 
     // check if user has already clicked start so as to not double up the decrement 
     if firstCheck == true { 
      startTimeCounter += (NSTimeInterval(hours!) * 3600) 
      startTimeCounter += (NSTimeInterval(minutes!) * 60) 
      startTimeCounter += NSTimeInterval(seconds!) 
      firstCheck = false 
     } 
     else { 
      firstCheck = false 
     } 
     // turn the user data into hrs mins secs 
     var timeRemaining : NSTimeInterval = startTimeCounter 

     var hoursInt = Int(timeRemaining/3600.0) 
     timeRemaining -= (NSTimeInterval(hoursInt) * 3600) 

     var minutesInt = Int(timeRemaining/60.0) 
     timeRemaining -= (NSTimeInterval(minutesInt) * 60) 

     var secondsInt = Int(timeRemaining) 
     timeRemaining -= NSTimeInterval(secondsInt) 

     var strHours = String(format: "%02d", hoursInt) 
     var strMinutes = String(format: "%02d", minutesInt) 
     var strSeconds = String(format: "%02d", secondsInt) 
     // create a string for the label 
     timeString = "\(strHours):\(strMinutes):\(strSeconds)" 
    } 

    func updateTime() { 
     startTimeCounter -= 1 
     getTime() 
    } 

    func startTimer() { 
     timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector:#selector(TimerClass.updateTime), userInfo: nil, repeats: true) 

    } 


} 

はまた、私のビューコントローラは、次のようになります

class ViewController: UIViewController { 


    @IBOutlet weak var timeRemainingLabel: UILabel! 
    @IBOutlet weak var startButton: UIButton! 
    @IBOutlet weak var setDoneButton: UIButton! 
    @IBOutlet weak var secStepper: UIStepper! 
    @IBOutlet weak var minStepper: UIStepper! 
    @IBOutlet weak var hourStepper: UIStepper! 
    @IBOutlet weak var secLabel: UILabel! 
    @IBOutlet weak var minLabel: UILabel! 
    @IBOutlet weak var hourLabel: UILabel! 
    @IBOutlet weak var setView: UIView! 
    @IBOutlet weak var timerLabel: UILabel! 
    @IBOutlet weak var setButton: UIButton! 
    @IBOutlet weak var pauseButton: UIButton! 


    var hourSelected = Int() 
    var minSelected = Int() 
    var secSelected = Int() 
    var newTimer:TimerClass = TimerClass() 
    var startPressed:Bool = false 



    override func viewDidLoad() { 
     super.viewDidLoad() 
     // Do any additional setup after loading the view, typically from a nib. 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 

     // Dispose of any resources that can be recreated. 
    } 

    // Set button pressed 
    @IBAction func setPressed(sender: AnyObject) { 
     self.setView.alpha = 0.8 
    } 

    // User closed set menu 
    @IBAction func setDonePressed(sender: AnyObject) { 
     self.setView.alpha = 0 
     newTimer.hours = Int(self.hourStepper.value) 
     newTimer.minutes = Int(self.minStepper.value) 
     newTimer.seconds = Int(self.secStepper.value) 
     newTimer.getTime() 
    } 

    // Stepper functions 
    @IBAction func hourStepperPressed(sender: AnyObject) { 
     self.hourLabel.text = String(format: "%.0f", hourStepper.value) 
    } 

    @IBAction func minStepperPressed(sender: AnyObject) { 
     self.minLabel.text = String(format: "%.0f", minStepper.value) 
    } 

    @IBAction func secStepperPressed(sender: AnyObject) { 
     self.secLabel.text = String(format: "%.0f", secStepper.value) 
    } 

    // User pressed start 
    @IBAction func startPressed(sender: AnyObject) { 
     self.newTimer.startTimer() 
     updateTimerLabel() 
     startPressed = true 
    } 

    func updateTimerLabel() { 
     timeRemainingLabel.text = newTimer.timeString 
    } 
} 

私はおそらくこの問題を回避長い道のりを行っているが、それは私であることを理解します最初の独立したアプリなので、私はまだ物事に頭を抱えています!

+0

そして、あなたは正確に何を期待していますか? 'startPressed'メソッドで' updateTimerLabel'を一度呼びます。タイマーのターゲットメソッドで呼び出すべきではないでしょうか? –

+0

ラベルを更新する関数を呼び出していません。ラベルの値を変更するように設定した値のため、ラベルを変更する必要があると思われます。それは(場合によっては、悲しいことに)それがどのように機能するかではありません。タイマーが変わるたびにラベルテキストを設定する必要があります。 – ntoonio

+0

ああ、ターゲットメソッドはタイマークラスそのものですか?クラス内からラベルを更新できませんでした。クラス内のtimerLabel.textにアクセスできるように、デリゲートなどを使用する必要がありますか? – EtherCode

答えて

1

ユーザーが完了ボタンを選択したときにのみUIを更新します。

TimerClassがUIを更新する必要があることをView Controllerに知らせるためのもう1つのタイマーがありません。

TimerClassでプロトコルを作成し、ビューコントローラーをタイマーの委任オブジェクトとして設定できます。

このような何か:その後、

protocol TimerDelegate: class { 
    /** 
    * Tell the delegate to update the interface 
    **/ 
    func updateUI() 
} 

class TimerClass: NSObject { 
    var timer = NSTimer() 
    ... 
    var firstCheck:Bool = true 

    weak var delegate: TimerDelegate? 

    func getTime() { 
     /// 
    } 

    func updateTime() { 
     startTimeCounter -= 1 
     getTime() 
     delegate?.updateUI() 
    } 

    func startTimer() { 
     ... 
    } 
} 

そして、あなたのビューコントローラ

class ViewController: UIViewController, TimerDelegate 
{ 
    @IBOutlet weak var timeRemainingLabel: UILabel! 
    ... 
    @IBOutlet weak var pauseButton: UIButton! 

    var hourSelected = Int() 
    ... 
    var startPressed:Bool = false 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     newTimer.delegate = self 
    } 

    // Set button pressed 
    @IBAction func setPressed(sender: AnyObject) { 
     ... 
    } 

    // User closed set menu 
    @IBAction func setDonePressed(sender: AnyObject) { 
     ... 
    } 

    // Stepper functions 
    @IBAction func hourStepperPressed(sender: AnyObject) { 
     ... 

    } 
    @IBAction func minStepperPressed(sender: AnyObject) { 
     ... 
    } 
    @IBAction func secStepperPressed(sender: AnyObject) { 
     ... 
    } 

    //MARK: TimerDelegate 

    func updateUI() { 
     updateTimerLabel() 
    } 

    // User pressed start 
    @IBAction func startPressed(sender: AnyObject) { 
     self.newTimer.startTimer() 
     updateTimerLabel() 
     startPressed = true 
    } 

    func updateTimerLabel() { 
     timeRemainingLabel.text = newTimer.timeString 
    } 
} 
+0

これは魅力的でした!私は代議員を使わなければならないかもしれないと思っていたが、私はあまりにもそれほど精通していない。手伝ってくれてどうもありがとう。 私は今、代議員に関するいくつかの研究をしたいと思います。 – EtherCode

+1

パーフェクトな答えが既にupvoted、私はちょうどそれに少しの入力を追加したい:デリゲートから "updateUI"を呼び出すことは、それがUIコンポーネントから呼び出されていることをタイマーが知っていることを意味します。 ジェネリックタイマーを作成するには、そのような情報を与えないと便利です。そのため、 "didUpdate"のようなプロトコルメソッドを作成し、その実装で何をすべきかを決定する方がよいでしょう。このようにタイマーは1つの機能を持ち続けますが、汎用でUIコンポーネント、ロジックコンポーネントなどで使用できます。 Btw、2ヶ月後の良い改善:) –

+0

@Marco Paceあなたは正しいです、それは答えを良くしました! – Simon

関連する問題