Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to download images async for WidgetKit

I am developing Widgets for iOS and I really don't know how to download images for the widgets.

The widget currently downloads an array of Objects, and every object has a URL of an image. The idea is that every object makes a SimpleEntry for the Timeline.

What's the best way of achieving this? I read that Widgets shouldn't use the ObservableObject. I fetch the set of objects in the timeline provider, which seems to be what Apple recommends. But do I also download the images there and I wait until all are done to send the timeline?

Any advice would be very helpful,

like image 920
Joan Cardona Avatar asked Jul 30 '20 13:07

Joan Cardona


People also ask

How often do iPhone widgets refresh?

For a widget the user frequently views, a daily budget typically includes from 40 to 70 refreshes. This rate roughly translates to widget reloads every 15 to 60 minutes, but it's common for these intervals to vary due to the many factors involved. The system takes a few days to learn the user's behavior.

How do you refresh widgets on iOS 14?

Users can always manually force a refresh by tapping on the refresh button in the widget zoom view, or simply by double tapping on a widget in the main dashboard view.

How do you update widgets?

Full update: Call AppWidgetManager. updateAppWidget(int, android. widget. RemoteViews) to fully update the widget.

Why are my iPhone widgets not updating?

If Widgets not updating on iPhone after the iOS 16 update, then enable Background App Refresh. If this option is turned off, then the apps cannot check for new content and updates when they aren't actively in usage.


Video Answer


1 Answers

Yes, you should download the images in the timeline provider and send the timeline when they are all done. Refer to the following recommendation by an Apple frameworks engineer.

I use a dispatch group to achieve this. Something like:

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)
}

I then use SwiftUI's Image(uiImage:) initializer to display the images

like image 56
bee8ee Avatar answered Oct 10 '22 12:10

bee8ee