我问的问题是Display photolibrary images in an effectual way iPhone和 Highly efficient UITableView "cellForRowIndexPath" method to bind the PhotoLibrary images 。
所以我想请求在没有阅读以下细节的情况下,答案不会重复到这个答案:)
让我们来讨论这个问题,
我已经详细研究了上述问题,我从here找到了关于操作队列的文档。
所以我创建了一个示例应用程序,通过ALAsset块使用操作队列显示七个照片库图像。
以下是示例应用程序详细信息。
第1步:
在NSOperationalQueueViewController viewDidLoad 方法中,我已将所有照片库ALAsset URLs检索到名为urlArray
的数组中。
第2步:
将所有网址添加到urlArray
后, if(group!= nil)条件在assetGroupEnumerator
中将为false,因此我创建了一个{{ 1}},然后通过NSOperationQueue
循环创建了7个UIImageView,并使用相应的图像视图和 URL 创建了我的for
子类对象每个将添加到NSOperation
。
请参阅我的NSOperationQueue
子类here。
查看我的实现(VierwController)类 here。
让我们来讨论这个问题。
它不会始终显示所有七个图像。一些图像丢失了。丢失的顺序多次改变(一次不显示第六和第七次,另一次不显示第二次和第三次)。控制台日志显示无法找到照片图片号。但是,URL已正确记录。
您可以查看日志详细信息here。
我班上有错误吗?
另外,当我浏览上面提到的operational queue文档时,我已经阅读了NSOperation
。在处理ALAsset块时,是否需要实现NSBlockOperation
而不是NSBlockOperation
?
NSOperation
说明
您原样使用的类,用于执行一个或多个块对象 同时。因为它可以执行多个块,一个块 操作对象使用组语义进行操作;只有当所有的 关联块已完成执行是操作本身 考虑完了。
如何针对我的示例应用程序实现带有ALAsset块的NSBlockOperation
?
我已经完成了Stack Overflow问题 Learning NSBlockOperation 。但是,我没有想到用ALAsset块实现NSBlockOperation
!!
答案 0 :(得分:5)
这是关于“如何使用ALAsset库从iPhonePhoto库访问所有图像并在UIScrollView上显示它们的教程”的教程,如iPhoneSimulator。
首先将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];
}
现在您有两个array
一个imageThumbnailArray
,另一个imageOriginalArray
。
使用imageThumbnailArray
在UIScrollView
上显示您的滚动速度不会很慢....并使用imageOriginalArray
进行放大的图像预览。
'loadScrollView:'方法,这是UIScrollView
上的图像,如 iPhoneSimulator
#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]);
}
希望本教程能够帮助您和许多搜索相同内容的用户..谢谢!
答案 1 :(得分:4)
您在DisplayImages NSOperation子类中有一行更新UI(DisplayImages.m第54行):
self.imageView.image = topicImage;
此操作队列在后台线程上运行,我们知道您应该只更新主线程上的UI状态。由于更新图像视图的视图肯定是在更新UI,因此可以通过使用:
包装调用来简单地修复此问题dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = topicImage;
});
这会在主队列上进行异步调用,以使用映像更新UIImageView。它是异步的,所以你的其他任务可以在后台安排,并且它在主队列上运行是安全的 - 这是主线程。