6

SO にこの質問が既にあることは知っていますが、与えられた答えが満足のいくもの/完全なものであるとは思いません: How can IOS Photos app can show何百もの写真を 1 つの画面に表示できますか?

達成したいこと

whatsapp(iOS)での画像選択のようなものが必要です(スクリーンショットを参照)。カメラを開くと、ギャラリーのすべての画像を表示できる水平スライダーもあります。

whatsappのスクリーンショット

私が試したこと

現在、appDelegate に次のコードがあります。

let options = PHFetchOptions()

options.sortDescriptors = [
    NSSortDescriptor(key: "creationDate", ascending: true)
]
if let results = PHAsset.fetchAssetsWithMediaType(.Image, options: options) {

    results.enumerateObjectsUsingBlock { (object, idx, _) in
        if let asset = object as? PHAsset {
            Variables.assets.append(asset)
        }
    }

    println(Variables.assets.count)

    Variables.imageManager.startCachingImagesForAssets(Variables.assets, targetSize: CGSizeMake(viewWidth, viewWidth), contentMode: .AspectFill, options: self.requestOptions)
}

後で、UITableViewController に画像をロードし、スクロール時に次の関数を呼び出します。

func fetchPhotoAtIndex(index : Int) {

    let asset = Variables.assets[Variables.assets.count - 1 - index] as PHAsset

    Variables.imageManager.requestImageForAsset(asset, targetSize: CGSizeMake(self.viewWidth, self.viewWidth), contentMode: .AspectFill, options: self.requestOptions, resultHandler: { (image, _) in

        println("\(asset.localIdentifier) \(asset.creationDate) ")

        [...]

        self.tableView.reloadData()
    })

}

これはうまく機能しますが、アプリを起動するたびにすべてのアセットがキャッシュされるという問題があります。これは私の問題に対する正しいアプローチですか? whatsappのようにギャラリーの写真をリアルタイムで表示するにはどうすればよいですか?

4

1 に答える 1

4

この写真フレームワークの例を参照してください 。このプロジェクトでは、ファイル AAPLAssetGridViewController.m と、スクロール位置に基づいてキャッシュを処理する方法を調べる必要があります。

 - (void)updateCachedAssets
        {
            BOOL isViewVisible = [self isViewLoaded] && [[self view] window] != nil;
            if (!isViewVisible) { return; }
            
            // The preheat window is twice the height of the visible rect
            CGRect preheatRect = self.collectionView.bounds;
            preheatRect = CGRectInset(preheatRect, 0.0f, -0.5f * CGRectGetHeight(preheatRect));
            
            // If scrolled by a "reasonable" amount...
            CGFloat delta = ABS(CGRectGetMidY(preheatRect) - CGRectGetMidY(self.previousPreheatRect));
            if (delta > CGRectGetHeight(self.collectionView.bounds) / 3.0f) {
                
                // Compute the assets to start caching and to stop caching.
                NSMutableArray *addedIndexPaths = [NSMutableArray array];
                NSMutableArray *removedIndexPaths = [NSMutableArray array];
                
                [self computeDifferenceBetweenRect:self.previousPreheatRect andRect:preheatRect removedHandler:^(CGRect removedRect) {
                    NSArray *indexPaths = [self.collectionView aapl_indexPathsForElementsInRect:removedRect];
                    [removedIndexPaths addObjectsFromArray:indexPaths];
                } addedHandler:^(CGRect addedRect) {
                    NSArray *indexPaths = [self.collectionView aapl_indexPathsForElementsInRect:addedRect];
                    [addedIndexPaths addObjectsFromArray:indexPaths];
                }];
                
                NSArray *assetsToStartCaching = [self assetsAtIndexPaths:addedIndexPaths];
                NSArray *assetsToStopCaching = [self assetsAtIndexPaths:removedIndexPaths];
                
                [self.imageManager startCachingImagesForAssets:assetsToStartCaching
                                                    targetSize:AssetGridThumbnailSize
                                                   contentMode:PHImageContentModeAspectFill
                                                       options:nil];
                [self.imageManager stopCachingImagesForAssets:assetsToStopCaching
                                                   targetSize:AssetGridThumbnailSize
                                                  contentMode:PHImageContentModeAspectFill
                                                      options:nil];
        
                 self.previousPreheatRect = preheatRect;
            }
        }
        //In your case this computeDifference method changes to handle horizontal scrolling
            - (void)computeDifferenceBetweenRect:(CGRect)oldRect andRect:(CGRect)newRect removedHandler:(void (^)(CGRect removedRect))removedHandler addedHandler:(void (^)(CGRect addedRect))addedHandler
            {
                if (CGRectIntersectsRect(newRect, oldRect)) {
                    CGFloat oldMaxY = CGRectGetMaxY(oldRect);
                    CGFloat oldMinY = CGRectGetMinY(oldRect);
                    CGFloat newMaxY = CGRectGetMaxY(newRect);
                    CGFloat newMinY = CGRectGetMinY(newRect);
                    if (newMaxY > oldMaxY) {
                        CGRect rectToAdd = CGRectMake(newRect.origin.x, oldMaxY, newRect.size.width, (newMaxY - oldMaxY));
                        addedHandler(rectToAdd);
                    }
                    if (oldMinY > newMinY) {
                        CGRect rectToAdd = CGRectMake(newRect.origin.x, newMinY, newRect.size.width, (oldMinY - newMinY));
                        addedHandler(rectToAdd);
                    }
                    if (newMaxY < oldMaxY) {
                        CGRect rectToRemove = CGRectMake(newRect.origin.x, newMaxY, newRect.size.width, (oldMaxY - newMaxY));
                        removedHandler(rectToRemove);
                    }
                    if (oldMinY < newMinY) {
                        CGRect rectToRemove = CGRectMake(newRect.origin.x, oldMinY, newRect.size.width, (newMinY - oldMinY));
                        removedHandler(rectToRemove);
                    }
                } else {
                    addedHandler(newRect);
                    removedHandler(oldRect);
                }
            }
            
        

- (NSArray *)assetsAtIndexPaths:(NSArray *)indexPaths
    {
        if (indexPaths.count == 0) { return nil; }
        
        NSMutableArray *assets = [NSMutableArray arrayWithCapacity:indexPaths.count];
        for (NSIndexPath *indexPath in indexPaths) {
            PHAsset *asset = self.assetsFetchResults[indexPath.item];
            [assets addObject:asset];
        }
        return assets;
    }

イメージ キャッシュ マネージャーは、目的のサイズのアセットでヒートアップし、イメージ キャッシュ マネージャー自体からそれらを取得できます。

お役に立てば幸いです。

于 2015-07-04T08:50:01.193 に答える