SwiftでライブラリKingfisherを利用してURLの画像を取得してリストとして表示しようとしているのですが
Kingfisherは非同期で取得するようでボタンを一回押すだけでは表示できないようです
DispatchSemaphoreを使えば待機していくれるということはわかったのですが
下記のコードを実行するとフリーズしていまいます
swift
1 let semaphore = DispatchSemaphore(value: 0) 2 var uiImage : [UIImage] = [] 3 4 for(_ ,value) in self.ImageUrlList 5 { 6 KingfisherManager.shared.retrieveImage(with: URL(string: value)!){ result in 7 switch result { 8 case .success(let value): 9 uiImage.append(value.image) 10 semaphore.signal() 11 case .failure(let error): 12 print(error) 13 } 14 } 15 16 semaphore.wait() 17 18 }
ImageUrlListはDictionary型で画像のURLが入っています
このコードのどこが問題なのでしょうか
Kingfisher の completionHandler はデフォルトではメインスレッドで処理されるので、semaphore.wait を先に呼ぶと semaphore.signal が呼ばれずにデッドロックするのでしょう。
https://kingfisher.onevcat.com/kingfishermanager/
非同期処理を待機するのは基本的に良くなくて、いったん制御を OS に戻して、結果が戻ってきた時に改めて処理を行うようにするのが良いと思います。
そもそもどのクラスの下でそのコードを書いているかわからないんですけど?
>hoshi-takanoriさん
そうなんですかそちらの方向で修正したいと思います
コードが書いてあるプロジェクトはある程度進んでおり待機中の操作を制御するフラグを追加するのが大変そうなので待機を追加できればなと思ってのものでよい方法があったら教えていただきたいです
>tomato879241さん
メインのViewControllerです
待機するということはその間メインスレッドを止めてアプリが固まったように見えるということなので、お勧めはできません。
ちなみに、uiImage の配列はどう使うのでしょうか?
配列に関してはcollectionViewで表示するのと
ファイルで保存するために取得しております。(保存→保存した画像を表示という感じです)
強制待機は良くないとわかったので処理後に表示する機能を追加したいと思います
ありがとうございます
保存に関しては、Kingfisher はもともとダウンロードした画像をキャッシュする機能を持ってると思いますが、それとは別に保存したいということでしょうか? また、表示に関しては、とりあえず仮の画像 (placeholder) を表示しておいて、目的の画像がダウンロードされたら自動的に表示するような機能も、たぶん Kingfisher が持ってるのでは…。
すいません
正直Kingfisherの機能についてはまだ把握してない部分が多くよくわかってません
placeholderなどを調べて見たいと思います
ありがとうございます
というか、Kingfisher の基本的な使い方って、
imageView.kf.setImage(with: imageUrl)
これだけですけど…。
https://github.com/onevcat/Kingfisher
あなたの回答
tips
プレビュー