项目要用到图片上传功能,要求读取相册中的全部图片加以展示,由用户选择进行上传。从网上找了大家比较通用的方法,稍加修改,实现了需求。
参考代码:ELCImagePickerDemo
一、读取相册
[cpp] view plain copy print ?
-
- dispatch_async(dispatch_get_main_queue(), ^
- {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
-
- void (^assetGroupEnumerator)(ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop)
- {
- if (group == nil)
- {
- return;
- }
-
- [self.assetGroups addObject:group];
-
-
- [self performSelectorOnMainThread:@selector(reloadTableView) withObject:nil waitUntilDone:YES];
- };
-
-
- void (^assetGroupEnumberatorFailure)(NSError *) = ^(NSError *error) {
-
- UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Error" message:[NSString stringWithFormat:@"Album Error: %@ - %@", [error localizedDescription], [error localizedRecoverySuggestion]] delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
- [alert show];
- [alert release];
-
- NSLog(@"A problem occured %@", [error description]);
- };
-
-
- [library enumerateGroupsWithTypes:ALAssetsGroupAll
- usingBlock:assetGroupEnumerator
- failureBlock:assetGroupEnumberatorFailure];
-
- [pool release];
- });
// Load Albums into assetGroups
dispatch_async(dispatch_get_main_queue(), ^
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Group enumerator Block
void (^assetGroupEnumerator)(ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop)
{
if (group == nil)
{
return;
}
[self.assetGroups addObject:group];
// Reload albums
[self performSelectorOnMainThread:@selector(reloadTableView) withObject:nil waitUntilDone:YES];
};
// Group Enumerator Failure Block
void (^assetGroupEnumberatorFailure)(NSError *) = ^(NSError *error) {
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Error" message:[NSString stringWithFormat:@"Album Error: %@ - %@", [error localizedDescription], [error localizedRecoverySuggestion]] delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
[alert show];
[alert release];
NSLog(@"A problem occured %@", [error description]);
};
// Enumerate Albums
[library enumerateGroupsWithTypes:ALAssetsGroupAll
usingBlock:assetGroupEnumerator
failureBlock:assetGroupEnumberatorFailure];
[pool release];
});
上面的代码就是用于读取相册内容的。几点说明:
1. 因为图片中包含位置信息,因此访问图片资源时,系统会弹出询问框“是否允许访问位置信息”?如果选择否,就会进入这一块assetGroupEnumberatorFailure,提示读取图片失败。据说ios5.0以后系统才增加了这个提示,之前是没有这种情况的。
2. ios5.0以后用户可以自己新建相簿,因此这个ALAssetsGroupAll这个值是表示读出所有相簿,你可以把每个相簿列出来,再进一步选择展示哪个相簿中的图片。开源例子中就是这个效果。不过因为我的需求是只展示系统默认的“相机胶卷”这个相簿中的图片,因此,把这里改为ALAssetsGroupSavedPhotos这个值,就可以直接读取相机胶卷中的照片,不需要进一步选择了。
二、读取相册中的图片
ELCAssetTablePicker.m中的preparePhotos函数
[cpp] view plain copy print ?
- -(void)preparePhotos {
-
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
-
- NSLog(@"enumerating photos");
- [self.assetGroup enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop)
- {
- if(result == nil)
- {
- return;
- }
-
- ELCAsset *elcAsset = [[[ELCAsset alloc] initWithAsset:result] autorelease];
- [elcAsset setParent:self];
- [self.elcAssets addObject:elcAsset];
- }];
- NSLog(@"done enumerating photos");
-
- [self.tableView reloadData];
- [self.navigationItem setTitle:@"Pick Photos"];
-
- [pool release];
-
- }
-(void)preparePhotos {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(@"enumerating photos");
[self.assetGroup enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop)
{
if(result == nil)
{
return;
}
ELCAsset *elcAsset = [[[ELCAsset alloc] initWithAsset:result] autorelease];
[elcAsset setParent:self];
[self.elcAssets addObject:elcAsset];
}];
NSLog(@"done enumerating photos");
[self.tableView reloadData];
[self.navigationItem setTitle:@"Pick Photos"];
[pool release];
}
在次之前,可以对assetGroup设置过滤,如下设置为只读取图片。因为其实用手机拍摄的视频也会存入“相机胶卷”中,所以可以根据自己的需要进行过滤。
[picker.assetGroup setAssetsFilter:[ALAssetsFilter allPhotos]];
每张图片对应的就是一个ALAsset对象。
三、读取出的图片信息
[cpp] view plain copy print ?
- [self.asset thumbnail]
[self.asset thumbnail]
ALAsset的thumbnail是图片的缩略图,如果你需要以九宫格的形式把图片都展示出来,肯定要展示的是缩略图,而不能是巨大的原图。
[cpp] view plain copy print ?
- -(void)selectedAssets:(NSArray*)_assets {
-
- NSMutableArray *returnArray = [[[NSMutableArray alloc] init] autorelease];
-
- for(ALAsset *asset in _assets) {
-
- NSMutableDictionary *workingDictionary = [[NSMutableDictionary alloc] init];
- [workingDictionary setObject:[asset valueForProperty:ALAssetPropertyType] forKey:@"UIImagePickerControllerMediaType"];
- [workingDictionary setObject:[UIImage imageWithCGImage:[[asset defaultRepresentation] fullScreenImage]] forKey:@"UIImagePickerControllerOriginalImage"];
- [workingDictionary setObject:[[asset valueForProperty:ALAssetPropertyURLs] valueForKey:[[[asset valueForProperty:ALAssetPropertyURLs] allKeys] objectAtIndex:0]] forKey:@"UIImagePickerControllerReferenceURL"];
-
- [returnArray addObject:workingDictionary];
-
- [workingDictionary release];
- }
-
- [self popToRootViewControllerAnimated:NO];
- [[self parentViewController] dismissModalViewControllerAnimated:YES];
-
- if([delegate respondsToSelector:@selector(elcImagePickerController:didFinishPickingMediaWithInfo:)]) {
- [delegate performSelector:@selector(elcImagePickerController:didFinishPickingMediaWithInfo:) withObject:self withObject:[NSArray arrayWithArray:returnArray]];
- }
- }
-(void)selectedAssets:(NSArray*)_assets {
NSMutableArray *returnArray = [[[NSMutableArray alloc] init] autorelease];
for(ALAsset *asset in _assets) {
NSMutableDictionary *workingDictionary = [[NSMutableDictionary alloc] init];
[workingDictionary setObject:[asset valueForProperty:ALAssetPropertyType] forKey:@"UIImagePickerControllerMediaType"];
[workingDictionary setObject:[UIImage imageWithCGImage:[[asset defaultRepresentation] fullScreenImage]] forKey:@"UIImagePickerControllerOriginalImage"];
[workingDictionary setObject:[[asset valueForProperty:ALAssetPropertyURLs] valueForKey:[[[asset valueForProperty:ALAssetPropertyURLs] allKeys] objectAtIndex:0]] forKey:@"UIImagePickerControllerReferenceURL"];
[returnArray addObject:workingDictionary];
[workingDictionary release];
}
[self popToRootViewControllerAnimated:NO];
[[self parentViewController] dismissModalViewControllerAnimated:YES];
if([delegate respondsToSelector:@selector(elcImagePickerController:didFinishPickingMediaWithInfo:)]) {
[delegate performSelector:@selector(elcImagePickerController:didFinishPickingMediaWithInfo:) withObject:self withObject:[NSArray arrayWithArray:returnArray]];
}
}
这个函数,将用户选择的图片的信息记录下来,在主界面上弄个scrollView来一一展示,这里就要用到原图了,开源的例子有问题,居然把图片都加载进去了,选多了必然崩溃呀,反正就是示例吧,没考虑那么细。
这个函数中可以看到,ALAsset对象中包括媒体类型、原图、各种的句柄URL之类的(我还没用过),应该足够满足你的需求了。因为我要做的功能是图片的上传功能,肯定涉及将图片转为NSData进行上传的处理,因此还获取了图片的类型,是png还是jpg,以便调用相应的api进行转码。下面代码能获取,然后比较是kUTTypePNG还是kUTTypeJPEG。
[[asset defaultRepresentation]UTI]
总结:上述方法算是大家都采用的常规方法了吧,开源的例子挺清楚的,相关界面的实现也有一定参考价值,最终我实现的效果是这样。
PS:顶部的navibar仿照系统的相册,系统提供的方法就足够了,稍微尝试一下,找到最接近系统相册的效果就好了。