質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

iPhone

iPhoneとは、アップル社が開発・販売しているスマートフォンです。 同社のデジタルオーディオプレーヤーiPodの機能、電話機能、インターネットやメールなどのWeb通信機能の3つをドッキングした機器です。

Q&A

解決済

3回答

253閲覧

SwiftでTimerを2つ利用し,交互に動作させようとしているが正常に動作しない。

snowman2

総合スコア3

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

iPhone

iPhoneとは、アップル社が開発・販売しているスマートフォンです。 同社のデジタルオーディオプレーヤーiPodの機能、電話機能、インターネットやメールなどのWeb通信機能の3つをドッキングした機器です。

0グッド

0クリップ

投稿2024/01/19 08:38

実現したいこと

3つラベルを用意し,スタートボタンを押すとルーレットのようにラベル内の数字が高速かつランダムに変化しつつ,5秒後に当たりorハズレに合わせてラベル内の数字がストップ(当たりの場合は3つとも同じ数字を,ハズレの場合は数字が揃わないように)するプログラムを作成させたいと考えています。

発生している問題・分からないこと

Timer機能にて0.01秒ごとにラベル内の数字を変化させ,もう一つのTimerにて5秒後に当たりorハズレの抽選を行ってその結果に合わせてラベル内に数字を表示させるプログラムを記入しました。
5秒後に発火するTimerにて0.01秒毎に発火するTimerを終了させた際にはランダムに選ばれた数字がラベル内に表示されますが,抽選後の数字(当たりの場合は111,222など,ハズレの場合は384,242など)を表示させるタイミングでラベルの数字が更新されず,0.01秒毎に発火されるTimerで選ばれた数字が残ってしまうため,当たっている時に384,242などのハズレ数字が表示されたり,ハズレの時に111,222など当たり数字が表示されたりしてしまいます。
Printを用いてコンソールに表示させると正常にプログラム自体は動いているようですが,ラベルの表示のみ正常に動作していません。
どの部分を改善すればよろしいか,ご教授いただけますと幸いです。

該当のソースコード

Swift

1class ViewController: UIViewController { 2 3 @IBOutlet weak var hundred: UILabel! 4 @IBOutlet weak var ten: UILabel! 5 @IBOutlet weak var one: UILabel! 6 @IBOutlet weak var hundred2: UILabel! 7 @IBOutlet weak var ten2: UILabel! 8 @IBOutlet weak var one2: UILabel! 9 10 override func viewDidLoad() { 11 super.viewDidLoad() 12 // Do any additional setup after loading the view. 13 14 testCountNum.text = String(testCount) 15 kakuhenCountNum.text = String(kakuhenCount) 16 normalCountNum.text = String(normalCount) 17 hazureCountNum.text = String(hazureCount) 18 hundred.text = nil 19 ten.text = nil 20 one.text = nil 21 hundred2.isHidden = true 22 ten2.isHidden = true 23 one2.isHidden = true 24 25 } 26 27 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 28 view.endEditing(true) 29 } 30 31 @IBOutlet weak var testCountNum: UILabel! 32 @IBOutlet weak var kakuhenCountNum: UILabel! 33 @IBOutlet weak var normalCountNum: UILabel! 34 @IBOutlet weak var hazureCountNum: UILabel! 35 36 var testCount = 0 37 var kakuhenCount = 0 38 var normalCount = 0 39 var hazureCount = 0 40 let kakuhenArray = [10, 24, 36, 68, 103, 104, 210, 253, 286, 289, 296, 409, 637, 715, 747, 912, 1046, 1048, 1356, 1827, 2846, 3096, 3784, 5060, 5283, 5475, 5876, 6106, 7777, 9037, 11303, 11586, 11867, 12486, 14869, 18576, 18764, 18978, 19284, 19384, 20193, 22222, 22857, 23487, 23867, 25049, 25867, 26157, 27373, 28345, 30938, 31000] 41 let normalArray = [3, 16, 20, 64, 105, 158, 179, 236, 247, 295, 314, 376, 736, 799, 1175, 1657, 1659, 1688, 2186, 2367, 2646, 3263, 3948, 4857, 4938, 5338, 6456, 6873, 6874, 7041, 8456, 9285, 10374, 15364, 17366, 17684, 19867, 23136, 23183, 23456, 23576, 25676, 27756, 29173, 29465, 30124, 30476, 31900] 42 let kakuhenArray2 = [1, 3, 5, 7, 9] 43 let normalArray2 = [2, 4, 6, 8] 44 let kakuhenNumArray = [1, 3, 5, 7, 9] 45 let normalNumArray = [2, 4, 6, 8] 46 var hundredNum:Int = 0 47 var tenNum:Int = 0 48 var oneNum:Int = 0 49 50 51 @IBAction func startCount(_ sender: UIButton) { 52 53 testCountNum.text = String(testCount) 54 kakuhenCountNum.text = String(kakuhenCount) 55 normalCountNum.text = String(normalCount) 56 hazureCountNum.text = String(hazureCount) 57 58 let repeatingTimer2 = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true) { timer in 59 self.hundredNum = Int.random(in: 1...9) 60 self.tenNum = Int.random(in: 1...9) 61 self.oneNum = Int.random(in: 1...9) 62 self.hundred.text = String(self.hundredNum) 63 self.ten.text = String(self.tenNum) 64 self.one.text = String(self.oneNum) 65 } 66 67 let repeatingTimer = Timer.scheduledTimer(withTimeInterval: 5, repeats: true) { timer in 68 69 repeatingTimer2.invalidate() 70 print("StopTimer") 71 self.testCount += 1 72 print(self.testCount) 73 self.testCountNum.text = String(self.testCount) 74 let pickNum = Int.random(in: 1...20) 75 print(pickNum) 76 print(self.hundredNum) 77 print(self.tenNum) 78 print(self.oneNum) 79 if self.kakuhenArray2.contains(pickNum) == true { 80 let kakuhenNum:Int! = self.kakuhenNumArray.randomElement() 81 self.hundredNum = kakuhenNum 82 self.tenNum = kakuhenNum 83 self.oneNum = kakuhenNum 84 print(self.hundredNum) 85 print(self.tenNum) 86 print(self.oneNum) 87 self.hundred.isHidden = true 88 self.ten.isHidden = true 89 self.one.isHidden = true 90 self.hundred2.isHidden = false 91 self.ten2.isHidden = false 92 self.one2.isHidden = false 93 self.hundred2.text = String(self.hundredNum) 94 self.ten2.text = String(self.tenNum) 95 self.one2.text = String(self.oneNum) 96 self.kakuhenCount += 1 97 print("kakuhen") 98 self.kakuhenCountNum.text = String(self.kakuhenCount) 99 }else if self.normalArray2.contains(pickNum) == true { 100 let normalNum:Int! = self.normalNumArray.randomElement() 101 self.hundredNum = normalNum 102 self.tenNum = normalNum 103 self.oneNum = normalNum 104 print(self.hundredNum) 105 print(self.tenNum) 106 print(self.oneNum) 107 self.hundred.isHidden = true 108 self.ten.isHidden = true 109 self.one.isHidden = true 110 self.hundred2.isHidden = false 111 self.ten2.isHidden = false 112 self.one2.isHidden = false 113 self.hundred2.text = String(self.hundredNum) 114 self.ten2.text = String(self.tenNum) 115 self.one2.text = String(self.oneNum) 116 self.normalCount += 1 117 print("normal") 118 self.normalCountNum.text = String(self.normalCount) 119 }else { 120 self.hundredNum = Int.random(in: 1...9) 121 self.hundred.isHidden = true 122 self.hundred2.isHidden = false 123 self.hundred2.text = String(self.hundredNum) 124 self.tenNum = Int.random(in: 1...9) 125 self.ten.isHidden = true 126 self.ten2.isHidden = false 127 self.ten2.text = String(self.tenNum) 128 self.oneNum = Int.random(in: 1...9) 129 if self.hundredNum == self.tenNum { 130 while self.oneNum == self.tenNum { 131 self.oneNum = Int.random(in: 1...9) 132 } 133 } 134 print(self.hundredNum) 135 print(self.tenNum) 136 print(self.oneNum) 137 self.one.isHidden = true 138 self.one2.isHidden = false 139 self.one2.text = String(self.oneNum) 140 self.hazureCount += 1 141 print("hazure") 142 self.hazureCountNum.text = String(self.hazureCount) 143 } 144 145 146 sleep(3) 147 print("Wait a 3 seconds.") 148 149 self.hundred.isHidden = false 150 self.ten.isHidden = false 151 self.one.isHidden = false 152 self.hundred2.isHidden = true 153 self.ten2.isHidden = true 154 self.one2.isHidden = true 155 156 let repeatingTimer2 = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true) { timer in 157 let hundredNum = Int.random(in: 1...9) 158 let tenNum = Int.random(in: 1...9) 159 let oneNum = Int.random(in: 1...9) 160 self.hundred.text = String(hundredNum) 161 self.ten.text = String(tenNum) 162 self.one.text = String(oneNum) 163 } 164 print("StartTimer") 165 } 166 167 168 169 } 170 171} 172

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

ラベルを別物にして,0.01秒ごとに発火されるTimerで表示されるラベルと,5秒毎に発火されるTimerで表示されるラベルを非表示対応などで切り替わるようにしましたが,これでも上手くいきませんでした。

補足

特になし

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

(1) Timer.invalidate()は、タイマーを開始したスレッドから呼ばないといけないそうです。今は、5秒タイマーが発火したときに呼んでいるので、別のスレッドで呼んでいます。このため、0.01秒タイマーを正しく停止できていないと思われます。

(2) UIの操作は、メインスレッドから行う必要があります。UIの操作というのは、UILabelの操作など、画面に表示しているパーツに触る事です。これはそういう決まりです。

DispatchQueue.main.sync {} または、DispatchQueue.main.async {}というようにして、{}内のコードをメインスレッドで実行させる事ができます。syncは同期、asyncは非同期に{}内を実行します。

メインスレッドは単一のスレッドなので、0.01秒Timerの作成と停止、UILabelの操作をメインスレッドで行えば、どちらの問題も解決できますね。
ただ、メインスレッドは全部のUI操作が行われるスレッドなので、0.01秒毎に重い処理をしたりすると全体の動きが悪くなります。できるだけ処理を少なくする方がよいです。工夫してみて下さい。

投稿2024/01/24 13:56

eytyet

総合スコア803

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

snowman2

2024/01/27 12:11

ご回答ありがとうございます。 ご回答いただいたことを参考に,今一度プログラムを作り直してみたいと思います。 また何か不明な点が出てきたらこちらに投稿致しますので,その際はまたご教授いただけますと幸いです。
guest

0

ベストアンサー

Whileの中にTimerを入れたら正常に動作せず,どのようにすればいいか行き詰まっている状況です。 度々で申し訳ございませんが,ご教授いただけますと幸いです。

うーん・・
まず、下の引用を読んでもらいたいですね・・

teratailを「サポートセンター」だとは思わないでください。
作業依頼のような投稿をして、課題や仕事を無償でやってもらえる場ではありません。
あなたがそのようなつもりで質問しているのだと他のユーザーから誤解されないように、丁寧な質問を心がけましょう。

〜〜〜

何をどう検索すれば良いのかわからない場合は?
検索ワードが頭に浮かばないということは、人に説明するための言語化もできていない可能性があります。
これでは質問をしても他のユーザーが内容を理解できず、結果回答を得ることが出来なくなってしまいます。
もう一度状況を整理し、何がわからないのかを明確にしてみてください。
この作業を行うことで、何を質問すべきかも明確になります。

〜〜〜

2. 質問をする前に自分で何がわからないのかを把握しましょう
人に質問をするには、自分が何を尋ねたいかを知っている必要があります。
これは、「自分が今『何がわからないのか』がわかっていて、言語化できている」ということです。
一見簡単なようですが、実はとても難しいことです。
そしてこの工程が抜けていると、

  1. 「どのように人に尋ねればいいのか」、「どのような情報を提示すべきか」がわからない為、正しい質問ができない

  2. 質問が他のユーザーに正しく伝わらなかったり、聞き方が大雑把になりすぎたため他のユーザーから見た時に丸投げの質問・作業依頼だと受け取られてしまう

結果、思うような回答が得られなかったり、指摘をされてしまったり、逆に質問で返されてしまったりという悪い流れが生まれてしまいます。
何がわからないかわからない人から質問を受けても、答える側も困ってしまいます。
では、自分で何がわからないのかを知るためにはどうしたらいいのでしょうか?

〜〜〜

3. 正しく伝わる質問の仕方
人に何かを尋ねるときは、質問内容と回答に必要な情報を正しく伝える必要があります。「もし自分がおなじ質問をされて、答える立場になったら」ということを考えて質問をしましょう。
あなたの質問は
他の人が読んで理解ができますか?
何を教えてほしいと言っているのかちゃんと伝わりますか?
その質問に答えるために必要な情報は記載されていますか?
逆の立場に立って考えてみると、よりよい質問ができます。
例えば、「作りたいものがあり作り方を調べたいが、名称や検索ワードがわからない為調べることができない」のであれば、
作りたいものがどんなものかを人に理解してもらったうえで、調べ方を教えてもらう必要があります。
「作ってみたがうまく行かず、解決方法を調べたが理解できない」のであれば、
何をどのように作ってどうなったかを説明し、調べた解決方法とその内容及びどこが理解できないのかを順を追って伝える必要があります。

teratail【テラテイル】|ITエンジニア特化型Q&Aサイト

swift

1import UIKit 2 3class ViewController: UIViewController { 4 5 @IBOutlet weak var hundred: UILabel! 6 @IBOutlet weak var ten: UILabel! 7 @IBOutlet weak var one: UILabel! 8 @IBOutlet weak var hundred2: UILabel! 9 @IBOutlet weak var ten2: UILabel! 10 @IBOutlet weak var one2: UILabel! 11 12 override func viewDidLoad() { 13 super.viewDidLoad() 14 // Do any additional setup after loading the view. 15 16 testCountNum.text = String(testCount) 17 kakuhenCountNum.text = String(kakuhenCount) 18 normalCountNum.text = String(normalCount) 19 hazureCountNum.text = String(hazureCount) 20 hundred.text = nil 21 ten.text = nil 22 one.text = nil 23 hundred2.isHidden = true 24 ten2.isHidden = true 25 one2.isHidden = true 26 27 } 28 29 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 30 view.endEditing(true) 31 } 32 33 @IBOutlet weak var testCountNum: UILabel! 34 @IBOutlet weak var kakuhenCountNum: UILabel! 35 @IBOutlet weak var normalCountNum: UILabel! 36 @IBOutlet weak var hazureCountNum: UILabel! 37 38 var testCount = 0 39 var kakuhenCount = 0 40 var normalCount = 0 41 var hazureCount = 0 42 let kakuhenArray = [10, 24, 36, 68, 103, 104, 210, 253, 286, 289, 296, 409, 637, 715, 747, 912, 1046, 1048, 1356, 1827, 2846, 3096, 3784, 5060, 5283, 5475, 5876, 6106, 7777, 9037, 11303, 11586, 11867, 12486, 14869, 18576, 18764, 18978, 19284, 19384, 20193, 22222, 22857, 23487, 23867, 25049, 25867, 26157, 27373, 28345, 30938, 31000] 43 let normalArray = [3, 16, 20, 64, 105, 158, 179, 236, 247, 295, 314, 376, 736, 799, 1175, 1657, 1659, 1688, 2186, 2367, 2646, 3263, 3948, 4857, 4938, 5338, 6456, 6873, 6874, 7041, 8456, 9285, 10374, 15364, 17366, 17684, 19867, 23136, 23183, 23456, 23576, 25676, 27756, 29173, 29465, 30124, 30476, 31900] 44 let kakuhenArray2 = [1, 3, 5, 7, 9] 45 let normalArray2 = [2, 4, 6, 8] 46 let kakuhenNumArray = [1, 3, 5, 7, 9] 47 let normalNumArray = [2, 4, 6, 8] 48 var hundredNum:Int = 0 49 var tenNum:Int = 0 50 var oneNum:Int = 0 51 52 enum TmpStatus { 53 case one 54 case two(date: Date) 55 case three 56 case four(date: Date) 57 } 58 var tmpStatus: TmpStatus = .one 59 60 @IBAction func startCount(_ sender: UIButton) { 61 62 testCountNum.text = String(testCount) 63 kakuhenCountNum.text = String(kakuhenCount) 64 normalCountNum.text = String(normalCount) 65 hazureCountNum.text = String(hazureCount) 66 67 tmpStatus = .two(date: Date()) 68 _ = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true, block: { timer in 69 switch self.tmpStatus { 70 case .one: 71 self.tmpStatus = .two(date: timer.fireDate) 72 case .two(let date): 73 let timeInterval = timer.fireDate.timeIntervalSinceReferenceDate - date.timeIntervalSinceReferenceDate 74 if 5.0 < timeInterval { 75 self.tmpStatus = .three 76 break 77 } 78 self.block1() 79 break 80 case .three: 81 self.block2() 82 self.tmpStatus = .four(date: timer.fireDate) 83 break 84 case .four(let date): 85 let timeInterval = timer.fireDate.timeIntervalSinceReferenceDate - date.timeIntervalSinceReferenceDate 86 if 1.0 < timeInterval { 87 self.block3() 88 self.tmpStatus = .two(date: timer.fireDate) 89 break 90 } 91 break 92 } 93 }) 94 } 95 96 func block1() { 97 self.hundredNum = Int.random(in: 1...9) 98 self.tenNum = Int.random(in: 1...9) 99 self.oneNum = Int.random(in: 1...9) 100 self.hundred.text = String(self.hundredNum) 101 self.ten.text = String(self.tenNum) 102 self.one.text = String(self.oneNum) 103 } 104 105 func block2() { 106 self.testCount += 1 107 print(self.testCount) 108 self.testCountNum.text = String(self.testCount) 109 let pickNum = Int.random(in: 1...20) 110 print(pickNum) 111 print(self.hundredNum) 112 print(self.tenNum) 113 print(self.oneNum) 114 if self.kakuhenArray2.contains(pickNum) == true { 115 let kakuhenNum:Int! = self.kakuhenNumArray.randomElement() 116 self.hundredNum = kakuhenNum 117 self.tenNum = kakuhenNum 118 self.oneNum = kakuhenNum 119 print(self.hundredNum) 120 print(self.tenNum) 121 print(self.oneNum) 122 self.hundred.isHidden = true 123 self.ten.isHidden = true 124 self.one.isHidden = true 125 self.hundred2.isHidden = false 126 self.ten2.isHidden = false 127 self.one2.isHidden = false 128 self.hundred2.text = String(self.hundredNum) 129 self.ten2.text = String(self.tenNum) 130 self.one2.text = String(self.oneNum) 131 self.kakuhenCount += 1 132 print("kakuhen") 133 self.kakuhenCountNum.text = String(self.kakuhenCount) 134 }else if self.normalArray2.contains(pickNum) == true { 135 let normalNum:Int! = self.normalNumArray.randomElement() 136 self.hundredNum = normalNum 137 self.tenNum = normalNum 138 self.oneNum = normalNum 139 print(self.hundredNum) 140 print(self.tenNum) 141 print(self.oneNum) 142 self.hundred.isHidden = true 143 self.ten.isHidden = true 144 self.one.isHidden = true 145 self.hundred2.isHidden = false 146 self.ten2.isHidden = false 147 self.one2.isHidden = false 148 self.hundred2.text = String(self.hundredNum) 149 self.ten2.text = String(self.tenNum) 150 self.one2.text = String(self.oneNum) 151 self.normalCount += 1 152 print("normal") 153 self.normalCountNum.text = String(self.normalCount) 154 }else { 155 self.hundredNum = Int.random(in: 1...9) 156 self.hundred.isHidden = true 157 self.hundred2.isHidden = false 158 self.hundred2.text = String(self.hundredNum) 159 self.tenNum = Int.random(in: 1...9) 160 self.ten.isHidden = true 161 self.ten2.isHidden = false 162 self.ten2.text = String(self.tenNum) 163 self.oneNum = Int.random(in: 1...9) 164 if self.hundredNum == self.tenNum { 165 while self.oneNum == self.tenNum { 166 self.oneNum = Int.random(in: 1...9) 167 } 168 } 169 print(self.hundredNum) 170 print(self.tenNum) 171 print(self.oneNum) 172 self.one.isHidden = true 173 self.one2.isHidden = false 174 self.one2.text = String(self.oneNum) 175 self.hazureCount += 1 176 print("hazure") 177 self.hazureCountNum.text = String(self.hazureCount) 178 } 179 } 180 181 func block3() { 182 self.hundred.isHidden = false 183 self.ten.isHidden = false 184 self.one.isHidden = false 185 self.hundred2.isHidden = true 186 self.ten2.isHidden = true 187 self.one2.isHidden = true 188 } 189}

投稿2024/01/22 10:58

KEMONO_PANTSU_k

総合スコア499

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

snowman2

2024/01/27 12:14

ご回答ありがとうございます。 自分で試しましたが分からず,質問させていただきました。 プログラムも記載いただきまして誠にありがとうございます。
guest

0

swiftで繰り返し処理を行う際の画面更新について

前回の質問につきまして、自己解決にしておくと良いかなと思いました。

今回の質問も前回の質問と問題は同じだと思います。
前回の回答で問題をはっきり書かなかったですが、
sleepが原因だと思います。

ちょっと私も説明できるほど詳しくなく、
公式の正しい情報もうまく見つけられなかったので、
ネットの記事を少し引用してみますね。

sleep関数は、現在のスレッド全体を指定された秒数だけ停止させます。
Swiftのsleep関数を完全理解!初心者のための8選の使い方 | Japanシーモア

UIの更新はメインスレッドで行わなければならない
Swiftでメインスレッドの理解を深める12のステップ | Japanシーモア

ポイントは上に引用した2つかなと思います。

Timer.scheduledTimerを使ったとしても、
中に記述した処理でsleepするとそこで止まってしまいます。
sleepするとシステムに制御が戻らず、sleepの行で止まってしまいますので、該当のソースコードの69行目〜164行目に処理された結果の全てが画面には反映されないことになります。(ラベルの表示・再描画がされません)
なので、sleepで止まった時に、ラベルは一つ前の処理で設定した値が表示された状態になっていると思います。(2つタイマーがあるためややこしいかもしれません)

細かいところまで公式の正しい用語を使って説明するほど知識・技術がないため、
このあたりの仕組みについてご自身で学習してもらいたいかなと思います。

Swiftのsleep関数を完全理解!初心者のための8選の使い方 | Japanシーモア
Swiftでメインスレッドの理解を深める12のステップ | Japanシーモア
【Xcode/Swift】◯秒後に処理を行う遅延実行のやり方Dispatch、#selector、sleepの使い方 - iOS-Docs

*前回の回答で「考え方を変えないといけなそう」と書いたのは、このあたりも踏まえてのことでした。

追記です。

コメントありがとうございます。

156行目からのTimerではhundred, ten, oneラベルの値がきちんと変化しておりますが,
hundred, ten, oneのラベルの値のみ変化しないのはなぜでしょうか……?

これらの記載を見る限りですが、
処理の流れをちゃんと追えていないように感じました。
(タイマーが2つも動いているので、ちょっと追うのが難しいですよね・・)

質問欄の該当のソースコードの書き方もそうですが、
何が問題なのか、ご自身で正しく理解するために、
単純・シンプルな最小限のソースコードを新しく書いた方が良いと思いました。
下に引用するヘルプにある通りですね。

関連するソースコードを抽出して本文に含めましょう。 多すぎず、少なすぎずという分量の判断は難しいことですが、読むのに苦痛ではないくらいの量に抑える必要があり、でも問題の本質がわかるほどには多くなければいけません。最も良いのは、現象を再現するためのミニマムなプログラムを改めて作ることです。そうすれば、貴方自身が現象と問題をより良く理解することにもつながるからです。
teratail【テラテイル】|ITエンジニア特化型Q&Aサイト

前回の質問に対する回答も、ただカウントアップするだけのサンプルコードでしたが、
より単純・シンプル・小さいコードで「考え方」を見てもらいたかったからです。

今回、問題になっているsleepの動きを理解するためのコードを書いてみました。

swift

1class ViewController: UIViewController { 2 @IBOutlet weak var hundred: UILabel! 3 override func viewDidLoad() { 4 super.viewDidLoad() 5 // Do any additional setup after loading the view. 6 hundred.text = "a" 7 } 8 @IBAction func startCount(_ sender: UIButton) { 9 hundred.text = "b" 10 print("b") 11 sleep(3) 12 } 13}

snowman2さんのご理解だと、
ボタンをタップしてstartCountメソッドのsleepで止まったタイミングでは
hundred.textは"b"になっているはずですね。

でもそうはならないですね。
startCountメソッドの処理中(sleepしている間)は"a"のままです。

「システム側」「アプリ側(開発者側のソースコード)」という言葉は正しくないのかもしれませんが、
下の画像のようなイメージです。(イメージなので正しくないと思います・・雰囲気だけ見てください)

イメージ説明

ポイントは「アプリ側(開発者側のソースコード)」の制御から、
「システム側」の制御に戻してあげないといけないというところです。
(戻すというか、「アプリ側(開発者側のソースコード)」の処理を終了まで動かすというか)
startCountメソッドでsleepするということは、
制御が「システム側」に戻っていない状況で止まっているということです。
hundred.text = "b"という命令は「システム側」に画面(ラベル)を変更するように依頼を出すようなイメージですかね。(厳密には違うと思いますが・・)

タイマーに関するところまで書きますと、
タイマーの場合はTimer.scheduledTimer{ timer in ... }(block引数/クロージャ)の中に記述した処理が
スケジュールごとに「システム側」から呼び出されることになると思います。
このあたり2つタイマーを使うと理解が難しいと思いますが、
一つずつ単純・シンプル・小さなソースコード書きながら理解してみてください。

たくさんある問題をいっぺんに解決しようと思ったら
頭の中が整理つかなくて思うように進まないと思います。
ですので、問題は小さく分割して、一つずつ解決するようにしてみてください。
自己解決できることが増えていくと思います。

投稿2024/01/20 02:41

編集2024/01/21 01:16
KEMONO_PANTSU_k

総合スコア499

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

snowman2

2024/01/20 16:50

前回の質問に続き,ご回答くださりありがとうございます。 Sleepは146行目に記載しているのですが,これは次のTimer設定までの時間を空けたいため記入いたしました。 156行目からのTimerではhundred, ten, oneラベルの値がきちんと変化しておりますが,79〜143行目までのコードではこの3つのラベルの値が変化せずにTimer内でランダムに選ばれた数字を引き継いでしまっている状況です。他のラベル(testCount, kakuhenCount, normalCount, hazureCount)のラベルの値は正常に変化しています。 hundred, ten, oneのラベルの値のみ変化しないのはなぜでしょうか……? ご教授いただけますと幸いです。
snowman2

2024/01/21 16:17

ご回答ありがとうございます。 146行目以降を消去したところ,79〜143行目までのコードで設定した値にラベルの値が変化しました。 ですが,156行目以降のTimerも削除しなければならず,想定している挙動にはなりませんでした。 想定している挙動といたしましては,58〜65行目のTimerを基本的な動作とし,5秒に1回79〜143行目で設定された値をラベルに0.5〜1秒間表示,再度58〜65行目のTimerを作動させる,といった流れが繰り返される事です。 Whileの中にTimerを入れたら正常に動作せず,どのようにすればいいか行き詰まっている状況です。 度々で申し訳ございませんが,ご教授いただけますと幸いです。 どうぞよろしくお願いいたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問