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

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

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

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

Q&A

解決済

2回答

1050閲覧

【Swift】UItextの中身を都度更新したい

nekoni_matatabi

総合スコア6

Swift

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

0グッド

1クリップ

投稿2021/08/20 09:57

編集2021/08/20 10:27

【Swift】UItextの中身を都度更新したい

Swiftを個人で勉強しており詰まってしまったので質問させてください

下記のソースコードで3のつく数字と3の倍数だけ漢数字に変換するメソッド(countメソッド)を作成し、viewDidLoadメソッド内でUIlabelのtextに対しcountメソッドをfor文で呼び出し、都度画面に結果を表示させる処理を実装したいです

困っていること

最後に処理された結果である100は画面に表示されるがそれまでに値が画面に表示されない

やりたいこと

画面に都度結果を表示させたい
コンソールではやりたいことをできていることは確認済み

Swift

1import UIKit 2 3class ViewController: UIViewController { 4 @IBOutlet weak var label: UILabel! 5 6 override func viewDidLoad() { 7 super.viewDidLoad() 8 //ここの呼び出し方が不明 9 for number in 1...100 { 10 Thread.sleep(forTimeInterval: 0.5) 11 //print(count(number: number)) 12 label.text = count(number: number) 13 } 14 } 15 16 func count(number: Int) -> String { 17 let formatter = NumberFormatter() 18 formatter.numberStyle = .spellOut 19 formatter.locale = .init(identifier: "ja-JP") 20 21 if number % 3 == 0 || String(number).contains("3"){ 22 if let string = formatter.string(from: NSNumber(value: number)){ 23 return string 24 } 25 }else{ 26 return String(number) 27 } 28 29 return "" 30 } 31 32 33}

ご回答お待ちしておりますm(_ _)m

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

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

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

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

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

hoshi-takanori

2021/08/20 13:33

メインスレッドを sleep などで停止すると、その間 UI が更新されずユーザーからはフリーズしたように見えるので、時間がかかる処理はバックうラウンドスレッドで実行して UI の更新だけメインスレッドに処理を投げるなどする必要があります。
nekoni_matatabi

2021/08/20 13:42

ユーザー視点でのご指摘ありがとうございます! 質問とは異なるので箇所なので仮の対応として該当の処理は削除致します
hoshi-takanori

2021/08/20 13:47

ごめんなさい、書き方が悪かったようですが、UI が実際に更新されるのは OS にメインスレッドの処理を戻したときなので、viewDidLoad などから return しない限り UI は更新されないという意味です。
nekoni_matatabi

2021/08/20 14:21

Thread.sleepの指摘かと勘違いしてしまいました すみません >UI が実際に更新されるのは OS にメインスレッドの処理を戻したとき つまりviewDidLoad内でいくら値を更新しても処理が継続している時はUIは更新されないということですね returnの仕方を検討してみます
guest

回答2

0

横から失礼します。
的外れかもしれませんが、試しに回答させてください。

質問文を見る限り、こんな感じのものを作りたいのかなと推測しました。
作りたいもの

実装をみると
カウントダウンタイマーのように一定時間ごとに表示を更新しようと、
Thread.sleep() を使ったのかなと思いました。

しかし、hoshi-takanori さんの指摘にあるように、
メインスレッドでThread.sleep() をかけてしまっているので、
UI 更新するためにメインスレッドが使えず、
表示が更新されなかったのではと思いました。

なので、下記のようにすれば添付したgif のようになるかと思います。

  1. 別スレッドを立ち上げる
  2. 手順1のスレッドで、for 文を書く
  3. 手順2のfor 文の中で、Thread.sleep() をかける
  4. 手順3の後に、メインスレッドに切り替える処理を書き、その中でUILabel の更新をする

※回答を書いていたら、hoshi-takanori さんがコードを載せてくださったので、そちらを参考にすると良いかと思います

投稿2021/08/21 01:48

編集2021/08/21 01:56
tshion

総合スコア65

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

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

nekoni_matatabi

2021/08/21 07:42

おっしゃる通り一定時間ごとに更新処理をしたかったので`Thread.sleep()`を使用しました 手順も記載いただき参考になります!
guest

0

ベストアンサー

例えばバックグラウンドスレッドで処理するならこんな感じでしょうか。

swift

1 // バックグラウンドスレッドで処理 2 DispatchQueue.global(qos: .default).async { 3 for number in 1...100 { 4 Thread.sleep(forTimeInterval: 0.5) 5 6 // UI の更新はメインスレッドで行う 7 DispatchQueue.main.async { 8 self.label.text = self.count(number: number) 9 } 10 } 11 }

ただし、このままでは画面を閉じても処理が動き続けるので、それを防ぐには例えばこう。

swift

1 // [weak self] を使うと ViewController が解放されたら self が nil になる 2 DispatchQueue.global(qos: .default).async { [weak self] in 3 for number in 1...100 { 4 // ViewController が解放されたら処理を停止 5 if self == nil { 6 break 7 } 8 9 Thread.sleep(forTimeInterval: 0.5) 10 11 // [weak self] なクロージャの中で self を使う場合は guard 節を利用 12 DispatchQueue.main.async { [weak self] in 13 guard let self = self else { 14 return 15 } 16 17 self.label.text = self.count(number: number) 18 } 19 } 20 }

投稿2021/08/21 01:06

hoshi-takanori

総合スコア7895

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

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

nekoni_matatabi

2021/08/21 08:00

サンプルソースまで添付いただきありがとうございます! UI更新とスレッドの関係性を知らなかったので勉強になりました ベストアンサーさせていただきました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問