2

これが問題です:私はスクロールビューを持っています、それはユーザーの写真のフルスクリーン画像の遅延ロードをしました:

[self.assetsLibrary assetForURL:[NSURL URLWithString:[[self.assets objectAtIndex:index] objectForKey:@"asset_url"]]
    resultBlock:^(ALAsset *asset) {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            CGImageRef cgImage = asset.defaultRepresentation.fullScreenImage;
            UIImage *image = [UIImage imageWithCGImage:cgImage];
            dispatch_async(dispatch_get_main_queue(), ^{
                imageView.image = image;
            });
        });
                    }
failureBlock:^(NSError *error) {
    NSLog(@"error");
}];

フルスクリーンの画像をロードするのはコストがかかることを知っているので、バックグラウンド スレッドに入れましたが、スクロールを行うとまだラグが発生します。そして、次のように変更してもまだ遅れます:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                            CGImageRef cgImage = asset.defaultRepresentation.fullScreenImage;
                            UIImage *image = [UIImage imageWithCGImage:cgImage];
                            imageView.image = image;
                            dispatch_async(dispatch_get_main_queue(), ^{
                            });
                        });

明らかに、メイン キューでは何もする必要はありませんが、次の行にコメントするまで遅れます。

// CGImageRef cgImage = asset.defaultRepresentation.fullScreenImage;

だから私はとても混乱しています.GCDを使用したときに何か問題がありますか? 誰かが私がそれを説明するのを手伝ってくれますか? どんなことでも役に立ちます。

君たちありがとう。

アップデート

@Fogmeister 様へ : 写真のサイズは全画面サイズ、実際の imageView サイズは半分程度です。「imageView.image = image;」という行にコメントを付けても。まだラグです。つまり、サイズ変更によるものではありません。ここでは、「asset.defaultRepresentation.fullScreenImage;」に時間がかかっていることを知っています。コメントすると、すべて問題なく、ラグはなくなりました。 だから、私が理解していないのは、すでにバックグラウンドスレッドに入れているということです...

4

4 に答える 4

5

わかりました、ついに私は問題を解決しました:

直接画像を取得する代わりに

asset.defaultRepresentation.fullScreenImage

Apple のExemple PhotosByLocation (以下のコード) のメソッドを使用して、BG スレッドで画像を取得します。それはうまく機能し、スクロール時のラグはもうありません。しかし、私はまだ混乱しています。正確な理由はわかりません。だから、誰かが私にそれを説明できるなら、私は感謝します。

- (UIImage *)fullSizeImageForAssetRepresentation:(ALAssetRepresentation *)assetRepresentation {

UIImage *result = nil;
NSData *data = nil;

uint8_t *buffer = (uint8_t *)malloc(sizeof(uint8_t)*[assetRepresentation size]);
if (buffer != NULL) {
    NSError *error = nil;
    NSUInteger bytesRead = [assetRepresentation getBytes:buffer fromOffset:0 length:[assetRepresentation size] error:&error];
    data = [NSData dataWithBytes:buffer length:bytesRead];

    free(buffer);
}

if ([data length]) {
    CGImageSourceRef sourceRef = CGImageSourceCreateWithData((__bridge CFDataRef)data, nil);

    NSMutableDictionary *options = [NSMutableDictionary dictionary];

    [options setObject:(id)kCFBooleanTrue forKey:(id)kCGImageSourceShouldAllowFloat];
    [options setObject:(id)kCFBooleanTrue forKey:(id)kCGImageSourceCreateThumbnailFromImageAlways];
    [options setObject:(id)[NSNumber numberWithFloat:640.0f] forKey:(id)kCGImageSourceThumbnailMaxPixelSize];
    //[options setObject:(id)kCFBooleanTrue forKey:(id)kCGImageSourceCreateThumbnailWithTransform];

    CGImageRef imageRef = CGImageSourceCreateThumbnailAtIndex(sourceRef, 0, (__bridge CFDictionaryRef)options);

    if (imageRef) {
        result = [UIImage imageWithCGImage:imageRef scale:[assetRepresentation scale] orientation:(UIImageOrientation)[assetRepresentation orientation]];
        CGImageRelease(imageRef);
    }

    if (sourceRef) CFRelease(sourceRef);
}

return result;
}
于 2012-12-19T15:48:41.623 に答える
1

あなたはAppleのPhotosByLocationから取られた解決策であり、実際にはフルスクリーン画像ではなく最大解像度の画像を取得しています。IOW、これは基本的に、fullScreenImageの代わりにfullResolutionImageを呼び出すのと同じです。それがあなたの問題をどのように解決するか、私にはわかりません。同じパフォーマンスの問題に苦しんでいます。fullScreenImageを使用すると、スクロールに遅れが生じます。ただし、fullResolutionImageに切り替えると、ラグがなくなります。fullResolutionImageはfullScreenImageの約2倍の時間がかかりますが、これは常にバックグラウンドであるため、どれだけの時間がかかるかは実際には問題ではありません。fullScreenImageは、メインスレッドの画面にレンダリングされた後、何らかの追加処理が必要な画像を返していると思われます。したがって、遅延が発生します。

于 2013-01-08T06:11:08.203 に答える
0

写真の実寸はわかりますか?非常にコストがかかるのは、画面に合わせてサイズ変更されている画像をスクロールすることです。

すでに BG スレッドに読み込んでいるので、画面に貼り付ける前に、表示しているサイズに画像のサイズを変更する価値があるかもしれません。

Xcode からアプリをプロファイリングすることで、Instruments の CoreAnimation ツールを使用して、どこで時間がかかっているかを確認できます。また、どのコード行が速度低下やアニメーション フレームの欠落の原因になっているかも教えてくれます。

于 2012-12-18T21:52:13.840 に答える
0

アップルのドキュメントから:

DISPATCH_QUEUE_PRIORITY_DEFAULT
Items dispatched to the queue run at the default priority; the queue is scheduled for execution after all high priority queues have been scheduled, but before any low priority queues have been scheduled.

DISPATCH_QUEUE_PRIORITY_BACKGROUND
Items dispatched to the queue run at background priority; the queue is scheduled for execution after all high priority queues have been scheduled and the system runs items on a thread whose priority is set for background status. Such a thread has the lowest priority and any disk I/O is throttled to minimize the impact on the system.

別のスレッドで実行していますが、それは必ずしも「バックグラウンドで」スレッドであるとは限りません。私の経験では、何かをロードしているバックグラウンド スレッドは、UIScrollView のスクロールなどの UI 更新を行うことで完全にブロックされます。使ってみましたDISPATCH_QUEUE_PRIORITY_BACKGROUNDか?

于 2012-12-18T21:57:41.417 に答える