好些天没写点东西了,最近公司要做新项目,有点小忙。不想我的坚持就此中断,我把我前些天研究的东西拿出来给大家看看。
这次整理的是AssetsLibrary和PhotoKit的使用。本人处女座,有点强迫症,之前写的项目里用的是AssetsLibrary写的调取相册内的媒体文件,但是Xcode总是报警告错误,虽然能够html" target="_blank">编译并展示效果,但是十几个警告错误挂在那,心里总不是滋味,所以我就研究了一下AssetLibrary和PhotoKit。
在 iOS 8 出现之前,开发者只能使用 AssetsLibrary 框架来访问设备的照片库,这是一个有点跟不上 iOS 应用发展步伐以及代码设计原则但确实强大的框架,考虑到 iOS7 仍占有不少的渗透率,因此 AssetsLibrary 也是本文重点介绍的部分。而在 iOS8 出现之后,苹果提供了一个名为 PhotoKit 的框架,一个可以让应用更好地与设备照片库对接的框架。
一、AssetsLibrary 组成
AssetsLibrary 的组成比较符合照片库本身的组成,照片库中的完整照片库对象、相册、相片都能在 AssetsLibrary 中找到一一对应的组成,这使到 AssetsLibrary 的使用变得直观而方便。想要了解AssetsLibrary得从它的类开始。
AssetsLibrary: 代表整个设备中的资源库(照片库),通过 AssetsLibrary 可以获取和包括设备中的照片和视频
@话不多说,直接上代码
#import <AssetsLibrary/AssetsLibrary.h> // 必须导入 // 照片原图路径 #define KOriginalPhotoImagePath \ [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@"OriginalPhotoImages"] // 视频URL路径 #define KVideoUrlPath \ [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@"VideoURL"] // caches路径 #define KCachesPath \ [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] // MainViewController @interface MTHMainViewController () @property (nonatomic,strong) MTHNextViewController *nextVC; @property (nonatomic,strong) NSMutableArray *groupArrays; @property (nonatomic,strong) UIImageView *litimgView; @end @implementation MTHMainViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.navigationItem.title = @"Demo"; self.view.backgroundColor = [UIColor clearColor]; // 初始化 self.groupArrays = [NSMutableArray array]; // 测试BarItem self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"测试" style:UIBarButtonItemStylePlain target:self action:@selector(testRun)]; // 测试手势 UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didClickPanGestureRecognizer:)]; [self.navigationController.view addGestureRecognizer:panRecognizer]; // 图片或者视频的缩略图显示 self.litimgView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 200, 120, 120)]; [self.view addSubview:_litimgView]; } - (void)testRun { __weak MTHMainViewController *weakSelf = self; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ ALAssetsLibraryGroupsEnumerationResultsBlock listGroupBlock = ^(ALAssetsGroup *group, BOOLBOOL *stop) { if (group != nil) { [weakSelf.groupArrays addObject:group]; } else { [weakSelf.groupArrays enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOLBOOL *stop) { [obj enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOLBOOL *stop) { if ([result thumbnail] != nil) { // 照片 if ([[result valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypePhoto]){ NSDate *date= [result valueForProperty:ALAssetPropertyDate]; UIImage *image = [UIImage imageWithCGImage:[result thumbnail]]; NSString *fileName = [[result defaultRepresentation] filename]; NSURL *url = [[result defaultRepresentation] url]; int64_t fileSize = [[result defaultRepresentation] size]; NSLog(@"date = %@",date); NSLog(@"fileName = %@",fileName); NSLog(@"url = %@",url); NSLog(@"fileSize = %lld",fileSize); // UI的更新记得放在主线程,要不然等子线程排队过来都不知道什么年代了,会很慢的 dispatch_async(dispatch_get_main_queue(), ^{ self.litimgView.image = image; }); } // 视频 else if ([[result valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypeVideo] ){ // 和图片方法类似 } } }]; }]; } }; ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError *error) { NSString *errorMessage = nil; switch ([error code]) { case ALAssetsLibraryAccessUserDeniedError: case ALAssetsLibraryAccessGloballyDeniedError: errorMessage = @"用户拒绝访问相册,请在<隐私>中开启"; break; default: errorMessage = @"Reason unknown."; break; } dispatch_async(dispatch_get_main_queue(), ^{ UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"错误,无法访问!" message:errorMessage delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil, nil nil]; [alertView show]; }); }; ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init]; [assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:listGroupBlock failureBlock:failureBlock]; }); }
@但是:
按照上面方法直接取出来的路径是无法传输的,必须自己转化成NSData对象重新写入沙盒路径
// 将原始图片的URL转化为NSData数据,写入沙盒 - (void)imageWithUrl:(NSURL *)url withFileName:(NSString *)fileName { // 进这个方法的时候也应该加判断,如果已经转化了的就不要调用这个方法了 // 如何判断已经转化了,通过是否存在文件路径 ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc] init]; // 创建存放原始图的文件夹--->OriginalPhotoImages NSFileManager * fileManager = [NSFileManager defaultManager]; if (![fileManager fileExistsAtPath:KOriginalPhotoImagePath]) { [fileManager createDirectoryAtPath:KOriginalPhotoImagePath withIntermediateDirectories:YES attributes:nil error:nil]; } dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ if (url) { // 主要方法 [assetLibrary assetForURL:url resultBlock:^(ALAsset *asset) { ALAssetRepresentation *rep = [asset defaultRepresentation]; Byte *buffer = (Byte*)malloc((unsigned long)rep.size); NSUInteger buffered = [rep getBytes:buffer fromOffset:0.0 length:((unsigned long)rep.size) error:nil]; NSData *data = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES]; NSString * imagePath = [KOriginalPhotoImagePath stringByAppendingPathComponent:fileName]; [data writeToFile:imagePath atomically:YES]; } failureBlock:nil]; } }); } // 将原始视频的URL转化为NSData数据,写入沙盒 - (void)videoWithUrl:(NSURL *)url withFileName:(NSString *)fileName { // 解析一下,为什么视频不像图片一样一次性开辟本身大小的内存写入? // 想想,如果1个视频有1G多,难道直接开辟1G多的空间大小来写? ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc] init]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ if (url) { [assetLibrary assetForURL:url resultBlock:^(ALAsset *asset) { ALAssetRepresentation *rep = [asset defaultRepresentation]; NSString * videoPath = [KCachesPath stringByAppendingPathComponent:fileName]; char constconst *cvideoPath = [videoPath UTF8String]; FILEFILE *file = fopen(cvideoPath, "a+"); if (file) { const int bufferSize = 11024 * 1024; // 初始化一个1M的buffer Byte *buffer = (Byte*)malloc(bufferSize); NSUInteger read = 0, offset = 0, written = 0; NSError* err = nil; if (rep.size != 0) { do { read = [rep getBytes:buffer fromOffset:offset length:bufferSize error:&err]; written = fwrite(buffer, sizeof(char), read, file); offset += read; } while (read != 0 && !err);//没到结尾,没出错,ok继续 } // 释放缓冲区,关闭文件 free(buffer); buffer = NULL; fclose(file); file = NULL; } } failureBlock:nil]; } }); }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
本文向大家介绍iOS开发-调用系统相机和相册获取照片示例,包括了iOS开发-调用系统相机和相册获取照片示例的使用技巧和注意事项,需要的朋友参考一下 前言:相信大家都知道大部分的app都是有我的模块的,而在我的模块基本都有用户的头像等信息,并且是可以更改头像的。那么今天小编给大家简单介绍一下iOS开发中如何调用系统相机拍照或者相册获取照片。要获取系统相机或者相册,我们需要使用到 UIImagePic
本文向大家介绍Android开发从相机或相册获取图片裁剪,包括了Android开发从相机或相册获取图片裁剪的使用技巧和注意事项,需要的朋友参考一下 废话不多说了,直接给大家贴代码了。 以上代码很简单,相信大家都可以看的懂吧,欲了解更多信息请持续关注本站,谢谢。
本文向大家介绍iOS开发教程之自定制图片浏览器,包括了iOS开发教程之自定制图片浏览器的使用技巧和注意事项,需要的朋友参考一下 前言 图片浏览器大家应该都用过,这方面的第三方也有很多,不过有时候第三方会跟我们的需求有一些出入,这就需要我们要么对第三方进行修改要么自己重新定制。我是比较喜欢自己重新定制的,在这给大家简单介绍一下我定制的图片浏览器,算是给大家提供一个思路,可以在此基础上进行修改完善。
内核是操作系统最基础也是最重要的部分,包含线程调度、时钟管理、线程间同步与通信、内存管理等内容,可阅读《内核基础》进行了解。 内核视频教程基于内核示例讲解,观看视频之前请做好内核示例代码准备 。 内核视频教程百度网盘链接:https://pan.baidu.com/s/19jvxfQlyfyp_PH9dt-6OAQ 提取码:i3xq 初识 RT-Thread 动态内存堆的使用 参考资料:《内存管理
问题内容: 我的情况很简单:我需要播放警告信号并希望确保用户会听到它,因此我想检查系统音量。 如何找出当前的系统容量是多少? 问题答案: Swift更新 音频会话可以提供输出音量(iOS> = 6.0)。
cmf_get_image_url($file, $style = '') 功能 转化数据库保存图片的文件路径,为可以访问的url 参数 $file: string 文件路径,数据存储的文件相对路径 $style: string 图片样式,支持各大云存储 返回 string 图片链接 例子 <?php // 数据存储的文件相对路径 $image_filepath='portal/12341234