iOS WidgetKit: удаленные изображения не загружаются

Я наблюдаю странную вещь: в новых виджетах слишком часто удаленные изображения не отображаются, даже если изображение было успешно загружено и помещено в кеш.

Для загрузки изображений я пробовал:

  • SDWebImageSwiftUI
  • Зимородок
  • SwURL

Все они указывают на то, что загрузка изображения прошла успешно, но фактический виджет этого не показывает.

struct TestWidgetEntryView : View {
    var entry: Provider.Entry

    var body: some View {
        WebImage(url: URL(string: "https://i2.wp.com/miro.medium.com/max/3840/0*TLqp5Uwavd-U_xrs.jpg"))
                        .onSuccess()
                        .resizable()
    }
}

При втором запуске отладчика - с загрузкой изображения из кеша - изображение отображается, но никогда (?) При первом запуске.

Такое чувство, что в onSuccess мне нужно вызвать недействительность пользовательского интерфейса? Но как?

(Поскольку это случается буквально с каждой библиотекой изображений, которую я пробую - я не думаю, что в библиотеках что-то не так)

Окружающая среда:

  • iOS 14 Beta 3 (как устройство, так и симуляторы)
  • Xcode 12 бета 3
  • Во время отладки используется память около 15 МБ.

person Konstantin Loginov    schedule 25.07.2020    source источник
comment
Я могу отобразить изображение на виджете с помощью RemoteImage, но иногда оно не отображается из-за политики виджета. Может быть, здесь та же проблема   -  person Neo.Mxn0    schedule 23.11.2020


Ответы (2)


Да, как упоминал Константин, загрузка изображений асинхронно не поддерживается. Есть 2 варианта загрузки сетевого изображения в виджеты

  1. Либо выберите все изображения в TimelineProvider и напрямую вставьте их в представления.

    OR

  2. Используйте Data(contentsOf: url), чтобы получить изображение. Таким образом, он по-прежнему извлекает их синхронно, но код чище. Образец кода -

    struct NetworkImage: View {
    
      private let url: URL?
    
      var body: some View {
    
        Group {
         if let url = url, let imageData = try? Data(contentsOf: url), 
           let uiImage = UIImage(data: imageData) {
    
           Image(uiImage: uiImage)
             .resizable()
             .aspectRatio(contentMode: .fill)
          } 
          else {
           Image("placeholder-image")
          }
        }
      }
    
    }
    

Этот вид можно просто использовать так -

NetworkImage(url: url)
person prad    schedule 13.08.2020
comment
Вы хотели, чтобы свойство url было частным? В противном случае его нельзя будет установить в другом месте. - person vikzilla; 19.03.2021

Понятно: он просто не поддерживается, и вы стремитесь загружать изображения внутри TimelineProvider:

https://developer.apple.com/forums/thread/652581.

person Konstantin Loginov    schedule 25.07.2020
comment
Это мне очень помогает, я всю ночь боролся с этим, спасибо! - person Johnny; 21.11.2020
comment
Означает ли это, что я не могу использовать компонент SwiftUI (например: github.com/dmytro-anokhin/url-image) для рендеринга изображения? Должен ли я сначала предварительно загрузить двоичный файл изображения на локальный компьютер в TImelineProvider? - person Neo.Mxn0; 23.11.2020