WidgetKit Memory Issue - Photo Asset Dimensions

With iOS 14 WidgetKit, I am trying to display a widget with a 'particular' photo asset from the library. With a medium-size widget, I want the photo asset to fill the whole area (Aspect Fill), just like the native Photos widget.
Code Block
struct My_WidgetEntryView : View
{
var entry : Provider.Entry
var body: some View
{
PhotoView(user: 1)
}
}
struct PhotoView: View
{
var user : Int
@ObservedObject private var assetImageModel = AssetImageModel()
init(user: Int)
{
self.user = user
self.assetImageModel.loadAsset()
}
var body: some View {
if self.assetImageModel.assetImage != nil {
Image(uiImage: self.assetImageModel.assetImage!)
.resizable()
} else {
Image(uiImage: UIImage(systemName: "photo")!)
.resizable()
}
}
}
class AssetImageModel: ObservableObject {
@Published var assetImage: UIImage?
init() {
loadAsset()
}
func loadAsset() {
if PHPhotoLibrary.authorizationStatus() == .authorized {
let allPhotosOptions = PHFetchOptions()
allPhotosOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
let assetsFetchResults = PHAsset.fetchAssets(with: allPhotosOptions)
if assetsFetchResults.count > 0 {
let asset = assetsFetchResults.lastObject
if asset != nil {
let options = PHImageRequestOptions()
options.isSynchronous = true
options.deliveryMode = .highQualityFormat
options.resizeMode = .exact
options.version = .current
PHCachingImageManager().requestImage(for: asset!, targetSize: CGSize(width: 360 * UIScreen.main.scale, height: 170 * UIScreen.main.scale), contentMode: .aspectFill, options: options, resultHandler: { image, _ in
//DispatchQueue.main.async {
self.assetImage = image
//}
})
} else {
//Asset was nil
}
} else {
//No assets
}
} else {
//No persmission
}
}
}


When the above is run, I get a crash with a memory warning stating allowed 30 MB memory limit has exceeded. This obvious due to this:
  • For the medium-size widget, I had to go by a 360 x 170 point size since there was no way to get the actual view dimensions before the the view gets displayed.

  • The actual target size then has to be multiplied by the screen scale, at the moment the test device is a 3x. Aspect Fill as to be the fill type. Due to this, PHCachingImageManageris returning a 360-point width with 480-point height for a portrait photo in order to fill the view. The final dimensions of the image end up being 1080 x 1440 pixel size. I imagine this is the reason for memory pressure.


Question

Is there a way to ask for a properly cropped 360 x 170 point size image? The stock Photos widget seems to manage this.


Things I Tried

* I tried normalizedCropRect in PHImageRequestOptions and had no luck.
  • Lowering the image size by a huge margin works, but the image looks blurred visually.



Replies

For the medium-size widget, I had to go by a 360 x 170 point size since there was no way to get the actual view dimensions before the the view gets displayed.

Just to touch on this, there is a way to do this.
TimelineProviderContext has a displaySize property that lets you know "The size, in points, of the widget."