1. ホーム
  2. swift

[解決済み] これを解決するにはどうしたらいいのでしょうか。UILabel.textは、メインスレッドからのみ使用する必要があります。

2022-02-12 02:29:32

質問

そこで、私のアプリケーションのUIを更新しようとしています。ラベルは更新されるのですが、その際に自分の値を保持せず、他のラベルの値を取得することがあります。 また、ラベルはメインスレッドからのみ使用されるべきであるというメッセージが表示されますが、これを解決するにはどうすればよいですか?

以下は私のコードです。

let queue = DispatchQueue(label: "update")
queue.async {
   for s in self.fietshare.stands {
      for b in s.bikes {
         lbAvailable.text = "Available Bikes: " + String(s.id) +  "  " + String( s.bikes.count) // shows too big numbers
         nrOfAvailable.text =  String(b.distance) + "M"
         annotationView.layoutIfNeeded()
         print(s.id)
         print("Nr of bikes")
         print(s.bikes.count)
      }
   }
}

DispatchQueue.main.async {
   self.view.backgroundColor = . black;
   self.view.layoutIfNeeded()
}

if (Thread.current.isMainThread) {
    print("Main thread")
}

解決方法は?

これを試してみてください

let queue = DispatchQueue(label: "update")

queue.async {

    var available = ""
    var nrOfAvailable = ""
    for s in self.fietshare.stands{
        for b in s.bikes {
            available = available + "Available Bikes: " + String(s.id) +  "  " + String( s.bikes.count) // shows too big numbers
            nrOfAvailable = String(b.distance) + "M"

            print(s.id)
            print("Nr of bikes")
            print(s.bikes.count)
        }
    }

    // UPDATE UI after all calculations have been done
    DispatchQueue.main.async {
        lbAvailable.text = available
        nrOfAvailable.text = nrOfAvailable
        annotationView.layoutIfNeeded()

        self.view.backgroundColor = . black;
        self.view.layoutIfNeeded()
    }
}

説明する。

  • で非同期タスクを開始した場合 queue.async
  • このバックグラウンドのジョブの内部で、forループを開始します。
  • このループは、いくつかのUIビットを更新する必要があります。
  • これはメインスレッドで行うので、この部分をメインスレッドに切り替える

説明2.

  • UIKitはスレッドセーフではありません。つまり、すべての変更はメインスレッドから来ることを想定しており、同期的(次々と)であることを意味します。そのため、ロック機構や保護機能はありません。もし、異なるスレッドから同時にラベルを変更しようとすると、 レースコンディションにより、ラベルの一部が異なる順序で変更されるなど、 奇妙なことが起こる可能性があります。