2016-08-30 1 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를 업데이트해야한다는 것을 뷰 컨트롤러에 알려주는 것입니다.

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"와 같은 프로토콜 메서드를 만들고 구현에서 수행 할 작업을 결정하는 것이 좋습니다. 이런 방식으로 타이머는 계속해서 하나의 기능을 갖지만 UI 컴포넌트, 로직 컴포넌트 등과 함께 사용할 수 있습니다. Btw, 2 개월 만 지나면 개선됨 :) –

+0

@Marco Pace 당신이 옳다면, 그 대답이 더 좋을 것입니다! – Simon

관련 문제