2

私は自分の質問Display photolibrary images in a effectual way iPhone非常に効率的な UITableView "cellForRowIndexPath" method to bind the PhotoLibrary imagesに関してこの質問をしています。

したがって、以下の詳細を読まずに回答が重複しないようにお願いしたいと思います:)

本題に入りましょう、

上記の問題について詳しく調査したところ、ここから操作キューに関するドキュメントを見つけました。

そこで、ALAsset ブロックによる操作キューを使用して、7 つのフォト ライブラリ イメージを表示する 1 つのサンプル アプリケーションを作成しました。

サンプル アプリケーションの詳細は次のとおりです。

ステップ1:

NSOperationalQueueViewController のviewDidLoadメソッドで、すべてのフォト ギャラリー ALAsset URLを という名前の配列に取得しましたurlArray

ステップ2:

すべての URL が に追加されたurlArray後、 if(group != nil)条件は で false になるassetGroupEnumeratorため、 を作成し、ループをNSOperationQueue介して 7 つの UIImageViewを作成し、対応するイメージ ビューURLを使用してサブクラス オブジェクトを作成しました。に追加します。forNSOperationNSOperationQueue

ここでNSOperation私のサブクラスを参照してください。

ここで私の実装(VierwController)クラスを参照して ください

問題に行きましょう。

7 つの画像すべてが一貫して表示されるわけではありません。画像の一部が欠落しています。欠落している順序が複数回変更されています (ある時は 6 番目と 7 番目が表示されず、別の時は 2 番目と 3 番目だけが表示されません)。コンソール ログには、Could not find photo pic number が表示されます。ただし、URL は正しくログに記録されます。

ログの詳細はこちらで確認できます。

私のクラスに間違いはありますか?

また、上記の操作キューのドキュメントを読んだときに、 について読みましNSBlockOperationた。ALAsset ブロックを処理するNSBlockOperation代わりに実装する必要がありますか?NSOperation

NSBlockOperation説明によると

1 つ以上のブロック オブジェクトを同時に実行するためにそのまま使用するクラス。複数のブロックを実行できるため、ブロック操作オブジェクトはグループ セマンティックを使用して動作します。関連付けられたすべてのブロックの実行が終了した場合にのみ、操作自体が終了したと見なされます。

NSBlockOperationサンプル アプリケーションに関して with ALAsset ブロックを実装するにはどうすればよいですか?

私は Stack Overflow の質問Learning NSBlockOperationを経験しました。NSBlockOperationしかし、 with ALAsset ブロックを実装するアイデアが思い浮かびませんでした!!

4

2 に答える 2

5

「ALAsset Libraryを使ってiPhonePhoto Libraryの全画像にアクセスし、iPhoneSimulatorのようにUIScrollViewで表示する方法」のチュートリアルです。 まずAssetsLibrary.framework、プロジェクトに追加します。

次に、ファイルにヘッダーファイルをviewController.hインポートします。#import <AssetsLibrary/AssetsLibrary.h>

これはあなたのviewController.hファイルです

#import <UIKit/UIKit.h>
#import <AssetsLibrary/AssetsLibrary.h>
#import "AppDelegate.h"

@interface ViewController : UIViewController <UIScrollViewDelegate>
{
    ALAssetsLibrary *assetsLibrary;
    NSMutableArray *groups;
    ALAssetsGroup *assetsGroup;

   // I will show all images on `UIScrollView`
    UIScrollView *myScrollView;

    UIActivityIndicatorView *activityIndicator;

    NSMutableArray *assetsArray;
    // Will handle thumbnail of images 
    NSMutableArray *imageThumbnailArray;
    // Will handle original images 
    NSMutableArray *imageOriginalArray;

    UIButton *buttonImage;
 }

-(void)displayImages;
-(void)loadScrollView;

@end

そして、これはあなたのviewController.mファイルです - viewWillAppear:

#import "ViewController.h"
#import <QuartzCore/QuartzCore.h>

@implementation ViewController

- (void)viewWillAppear:(BOOL)animated
{
  [super viewWillAppear:animated];

  assetsArray = [[NSMutableArray alloc]init];
  imageThumbnailArray = [[NSMutableArray alloc]init];
  imageOriginalArray = [[NSMutableArray alloc]init];

  myScrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0.0, 0.0, 320.0, 416.0)];
  myScrollView.delegate = self;
  myScrollView.contentSize = CGSizeMake(320.0, 416.0);
  myScrollView.backgroundColor = [UIColor whiteColor];

  activityIndicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
  activityIndicator.center = myScrollView.center;
  [myScrollView addSubview:activityIndicator];
  [self.view addSubview:myScrollView];

  [activityIndicator startAnimating];

}

viewDidAppear:

-(void)viewDidAppear:(BOOL)animated
{
 if (!assetsLibrary) {
        assetsLibrary = [[ALAssetsLibrary alloc] init];
    }
    if (!groups) {
     groups = [[NSMutableArray alloc] init];
  } 
 else {
     [groups removeAllObjects];
 }

 ALAssetsLibraryGroupsEnumerationResultsBlock listGroupBlock = ^(ALAssetsGroup *group, BOOL *stop) {
        //NSLog(@"group %@",group);
        if (group) {
            [groups addObject:group];
         //NSLog(@"groups %@",groups);
     } else {
         //Call display Images method here.
         [self displayImages];
        }
 };
 ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError *error) {
     NSString *errorMessage = nil;
        switch ([error code]) {
         case ALAssetsLibraryAccessUserDeniedError:
            case ALAssetsLibraryAccessGloballyDeniedError:
             errorMessage = @"The user has declined access to it.";
                break;
            default:
             errorMessage = @"Reason unknown.";
             break;
     }
    };
    [assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:listGroupBlock failureBlock:failureBlock];

}

そして、これがdisplayImages:メソッド本体です

-(void)displayImages
{
// NSLog(@"groups %d",[groups count]);
  for (int i = 0 ; i< [groups count]; i++) {
     assetsGroup = [groups objectAtIndex:i];
        if (!assetsArray) {
         assetsArray = [[NSMutableArray alloc] init];
        }
        else {
         [assetsArray removeAllObjects];
     }

     ALAssetsGroupEnumerationResultsBlock assetsEnumerationBlock = ^(ALAsset *result, NSUInteger index, BOOL *stop) {

            if (result) {
                [assetsArray addObject:result];
            }
     };
        ALAssetsFilter *onlyPhotosFilter = [ALAssetsFilter allPhotos];
        [assetsGroup setAssetsFilter:onlyPhotosFilter];
        [assetsGroup enumerateAssetsUsingBlock:assetsEnumerationBlock];

    }

    //Seprate the thumbnail and original images
    for(int i=0;i<[assetsArray count]; i++)
    {
        ALAsset *asset = [assetsArray objectAtIndex:i];
        CGImageRef thumbnailImageRef = [asset thumbnail];
        UIImage *thumbnail = [UIImage imageWithCGImage:thumbnailImageRef];
        [imageThumbnailArray addObject:thumbnail];

        ALAssetRepresentation *representation = [asset defaultRepresentation];
        CGImageRef originalImage = [representation fullResolutionImage];
        UIImage *original = [UIImage imageWithCGImage:originalImage];
        [imageOriginalArray addObject:original];
    }

    [self loadScrollView];
}

これで が 2arrayつありimageThumbnailArray、もう 1 つは ですimageOriginalArray。スクロールが遅くならないimageThumbnailArray表示に使用します.... 画像の拡大プレビューに使用します。UIScrollViewimageOriginalArray

'loadScrollView:' メソッド, iPhoneSimulator のように画像を表示する方法UIScrollViewです

#pragma mark - LoadImages on UIScrollView
-(void)loadScrollView
{
    float horizontal = 8.0;
    float vertical = 8.0;

    for(int i=0; i<[imageThumbnailArray count]; i++)
    {
        if((i%4) == 0 && i!=0)
        {
            horizontal = 8.0;
            vertical = vertical + 70.0 + 8.0;
        }

        buttonImage = [UIButton buttonWithType:UIButtonTypeCustom];
        [buttonImage setFrame:CGRectMake(horizontal, vertical, 70.0, 70.0)];
        [buttonImage setTag:i];
    [   buttonImage setImage:[imageThumbnailArray objectAtIndex:i] forState:UIControlStateNormal];
        [buttonImage addTarget:self action:@selector(buttonImagePressed:) forControlEvents:UIControlEventTouchUpInside];
        [myScrollView addSubview:buttonImage];
        horizontal = horizontal + 70.0 + 8.0;

    }

    [myScrollView setContentSize:CGSizeMake(320.0, vertical + 78.0)];
    [activityIndicator stopAnimating];
    [activityIndicator removeFromSuperview];
}

buttonここで、どの画像がクリックされたかを確認できます -

#pragma mark - Button Pressed method
-(void)buttonImagePressed:(id)sender
{
     NSLog(@"you have pressed : %d button",[sender tag]);   
}

このチュートリアルがあなたと同じものを検索する多くのユーザーに役立つことを願っています..ありがとう!

于 2012-07-23T06:44:32.347 に答える
4

DisplayImages NSOperation サブクラスに、UI を更新する行があります (DisplayImages.m 行 54):

self.imageView.image = topicImage;

この操作キューはバックグラウンド スレッドで実行されており、メイン スレッドでのみ UI の状態を更新する必要があることがわかっています。画像ビューのビューを更新すると間違いなく UI が更新されるため、呼び出しを次のようにラップすることで簡単に修正できます。

dispatch_async(dispatch_get_main_queue(), ^{
   self.imageView.image = topicImage;
});

これにより、非同期呼び出しがメイン キューに置かれ、UIImageView が画像で更新されます。非同期であるため、他のタスクをバックグラウンドでスケジュールできます。また、メイン キュー (メイン スレッド) で実行されるため安全です。

于 2012-07-23T18:14:48.273 に答える