diff --git a/AssetsPickerViewController/Classes/Assets/AssetsManager+Sync.swift b/AssetsPickerViewController/Classes/Assets/AssetsManager+Sync.swift index c47552f..9c0aa73 100644 --- a/AssetsPickerViewController/Classes/Assets/AssetsManager+Sync.swift +++ b/AssetsPickerViewController/Classes/Assets/AssetsManager+Sync.swift @@ -99,7 +99,8 @@ extension AssetsManager: PHPhotoLibraryChangeObserver { let removedIndexes = removedIndexesSet.asArray().sorted(by: { $0.row < $1.row }) var removedAssets = [PHAsset]() for removedIndex in removedIndexes.reversed() { - removedAssets.insert(assetArray.remove(at: removedIndex.row), at: 0) +// removedAssets.insert(assetArray.remove(at: removedIndex.row), at: 0) + // TODO: replace assetArray to fetchResult } // stop caching for removed assets stopCache(assets: removedAssets, size: pickerConfig.assetCacheSize) @@ -112,7 +113,8 @@ extension AssetsManager: PHPhotoLibraryChangeObserver { for insertedIndex in insertedIndexes { let insertedAsset = assetsChangeDetails.fetchResultAfterChanges.object(at: insertedIndex.row) insertedAssets.append(insertedAsset) - assetArray.insert(insertedAsset, at: insertedIndex.row) +// assetArray.insert(insertedAsset, at: insertedIndex.row) + // TODO: replace assetArray to fetchResult } // start caching for inserted assets cache(assets: insertedAssets, size: pickerConfig.assetCacheSize) diff --git a/AssetsPickerViewController/Classes/Assets/AssetsManager.swift b/AssetsPickerViewController/Classes/Assets/AssetsManager.swift index e2f40ec..73a8356 100644 --- a/AssetsPickerViewController/Classes/Assets/AssetsManager.swift +++ b/AssetsPickerViewController/Classes/Assets/AssetsManager.swift @@ -37,7 +37,7 @@ open class AssetsManager: NSObject { } } - fileprivate let imageManager = PHCachingImageManager() + let imageManager = PHCachingImageManager() fileprivate var authorizationStatus = PHPhotoLibrary.authorizationStatus() var subscribers = [AssetsManagerDelegate]() @@ -50,14 +50,14 @@ open class AssetsManager: NSObject { var fetchedAlbumsArray = [[PHAssetCollection]]() /// stores sorted array by applying user defined comparator, it's in decreasing order by count by default, and it might same as fetchedAlbumsArray if AssetsPickerConfig has albumFetchOptions without albumComparator var sortedAlbumsArray = [[PHAssetCollection]]() - internal(set) open var assetArray = [PHAsset]() + internal(set) open var fetchResult: PHFetchResult? fileprivate(set) open var defaultAlbum: PHAssetCollection? fileprivate(set) open var cameraRollAlbum: PHAssetCollection! fileprivate(set) open var selectedAlbum: PHAssetCollection? fileprivate var isFetchedAlbums: Bool = false - fileprivate var resourceLoadingQueue: DispatchQueue = DispatchQueue(label: "com.assetspicker.loader", qos: .userInitiated) + fileprivate var resourceLoadingQueue: DispatchQueue = DispatchQueue(label: "com.assetspicker.loader", qos: .default) private override init() { super.init() @@ -82,7 +82,7 @@ open class AssetsManager: NSObject { sortedAlbumsArray.removeAll() // clear assets - assetArray.removeAll() + fetchResult = nil // clear fetch results albumsFetchArray.removeAll() @@ -236,8 +236,9 @@ extension AssetsManager { open func image(at index: Int, size: CGSize, isNeedDegraded: Bool = true, completion: @escaping ((UIImage?, Bool) -> Void)) -> PHImageRequestID { let options = PHImageRequestOptions() options.isNetworkAccessAllowed = true + guard let asset = fetchResult?.object(at: index) else { return PHInvalidImageRequestID } return imageManager.requestImage( - for: assetArray[index], + for: asset, targetSize: size, contentMode: .aspectFill, options: options, @@ -318,13 +319,14 @@ extension AssetsManager { return false } self.selectedAlbum = newAlbum - if let fetchResult = fetchMap[newAlbum.localIdentifier] { - let indexSet = IndexSet(0.. Void) { + open func selectAsync(album newAlbum: PHAssetCollection, completion: @escaping (Bool, PHFetchResult?) -> Void) { if let oldAlbumIdentifier = self.selectedAlbum?.localIdentifier, oldAlbumIdentifier == newAlbum.localIdentifier { logi("Selected same album.") - completion(false, []) + completion(false, nil) } self.selectedAlbum = newAlbum - if let fetchResult = fetchMap[newAlbum.localIdentifier] { - resourceLoadingQueue.async { [weak self] in - let indexSet = IndexSet(0.. Void)? = nil) { + open func fetchAssets(isRefetch: Bool = false, completion: ((PHFetchResult?) -> Void)? = nil) { fetchAlbums(isRefetch: isRefetch, completion: { [weak self] _ in guard let `self` = self else { return } if isRefetch { - self.assetArray.removeAll() + self.fetchResult = nil } // set default album - self.selectAsync(album: self.defaultAlbum ?? self.cameraRollAlbum) { result, photos in - completion?(photos) + self.selectAsync(album: self.defaultAlbum ?? self.cameraRollAlbum) { successful, result in + completion?(result) } }) @@ -538,7 +536,10 @@ extension AssetsManager { let albumFetchResult = PHAssetCollection.fetchAssetCollections(with: type, subtype: .any, options: fetchOption) var fetchedAlbums = [PHAssetCollection]() - albumFetchResult.enumerateObjects({ (album, _, _) in + let indexSet = IndexSet(integersIn: 0.. Int { - let count = AssetsManager.shared.assetArray.count + let count = AssetsManager.shared.fetchResult?.count ?? 0 updateEmptyView(count: count) return count } @@ -23,11 +23,14 @@ extension AssetsPhotoViewController: UICollectionViewDataSource { logw("Failed to cast UICollectionViewCell.") return cell } - let asset = AssetsManager.shared.assetArray[indexPath.row] - photoCell.asset = asset - photoCell.isVideo = asset.mediaType == .video - if photoCell.isVideo { - photoCell.duration = asset.duration + if let asset = AssetsManager.shared.fetchResult?.object(at: indexPath.row) { + photoCell.asset = asset + photoCell.isVideo = asset.mediaType == .video + if photoCell.isVideo { + photoCell.duration = asset.duration + } + } else { + photoCell.asset = nil } return cell } @@ -40,17 +43,20 @@ extension AssetsPhotoViewController: UICollectionViewDataSource { return } - let asset = AssetsManager.shared.assetArray[indexPath.row] - photoCell.asset = asset - photoCell.isVideo = asset.mediaType == .video - if photoCell.isVideo { - photoCell.duration = asset.duration - } - - if let selectedAsset = selectedMap[asset.localIdentifier] { - if let targetIndex = selectedArray.firstIndex(of: selectedAsset) { - photoCell.count = targetIndex + 1 + if let asset = AssetsManager.shared.fetchResult?.object(at: indexPath.row) { + photoCell.asset = asset + photoCell.isVideo = asset.mediaType == .video + if photoCell.isVideo { + photoCell.duration = asset.duration } + + if let selectedAsset = selectedMap[asset.localIdentifier] { + if let targetIndex = selectedArray.firstIndex(of: selectedAsset) { + photoCell.count = targetIndex + 1 + } + } + } else { + photoCell.asset = nil } fetchService.cancelFetching(at: indexPath) @@ -114,8 +120,10 @@ extension AssetsPhotoViewController: UICollectionViewDataSourcePrefetching { public func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) { var assets = [PHAsset]() for indexPath in indexPaths { - if AssetsManager.shared.assetArray.count > indexPath.row { - assets.append(AssetsManager.shared.assetArray[indexPath.row]) + let count = AssetsManager.shared.fetchResult?.count ?? 0 + if count > indexPath.row { + guard let asset = AssetsManager.shared.fetchResult?.object(at: indexPath.row) else { return } + assets.append(asset) } } AssetsManager.shared.cache(assets: assets, size: pickerConfig.assetCacheSize) diff --git a/AssetsPickerViewController/Classes/Photo/Controller/AssetsPhotoViewController+Delegate.swift b/AssetsPickerViewController/Classes/Photo/Controller/AssetsPhotoViewController+Delegate.swift index 6b1ddb9..a93c533 100644 --- a/AssetsPickerViewController/Classes/Photo/Controller/AssetsPhotoViewController+Delegate.swift +++ b/AssetsPickerViewController/Classes/Photo/Controller/AssetsPhotoViewController+Delegate.swift @@ -74,7 +74,8 @@ extension AssetsPhotoViewController: UIViewControllerPreviewingDelegate { guard let pressingCell = collectionView.cellForItem(at: pressingIndexPath) else { return nil } previewingContext.sourceRect = pressingCell.frame let previewController = AssetsPreviewController() - previewController.asset = AssetsManager.shared.assetArray[pressingIndexPath.row] + guard let fetchResult = AssetsManager.shared.fetchResult else { return nil } + previewController.asset = fetchResult.object(at: pressingIndexPath.row) return previewController } diff --git a/AssetsPickerViewController/Classes/Photo/Controller/AssetsPhotoViewController+Model.swift b/AssetsPickerViewController/Classes/Photo/Controller/AssetsPhotoViewController+Model.swift index 4376006..8ca1801 100644 --- a/AssetsPickerViewController/Classes/Photo/Controller/AssetsPhotoViewController+Model.swift +++ b/AssetsPickerViewController/Classes/Photo/Controller/AssetsPhotoViewController+Model.swift @@ -36,8 +36,10 @@ extension AssetsPhotoViewController { func isSelected(at indexPath: IndexPath) -> Bool { let manager = AssetsManager.shared - guard indexPath.row < manager.assetArray.count else { return false } - if let _ = selectedMap[manager.assetArray[indexPath.row].localIdentifier] { + guard let fetchResult = manager.fetchResult else { return false } + guard indexPath.row < fetchResult.count else { return false } + let asset = fetchResult.object(at: indexPath.row) + if let _ = selectedMap[asset.localIdentifier] { return true } else { return false @@ -47,8 +49,9 @@ extension AssetsPhotoViewController { func select(at indexPath: IndexPath) { defer { logSelectStatus(indexPath, isSelect: true) } let manager = AssetsManager.shared - guard indexPath.row < manager.assetArray.count else { return } - let asset = manager.assetArray[indexPath.row] + guard let fetchResult = manager.fetchResult else { return } + guard indexPath.row < fetchResult.count else { return } + let asset = fetchResult.object(at: indexPath.row) if let _ = selectedMap[asset.localIdentifier] {} else { selectedArray.append(asset) selectedMap[asset.localIdentifier] = asset @@ -61,8 +64,9 @@ extension AssetsPhotoViewController { func deselect(at indexPath: IndexPath) { defer { logSelectStatus(indexPath, isSelect: false) } let manager = AssetsManager.shared - guard indexPath.row < manager.assetArray.count else { return } - let asset = manager.assetArray[indexPath.row] + guard let fetchResult = manager.fetchResult else { return } + guard indexPath.row < fetchResult.count else { return } + let asset = fetchResult.object(at: indexPath.row) guard let targetAsset = selectedMap[asset.localIdentifier] else { logw("Invalid status.") return diff --git a/AssetsPickerViewController/Classes/Photo/Controller/AssetsPhotoViewController+Selection.swift b/AssetsPickerViewController/Classes/Photo/Controller/AssetsPhotoViewController+Selection.swift index f63f7a5..b1e2a4c 100644 --- a/AssetsPickerViewController/Classes/Photo/Controller/AssetsPhotoViewController+Selection.swift +++ b/AssetsPickerViewController/Classes/Photo/Controller/AssetsPhotoViewController+Selection.swift @@ -32,7 +32,8 @@ extension AssetsPhotoViewController: UICollectionViewDelegate { if LogConfig.isSelectLogEnabled { logi("shouldSelectItemAt: \(indexPath.row)") } if let delegate = self.delegate { - let shouldSelect = delegate.assetsPicker?(controller: picker, shouldSelect: AssetsManager.shared.assetArray[indexPath.row], at: indexPath) ?? true + guard let fetchResult = AssetsManager.shared.fetchResult else { return false } + let shouldSelect = delegate.assetsPicker?(controller: picker, shouldSelect: fetchResult.object(at: indexPath.row), at: indexPath) ?? true guard shouldSelect else { return false } } @@ -62,7 +63,8 @@ extension AssetsPhotoViewController: UICollectionViewDelegate { public func collectionView(_ collectionView: UICollectionView, shouldDeselectItemAt indexPath: IndexPath) -> Bool { if LogConfig.isSelectLogEnabled { logi("shouldDeselectItemAt: \(indexPath.row)") } if let delegate = self.delegate { - let shouldDeselect = delegate.assetsPicker?(controller: picker, shouldDeselect: AssetsManager.shared.assetArray[indexPath.row], at: indexPath) ?? true + guard let fetchResult = AssetsManager.shared.fetchResult else { return false } + let shouldDeselect = delegate.assetsPicker?(controller: picker, shouldDeselect: fetchResult.object(at: indexPath.row), at: indexPath) ?? true guard shouldDeselect else { return false } } deselect(at: indexPath) @@ -86,7 +88,8 @@ extension AssetsPhotoViewController { return } for selectedIndexPath in indexPathsForSelectedItems { - if let _ = selectedMap[AssetsManager.shared.assetArray[selectedIndexPath.row].localIdentifier] { + guard let fetchResult = AssetsManager.shared.fetchResult else { return } + if let _ = selectedMap[fetchResult.object(at: selectedIndexPath.row).localIdentifier] { } else { loge("selected item not found in local map!") diff --git a/AssetsPickerViewController/Classes/Photo/Controller/AssetsPhotoViewController+Setup.swift b/AssetsPickerViewController/Classes/Photo/Controller/AssetsPhotoViewController+Setup.swift index 611fe4d..3556d9a 100644 --- a/AssetsPickerViewController/Classes/Photo/Controller/AssetsPhotoViewController+Setup.swift +++ b/AssetsPickerViewController/Classes/Photo/Controller/AssetsPhotoViewController+Setup.swift @@ -73,12 +73,13 @@ extension AssetsPhotoViewController { let manager = AssetsManager.shared manager.subscribe(subscriber: self) manager.fetchAlbums { _ in - manager.fetchAssets() { [weak self] photos in + manager.fetchAssets() { [weak self] result in guard let `self` = self else { return } - self.updateEmptyView(count: photos.count) + guard let fetchResult = result else { return } + self.updateEmptyView(count: fetchResult.count) self.updateNavigationStatus() self.collectionView.reloadData() - self.preselectItemsIfNeeded(photos: photos) + self.preselectItemsIfNeeded(result: fetchResult) self.scrollToLastItemIfNeeded() // hide loading self.loadingPlaceholderView.isHidden = true diff --git a/AssetsPickerViewController/Classes/Photo/Controller/AssetsPhotoViewController+UI.swift b/AssetsPickerViewController/Classes/Photo/Controller/AssetsPhotoViewController+UI.swift index d7b8e95..dbc749a 100644 --- a/AssetsPickerViewController/Classes/Photo/Controller/AssetsPhotoViewController+UI.swift +++ b/AssetsPickerViewController/Classes/Photo/Controller/AssetsPhotoViewController+UI.swift @@ -57,7 +57,9 @@ extension AssetsPhotoViewController { } func deselectOldestIfNeeded(isForced: Bool = false) { - if selectedArray.count > pickerConfig.assetsMaximumSelectionCount, let firstSelectedAsset = selectedArray.first, let indexToDeselect = AssetsManager.shared.assetArray.firstIndex(of: firstSelectedAsset) { + guard let fetchResult = AssetsManager.shared.fetchResult else { return } + if selectedArray.count > pickerConfig.assetsMaximumSelectionCount, let firstSelectedAsset = selectedArray.first { + let indexToDeselect = fetchResult.index(of: firstSelectedAsset) let indexPathToDeselect = IndexPath(row: indexToDeselect, section: 0) deselect(at: indexPathToDeselect) deselectCell(at: indexPathToDeselect, isForced: isForced) @@ -67,12 +69,13 @@ extension AssetsPhotoViewController { func select(album: PHAssetCollection) { loadingPlaceholderView.isHidden = false loadingActivityIndicatorView.startAnimating() - AssetsManager.shared.selectAsync(album: album, completion: { [weak self] (result, photos) in + AssetsManager.shared.selectAsync(album: album, completion: { [weak self] (successful, result) in guard let `self` = self else { return } - guard result else { return } + guard successful else { return } + guard let fetchResult = result else { return } self.collectionView.reloadData() self.scrollToLastItemIfNeeded() - self.preselectItemsIfNeeded(photos: photos) + self.preselectItemsIfNeeded(result: fetchResult) self.updateNavigationStatus() self.loadingPlaceholderView.isHidden = true self.loadingActivityIndicatorView.stopAnimating() @@ -90,26 +93,25 @@ extension AssetsPhotoViewController { func scrollToLastItemIfNeeded() { - let assets = AssetsManager.shared.assetArray - guard !assets.isEmpty else { return } + guard let fetchResult = AssetsManager.shared.fetchResult else { return } + guard !(fetchResult.count == 0) else { return } if pickerConfig.assetsIsScrollToBottom == true { - self.collectionView.scrollToItem(at: IndexPath(row: assets.count - 1, section: 0), at: .bottom, animated: false) + self.collectionView.scrollToItem(at: IndexPath(row: fetchResult.count - 1, section: 0), at: .bottom, animated: false) } else { self.collectionView.scrollToItem(at: IndexPath(row: 0, section: 0), at: .bottom, animated: false) } } - func preselectItemsIfNeeded(photos: [PHAsset]) { + func preselectItemsIfNeeded(result: PHFetchResult) { if selectedArray.count > 0 { // initialize preselected assets selectedArray.forEach({ [weak self] (asset) in - if let row = photos.firstIndex(of: asset) { - let indexPathToSelect = IndexPath(row: row, section: 0) - let scrollPosition = UICollectionView.ScrollPosition(rawValue: 0) - self?.collectionView.selectItem(at: indexPathToSelect, - animated: false, - scrollPosition: scrollPosition) - } + let row = result.index(of: asset) + let indexPathToSelect = IndexPath(row: row, section: 0) + let scrollPosition = UICollectionView.ScrollPosition(rawValue: 0) + self?.collectionView.selectItem(at: indexPathToSelect, + animated: false, + scrollPosition: scrollPosition) }) updateSelectionCount() } @@ -117,13 +119,13 @@ extension AssetsPhotoViewController { func updateSelectionCount() { let visibleIndexPaths = collectionView.indexPathsForVisibleItems - let assets = AssetsManager.shared.assetArray + guard let fetchResult = AssetsManager.shared.fetchResult else { return } for visibleIndexPath in visibleIndexPaths { - guard assets.count > visibleIndexPath.row else { - loge("Referred wrong index\(visibleIndexPath.row) while asset count is \(assets.count).") + guard fetchResult.count > visibleIndexPath.row else { + loge("Referred wrong index\(visibleIndexPath.row) while asset count is \(fetchResult.count).") break } - if let selectedAsset = selectedMap[assets[visibleIndexPath.row].localIdentifier], var photoCell = collectionView.cellForItem(at: visibleIndexPath) as? AssetsPhotoCellProtocol { + if let selectedAsset = selectedMap[fetchResult.object(at: visibleIndexPath.row).localIdentifier], var photoCell = collectionView.cellForItem(at: visibleIndexPath) as? AssetsPhotoCellProtocol { if let selectedIndex = selectedArray.firstIndex(of: selectedAsset) { photoCell.count = selectedIndex + 1 } @@ -196,4 +198,100 @@ extension AssetsPhotoViewController { } return titleString } + + func updateCachedAssets() { + let isViewVisible = isViewLoaded && view.window != nil + + if !isViewVisible { + return + } + + let bounds = collectionView.bounds + + // The preheat window is twice the height of the visible rect + var preheatRect = bounds + preheatRect = preheatRect.insetBy(dx: 0.0, dy: -0.5 * preheatRect.height) + + // If scrolled by a "reasonable" amount... + let delta = abs(preheatRect.midY - previousPreheatRect.midY) + + if delta > (bounds.height / 3.0) { + var addedIndexPaths: [IndexPath] = [] + var removedIndexPaths: [IndexPath] = [] + + computeDifferenceBetweenRect(previousPreheatRect, newRect: preheatRect, add: { (rect) in + let indexPaths = getIndexPathsForElements(in: rect) + addedIndexPaths.append(contentsOf: indexPaths) + }) { (rect) in + let indexPaths = getIndexPathsForElements(in: rect) + removedIndexPaths.append(contentsOf: indexPaths) + } + + let assetsToStartCaching = getAssets(at: addedIndexPaths) + let assetsToStopCaching = getAssets(at: removedIndexPaths) + + let isPortrait = UIApplication.shared.statusBarOrientation.isPortrait + let itemSize = isPortrait ? pickerConfig.albumPortraitCellSize : pickerConfig.albumLandscapeCellSize + let scale = traitCollection.displayScale + let targetSize = CGSize(width: itemSize.width * scale, height: itemSize.height * scale) + AssetsManager.shared.imageManager.startCachingImages(for: assetsToStartCaching, targetSize: targetSize, contentMode: .aspectFill, options: nil) + AssetsManager.shared.imageManager.stopCachingImages(for: assetsToStopCaching, targetSize: targetSize, contentMode: .aspectFill, options: nil) + self.previousPreheatRect = preheatRect + } + } + + func getIndexPathsForElements(in rect: CGRect) -> [IndexPath] { + let allLayoutAttributes = collectionView.collectionViewLayout.layoutAttributesForElements(in: rect) + guard let attributes = allLayoutAttributes else { return [] } + guard attributes.count == 0 else { return [] } + var indexPaths: [IndexPath] = [] + for attribut in attributes { + indexPaths.append(attribut.indexPath) + } + return indexPaths + } + + func getAssets(at indexPaths: [IndexPath]) -> [PHAsset] { + if indexPaths.count == 0 { return [] } + guard let fetchResult = AssetsManager.shared.fetchResult else { return [] } + var asstes: [PHAsset] = [] + for indexPath in indexPaths { + if indexPath.item < fetchResult.count && indexPath.item != 0 { + let index = fetchResult.count - indexPath.item + let asset = fetchResult.object(at: index) + asstes.append(asset) + } + } + return asstes + } + + func computeDifferenceBetweenRect(_ oldRect: CGRect, newRect: CGRect, add: (CGRect) -> Void, remove: (CGRect) -> Void) { + if newRect.intersects(oldRect) { + let oldMaxY = oldRect.maxY + let oldMinY = oldRect.minY + let newMaxY = newRect.maxY + let newMinY = newRect.minY + + if newMaxY > oldMaxY { + let rect = CGRect(x: newRect.origin.x, y: oldMaxY, width: newRect.size.width, height: (newMaxY - oldMaxY)) + add(rect) + } + if oldMinY > newMinY { + let rect = CGRect(x: newRect.origin.x, y: newMinY, width: newRect.size.width, height: oldMinY - newMinY) + add(rect) + } + if newMaxY < oldMaxY { + let rect = CGRect(x: newRect.origin.x, y: newMaxY, width: newRect.size.width, height: oldMaxY - newMaxY) + remove(rect) + } + if oldMinY < newMinY { + let rect = CGRect(x: newRect.origin.x, y: oldMinY, width: newRect.size.width, height: newMinY - oldMinY) + remove(rect) + } + + } else { + add(newRect) + remove(oldRect) + } + } } diff --git a/AssetsPickerViewController/Classes/Photo/Controller/AssetsPhotoViewController.swift b/AssetsPickerViewController/Classes/Photo/Controller/AssetsPhotoViewController.swift index b2848e4..4be80b9 100644 --- a/AssetsPickerViewController/Classes/Photo/Controller/AssetsPhotoViewController.swift +++ b/AssetsPickerViewController/Classes/Photo/Controller/AssetsPhotoViewController.swift @@ -30,6 +30,8 @@ open class AssetsPhotoViewController: UIViewController { let fetchService = AssetsFetchService() + var previousPreheatRect: CGRect = .zero + lazy var cancelButtonItem: UIBarButtonItem = { let buttonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, @@ -180,7 +182,8 @@ open class AssetsPhotoViewController: UIViewController { super.viewDidLayoutSubviews() if !didSetInitialPosition { if pickerConfig.assetsIsScrollToBottom { - let count = AssetsManager.shared.assetArray.count + guard let fetchResult = AssetsManager.shared.fetchResult else { return } + let count = fetchResult.count if count > 0 { if self.collectionView.collectionViewLayout.collectionViewContentSize.height > 0 { let lastRow = self.collectionView.numberOfItems(inSection: 0) - 1 @@ -194,13 +197,13 @@ open class AssetsPhotoViewController: UIViewController { open func deselectAll() { var indexPaths = [IndexPath]() + guard let fetchResult = AssetsManager.shared.fetchResult else { return } for selectedAsset in selectedArray { - if let row = AssetsManager.shared.assetArray.firstIndex(of: selectedAsset) { - let indexPath = IndexPath(row: row, section: 0) - deselectCell(at: indexPath) - delegate?.assetsPicker?(controller: picker, didDeselect: selectedAsset, at: indexPath) - indexPaths.append(indexPath) - } + let row = fetchResult.index(of: selectedAsset) + let indexPath = IndexPath(row: row, section: 0) + deselectCell(at: indexPath) + delegate?.assetsPicker?(controller: picker, didDeselect: selectedAsset, at: indexPath) + indexPaths.append(indexPath) } updateSelectionCount() updateNavigationStatus() @@ -244,6 +247,7 @@ open class AssetsPhotoViewController: UIViewController { if traitCollection.forceTouchCapability == .available { previewing = registerForPreviewing(with: self, sourceView: collectionView) } + updateCachedAssets() } override open func viewDidDisappear(_ animated: Bool) { @@ -258,6 +262,10 @@ open class AssetsPhotoViewController: UIViewController { deinit { logd("Released \(type(of: self))") } + + public func scrollViewDidScroll(_ scrollView: UIScrollView) { + updateCachedAssets() + } } extension UICollectionView { diff --git a/AssetsPickerViewController/Classes/Photo/View/AssetsPhotoLayout.swift b/AssetsPickerViewController/Classes/Photo/View/AssetsPhotoLayout.swift index f6f63f8..3555513 100644 --- a/AssetsPickerViewController/Classes/Photo/View/AssetsPhotoLayout.swift +++ b/AssetsPickerViewController/Classes/Photo/View/AssetsPhotoLayout.swift @@ -39,8 +39,9 @@ open class AssetsPhotoLayout: UICollectionViewFlowLayout { extension AssetsPhotoLayout { open func expectedContentHeight(forViewSize size: CGSize, isPortrait: Bool) -> CGFloat { - var rows = AssetsManager.shared.assetArray.count / (isPortrait ? pickerConfig.assetPortraitColumnCount : pickerConfig.assetLandscapeColumnCount) - let remainder = AssetsManager.shared.assetArray.count % (isPortrait ? pickerConfig.assetPortraitColumnCount : pickerConfig.assetLandscapeColumnCount) + guard let fetchResult = AssetsManager.shared.fetchResult else { return 0.0 } + var rows = fetchResult.count / (isPortrait ? pickerConfig.assetPortraitColumnCount : pickerConfig.assetLandscapeColumnCount) + let remainder = fetchResult.count % (isPortrait ? pickerConfig.assetPortraitColumnCount : pickerConfig.assetLandscapeColumnCount) rows += remainder > 0 ? 1 : 0 let cellSize = isPortrait ? pickerConfig.assetPortraitCellSize(forViewSize: UIScreen.main.portraitContentSize) : pickerConfig.assetLandscapeCellSize(forViewSize: UIScreen.main.landscapeContentSize)