Как скачать изображения асинхронно для WidgetKit

Я разрабатываю виджеты для iOS и действительно не знаю, как загружать изображения для виджетов.

В настоящее время виджет загружает массив объектов, и каждый объект имеет URL-адрес изображения. Идея состоит в том, что каждый объект создаетSimpleEntry для Timeline.

Как лучше всего этого добиться? Я читал, что виджеты не должны использоватьObservableObject. Я получаю набор объектов в провайдере временной шкалы, что, похоже, рекомендует Apple. Но могу ли я также загрузить туда изображения и дождаться, пока все будет готово, чтобы отправить временную шкалу?

Любые советы были бы очень полезны,

0 ответов

Да, вы должны загрузить изображения в провайдере временной шкалы и отправить временную шкалу, когда все они будут готовы. См. Следующую рекомендацию инженера по инфраструктуре Apple.

Для этого я использую группу отправки. Что-то вроде:

let imageRequestGroup = DispatchGroup()
var images: [UIImage] = []
for imageUrl in imageUrls {
    imageRequestGroup.enter()
    yourAsyncUIImageProvider.getImage(fromUrl: imageUrl) { image in
        images.append(image)
        imageRequestGroup.leave()
    }
}
imageRequestGroup.notify(queue: .main) {
    completion(images)
}

Затем я использую инициализатор SwiftUI Image(uiImage:) для отображения изображений.

У меня нет хорошего решения, но я пытаюсь использовать WidgetCenter.shared.reloadAllTimelines(), и это имеет смысл. В следующем коде.

var downloadImage: UIImage?

func downloadImage(url: URL) -> UIImage {
    
    var picImage: UIImage!
    
    if self.downloadImage == nil {
        
        picImage = UIImage(named: "Default Image")
        
        DispatchQueue.global(qos: .background).async {
            do {
                let data = try Data(contentsOf: url)
                DispatchQueue.main.async {
                    self.downloadImage = UIImage.init(data: data)
                    if self.downloadImage != nil {
                        DispatchQueue.main.async {
                            WidgetCenter.shared.reloadAllTimelines()
                        }
                    }
                }
            } catch { }
        }
    } else {
        picImage = self.downloadImage
    }
    
    return picImage
}

Также вы должны подумать, когда удалить это изображение. Это похоже на tableView.reloadData().

Другие вопросы по тегам