DragonCherry / AssetsPickerViewController

Powerfully Customizable - Multiple Photo & Video Picker Controller
MIT License
385 stars 136 forks source link

Very slow opening of picker when media is over 8K #62

Open Ava8 opened 5 years ago

Ava8 commented 5 years ago

I have two devices, on each is over 8K media, so when I open assets picker, I wait for а minute or more for loading image gallery.

Ashu commented 4 years ago

I am having the same issue.

DragonCherry commented 4 years ago

@Ava8, @Ashu Can you please upload such images that causing the bug? I've tested with 10 images over 9MB but couldn't reproduce the problem.

Ava8 commented 4 years ago

@DragonCherry I'm talking not about the quality but a count of photos and videos in the media library. So, my library is over 8000 photos and videos.

DavidBoyes commented 4 years ago

I looked in to this briefly, I currently use a different library which opens instantly where as this takes a few seconds before opening. I think it's due to the asset manager doing too much upfront. it loads every album and does an asset fetch request for each one.

DragonCherry commented 4 years ago

@Ava8, @Ashu , @DavidBoyes I couldn't reproduce it with iPhone 6+, over 10,000 images. "fetchAlbums" finished in very short time. Anyone can provide a fix for them?

DavidBoyes commented 4 years ago

I use an iPhone XS Max. ~36,000 images, iCloud enabled. Definitely noticeably slower than other libraries I have used to initially open. I'm looking in to it now. fetchAlbums takes around 0.9 seconds to complete and selectAlbum around 1.4 seconds.

Overall it can take 2.5-3.5 seconds to complete viewDidLoad in AssetsPhotoViewController.

Update: func select(album newAlbum: PHAssetCollection) -> Bool Copying each asset of the fetchResult in to the array is the cause of slowness for this function I believe.

Update 2: creating the fetchMap is the next slow piece.

I removed it from the code, as well as the assetArray. This took the viewDidLoad method down to 0.12 seconds to complete. The assetArray was replaced by just using the fetchRequest directly. However syncing changes had to be commented out for this to work. I have moved the creation of fetchMap to be more on demand in fetchResult(forAlbum album: PHAssetCollection). I've had to move the creation of sortedAlbumsArray to a background thread as well. My version is currently quite different to the original due to requirements for my app so I hope these descriptions help out somehow.

Ashu commented 4 years ago

This issue occurred to me on a iPhone X. Currently, I don't have that device, so can't share much info about it. It works perfectly fine on my iPhone 5s with 5000 images. Also works in iPhone 6. I guess this issue occurs only on newer phones. Need to check again in new devices. Will let you know soon.

DavidBoyes commented 4 years ago

@Ashu Is that comparing with the same image set on all devices?

Ashu commented 4 years ago

@Ashu Is that comparing with the same image set on all devices?

No. The image set was different. iPhone X was used by professional photographer, so it might have some RAW images. I need to check that.

DavidBoyes commented 4 years ago

@Ashu Is that comparing with the same image set on all devices?

No. The image set was different. iPhone X was used by professional photographer, so it might have some RAW images. I need to check that.

Ok, I tried on an iPhone 6S with ~5000 images, and it was faster but I would guess relative to the amount of images/albums rather than a device specific thing.

rad182 commented 4 years ago

have the same issue iPhone XS having 4k++ photos. opening picker takes ~3secs. any workaround for this?

DavidBoyes commented 4 years ago

A work around that removes some of the delay (not all) is to move fetchAlbums to a background thread. You'll have to manually specify the defaultAlbum in fetchAssets() so it loads the initial set of photos.

zongziyao commented 4 years ago

I have the same issue. 3000+ pics on my iPhone 6s and it took about 2s to open. I then wiped my iPhone and it'll open almost instantly.

avi-screenovate commented 4 years ago

@DragonCherry

To get around the performance issue with loading (I have a customer with a high bar), I created a hack in my app. I load the picker's view and then stash it as a hidden view in the main view of my app. This causes it to load while the user doesn't notice. Then, I add the view controller as a child view controller and move the view back. This works surprisingly well.

My issue is that there is no way to programmatically deselect assets that are not selected in the current album. Would it be possible to make setSelectedAssets(assets: [PHAsset]) public, or to add a clearAssets() method to AssetsPhotoViewController?

DragonCherry commented 4 years ago

@avi-screenovate I'm sorry for this bug that make you use tricky mechanism. How about calling AssetsPhotoViewController.deselectAll()?

avi-screenovate commented 4 years ago

deselectAll() only deselects from the current Album. It doesn't help for cross-album selections. In my app, I now recreate the ViewController after dismissal, to hide the load time. It's working well-enough now, and is a bit less hacky.

eytanschulman commented 4 years ago

Having this issue as well, takes a good 7 seconds for AssetsPickerViewController to load, which is quite long on my XS.

gezihuzi commented 4 years ago

@Ava8 @DavidBoyes @Ashu @rad182 @zongziyao @eytanschulman @DragonCherry

Hi guys, I have optimized accordingly for this issue, for more details please see :

pull request #86 pull request #85 pull request #84 develop

Please provide me with new test data and feedback to help me better refine the optimization section.

DragonCherry commented 4 years ago

Please consider replacing this library with PHPickerViewController.

eytanschulman commented 4 years ago

Please consider replacing this library with PHPickerViewController.

While native solutions are always better, PHPickerViewController is iOS 14+, many apps will need to support iOS 13 for the time being. That's why third party solutions like this one are great.