swiftでiPhone標準の時計アプリを作ろう 完成コード ストップウォッチ

2019年9月9日月曜日 更新:2019年09月17日

swift ストップウォッチ 時計

t f B! P L

Xcode 10.3
swift 5
ios 12.4

完成品

UI

UIは前回のタイマーのようにtableviewの上にcellを並べてもよかったのですが標準のアプリを見る限り使ってなさそうだったので一つのviewに配置することにしました。

コード

StopWatchVC

  1. import UIKit
  2.  
  3. class StopWatchVC: UIViewController , UITableViewDelegate,UITableViewDataSource {
  4. @IBOutlet weak var tableView: UITableView!
  5. @IBOutlet weak var startStopButton: UIButton!
  6. @IBOutlet weak var lapResetButton: UIButton!
  7. @IBOutlet weak var timerLabel: UILabel!
  8. var seconds:Double = 0
  9. var lap:Double = 0
  10. var timer = Timer()
  11. var lapTimers: [Double] = []
  12.  
  13. override func viewDidLoad() {
  14. super.viewDidLoad()
  15. //cellを登録
  16. tableView.register(UINib(nibName: "StopWatchTimeCell", bundle: nil), forCellReuseIdentifier: "StopWatchTimeCell")
  17. //UILabelを自動でリサイズする
  18. timerLabel.adjustsFontSizeToFitWidth = true
  19.   //ボタンを押せなくする
  20. lapResetButton.isEnabled = false
  21. }
  22. @IBAction func startStop(_ sender: Any) {
  23. //表示されているセルの配列を取得
  24. let cell = tableView.visibleCells as! [StopWatchTimeCell]
  25. //時間が動いているかどうか
  26. if timer.isValid {
  27. timer.invalidate()
  28. startButton()
  29. lapResetButton.setTitle("Reset", for: .normal)
  30.           一番上のセルのタイマーを停止する
  31. cell[0].timerStop()
  32. }else{
  33. timer = Timer.scheduledTimer(
  34. timeInterval: 0.01, // 時間間隔
  35. target: self, // タイマーの実際の処理の場所
  36. selector: #selector(StopWatchVC.tickTimer(_:)), // メソッド タイマーの実際の処理
  37. userInfo: nil,
  38. repeats: true)
  39.         //スクロール中でもタイマーが動くようにする
  40. RunLoop.main.add(timer, forMode: RunLoop.Mode.common)
  41.           //非表示解除
  42. cell[0].labelisHidden = false
  43.           //一番上のcellのタイマースタート
  44. cell[0].timerStart()
  45. stopButton()
  46. lapResetButton.setTitle("Lap", for: .normal)
  47. }
  48. //ボタンを押せるようにする
  49. lapResetButton.isEnabled = true
  50. }
  51. @IBAction func lapReset(_ sender: Any) {
  52. let cell = tableView.visibleCells as! [StopWatchTimeCell]
  53. if timer.isValid
  54.         //lapしたタイマーを配列に追加する
  55. lapTimers.append(seconds - lap)
  56.     //ラップした時の時間を取得する
  57. lap = seconds
  58.      //セルのタイマーを0にする
  59. cell[0].seconds = 0
  60. }else{
  61. seconds = 0
  62. startButton()
  63. timerLabel.text = timeString(time: seconds)
  64. lapTimers.removeAll()
  65. lapResetButton.setTitle("Lap", for: .normal)
  66. lapResetButton.isEnabled = false
  67. cell[0].seconds = 0
  68. cell[0].labelisHidden = true
  69. }
  70. tableView.reloadData()
  71. }
  72. func startButton(){
  73. startStopButton.setTitle("Start", for: .normal)
  74. startStopButton.setTitleColor(#colorLiteral(red: 0.7055676579, green: 1, blue: 0.6596676707, alpha: 1), for: .normal)
  75. startStopButton.backgroundColor = #colorLiteral(red: 0.1799043417, green: 0.6762347817, blue: 0.2553646266, alpha: 1)
  76. }
  77. func stopButton(){
  78. startStopButton.setTitle("Stop", for: .normal)
  79. startStopButton.setTitleColor(#colorLiteral(red: 0.8078431487, green: 0.02745098062, blue: 0.3333333433, alpha: 1), for: .normal)
  80. startStopButton.backgroundColor = #colorLiteral(red: 0.3098039329, green: 0.01568627544, blue: 0.1294117719, alpha: 1)
  81. }
  82. @objc func tickTimer(_ timer: Timer) {
  83. seconds += 1
  84. timerLabel.text = timeString(time: seconds)
  85. }
  86. func timeString(time:TimeInterval) -> String {
  87. let hours = Int(time) / 100 / 3600 //時
  88. let minutes = Int(time) / 100 / 60 % 60     //分
  89. let seconds = Int(time) / 100 % 60            //秒
  90. let milliseconds = Int(time) % 100              //ミリ秒
  91. //時が0の時に時までの時間を表示
  92. return hours == 0 ? String(format:"%02d:%02d:%02d", minutes, seconds,milliseconds) : String(format:"%02d:%02d:%02d:%02d",hours, minutes, seconds,milliseconds)
  93. }
  94. func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  95. return lapTimers.count + 1
  96. }
  97. func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  98. let cell = tableView.dequeueReusableCell(withIdentifier: "StopWatchTimeCell") as! StopWatchTimeCell
  99. cell.lapLabel.text = String(format: "Lap %d", lapTimers.count - indexPath.row + 1)
  100. if indexPath.row > 0 {
  101.            //配列の最大値を取得
  102. let max = lapTimers.max()
  103.       //配列の最小値を取得
  104. let min = lapTimers.min()
  105. cell.timerLabel.text = timeString(time: lapTimers[lapTimers.count - indexPath.row ])
  106. if lapTimers[lapTimers.count - indexPath.row ] == max {
  107. cell.timerLabel.textColor = .green
  108. cell.lapLabel.textColor = .green
  109. }else if lapTimers[lapTimers.count - indexPath.row ] == min {
  110. cell.timerLabel.textColor = .red
  111. cell.lapLabel.textColor = .red
  112. }else {
  113. cell.timerLabel.textColor = .black
  114. cell.lapLabel.textColor = .black
  115. }
  116. cell.labelisHidden = false
  117.  
  118. }
  119. return cell
  120. }
  121. }


StopWatchTimerCell

  1. import UIKit
  2.  
  3. class StopWatchTimeCell: UITableViewCell {
  4.  
  5. @IBOutlet weak var timerLabel: UILabel!
  6. @IBOutlet weak var lapLabel: UILabel!
  7. var timer:Timer = Timer()
  8. var seconds:Double = 0
  9. var labelisHidden:Bool = true {
  10. didSet{
  11. timerLabel.isHidden = labelisHidden
  12. lapLabel.isHidden = labelisHidden
  13. }
  14. }
  15.  
  16. override func awakeFromNib() {
  17. super.awakeFromNib()
  18. timerLabel.isHidden = true
  19. lapLabel.isHidden = true
  20. }
  21. func timerStart(){
  22. timer = Timer.scheduledTimer(
  23.  
  24. timeInterval: 0.01, // 時間間隔
  25.  
  26. target: self, // タイマーの実際の処理の場所
  27.  
  28. selector: #selector(StopWatchVC.tickTimer(_:)), // メソッド タイマーの実際の処理
  29.  
  30. userInfo: nil,
  31.  
  32. repeats: true
  33. RunLoop.main.add(timer, forMode: RunLoop.Mode.common)
  34. }
  35. func timerStop(){
  36. timer.invalidate()
  37. }
  38.  
  39. @objc func tickTimer(_ timer: Timer) {
  40. seconds += 1
  41. timerLabel.text = timeString(time: seconds)
  42. }
  43. func timeString(time:TimeInterval) -> String {
  44. let hours = Int(time) / 100 / 3600
  45. let minutes = Int(time) / 100 / 60 % 60
  46. let seconds = Int(time) / 100 % 60
  47. let milliseconds = Int(time) % 100
  48. return hours == 0 ? String(format:"%02d:%02d:%02d", minutes, seconds,milliseconds) : String(format:"%02d:%02d:%02d:%02d",hours, minutes, seconds,milliseconds)
  49. }
  50. }
githubはこちら

QooQ