ios设置imageview大小的占位占位图怎么设置 ios

iOS-自定义TextView的方法,可以设置占位文字(placeholder)又可滚动 - 推酷
iOS-自定义TextView的方法,可以设置占位文字(placeholder)又可滚动
自定义TextView
在使用textView的时候,我们如果希望它拥有textField的占位文字的功能,就要自定义了。
先看自定义的流程:
下面给出具体的代码:
(后面有注意点讲解)
#import &UIKit/UIKit.h&
@interface XYLPlaceHodlerTextView : UITextView
/**placeholder占位文字*/
@property (nonatomic, copy) NSString *
/**placeholderColor占位文字颜色*/
@property (nonatomic, strong) UIColor *placeholderC
#import &XYLPlaceHodlerTextView.h&
@interface XYLPlaceHodlerTextView()
/**UILabel*/
@property (nonatomic, strong) UILabel *placeholderL
@implementation XYLPlaceHodlerTextView
懒加载属性,并设置属性的值
-(UILabel *)placeholderLabel
if (!_placeholderLabel) {
UILabel *label = [[UILabel alloc]init];
label.font = [UIFont systemFontOfSize:14];
label.textColor = [UIColor grayColor];
label.numberOfLines = 0;
self.placeholderLabel =
return self.placeholderL
设置自己的属性
-(instancetype)initWithFrame:(CGRect)frame
if (self = [super initWithFrame:frame]) {
self.alwaysBounceVertical = YES;
self.textColor = [UIColor blackColor];
[XYLNotificationCenter addObserver:self selector:@selector(texting) name:UITextViewTextDidChangeNotification object:self];
监听有文字输入
-(void)texting
[self setPlaceholderTextShow];
设置占位文字的显示
-(void)setPlaceholderTextShow
self.placeholderLabel.hidden = self.hasT
-(void)layoutSubviews
[super layoutSubviews];
self.placeholderLabel.x = 4;
self.placeholderLabel.y = 8;
self.placeholderLabel.width = self.width - 2 * self.placeholderLabel.x;
[self.placeholderLabel sizeToFit];//这一步很重要,不能遗忘
-(void)setPlaceholder:(NSString *)placeholder
// _placeholder =//此句的意义何在?
self.placeholderLabel.text =
[self setNeedsLayout];
-(void)setPlaceholderColor:(UIColor *)placeholderColor
self.placeholderLabel.textColor = placeholderC
[self setNeedsLayout];
-(void)setFont:(UIFont *)font
[super setFont:font];
self.placeholderLabel.font =
[self setNeedsLayout];
-(void)setText:(NSString *)text
[super setText:text];
[self setPlaceholderTextShow];
-(void)setAttributedText:(NSAttributedString *)attributedText
[super setAttributedText:attributedText];
[self setPlaceholderTextShow];
界面显示步骤是先调用layoutSubviews将所有子控件的位置frame设计好,然后再调用drawRect方法画上去。
layoutSubviews的调用时机:
init时不会被调用
将要真正显示的会调用
frame发现改变时智能调用
滚动、旋转、remove等等时
这些时机都是和frame相关的,也是唯一能更新子视图的最好时机
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致Glide加载圆形image第一次显示占位图的原因
Glide加载圆形image第一次显示占位图的原因
Android基础知识
一些解决方案
1.如果你刚好使用了这个圆形或者其他的一些自定义的圆形Imageview,而你又刚好设置了占位的话,那么,你就会遇到第一个问题。如何解决呢?
方案一: 不设置占位;
方案二:使用Glide的Transformation API自定义圆形Bitmap的转换。这里是一个已有的;
方案三:使用下面的代码加载图片:
Glide.with(mContext)
.load(url)
.placeholder(R.drawable.loading_spinner)
.into(new SimpleTarget&Bitmap&(width, height) {
public void onResourceReady(Bitmap bitmap, GlideAnimation anim) {
感谢指出该方法在listview上复用有问题的bug,如果在listview中加载CircleImageView,请不要使用该方法。
方案四:不使用Glide的默认动画:
Glide.with(mContext)
.load(url)
.dontAnimate()
.placeholder(R.drawable.loading_spinner)
.into(circleImageview);
我的热门文章
即使是一小步也想与你分享主题 : 使用SDWebImage的UIImageView+WebCache.h下载图片出现错乱
级别: 新手上路
可可豆: 42 CB
威望: 44 点
在线时间: 107(时)
发自: Web Page
使用SDWebImage的UIImageView+WebCache.h下载图片出现错乱&&&
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *MyIdentifier = @"MyIdentifier";
UITableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:MyIdentifier];
Status *status = _statuses[indexPath.row] ;
[cell.textLabel setText:@"%i === %@",indexPath.row,status.user.screen_name]];
NSArray * arr = status.pic_
if (arr.count & 0) {
[cell.imageView setImageWithURL:[NSURL URLWithString:arr[0][@"thumbnail_pic"]] placeholderImage:[UIImage imageNamed:@"timeline_image_loading.png"] options:SDWebImageLowPriority | SDWebImageRetryFailed];
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 300.0;}
正确的情况是第4个cell应该没有图片的,但是结果是有跟第一个cell一样的图片的,而且接下来来回拖动会产生更过的错乱,麻烦求教下这是什么问题?
级别: 精灵王
UID: 113399
发帖: 3616
可可豆: 5689 CB
威望: 6206 点
在线时间: 2578(时)
发自: Web Page
你这个没用sdimageview来做图片的加载吧
SDwebImage的话 应该是用sd_setImageWithURL 这个方法的
还有你的UITableView的 大小设置的是多少?下面这个函数的return是多少
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
级别: 新手上路
可可豆: 13 CB
威望: 13 点
在线时间: 142(时)
发自: Web Page
可能是uitableview &重用导致的,,你可以测试一下
级别: 新手上路
可可豆: 42 CB
威望: 44 点
在线时间: 107(时)
发自: Web Page
我用了SDWebImage了,setImageWithURL内部调用sd_setImageWithURL,- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options {
[self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:nil];}- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section返回的行数是数组status.count。我就是纳闷既然用了sdimageview,加载为什么还出现问题
级别: 侠客
UID: 149352
可可豆: 1152 CB
威望: 772 点
在线时间: 410(时)
发自: Web Page
复用的问题,先理解下复用机制吧
级别: 新手上路
UID: 285691
可可豆: 87 CB
威望: 70 点
在线时间: 222(时)
发自: Web Page
指教,什么原因,怎么解决的呢?
级别: 新手上路
UID: 510864
可可豆: 36 CB
威望: 28 点
在线时间: 42(时)
发自: Web Page
用这个方法sd_setImageWithURL
级别: 新手上路
UID: 387725
可可豆: 118 CB
威望: 86 点
在线时间: 29(时)
发自: Web Page
试试每次加载图片前&&先把cell的imageView 上得图片清一下
不要做白日梦了,成就是努力得来的
级别: 新手上路
可可豆: 2 CB
威望: 2 点
在线时间: 48(时)
发自: Web Page
出现这种情况有可能是imageview设置成了Aspect Fill模式引起的,&&可以通过开启裁剪解决.然后最好设置占位图.&& 我也是出现了几次这种情况,实在不行可以换以前版本的框架试下&&......
关注本帖(如果有新回复会站内信通知您)
8*2-5 正确答案:11
发帖、回帖都会得到可观的积分奖励。
按"Ctrl+Enter"直接提交
关注CocoaChina
关注微信 每日推荐
扫一扫 浏览移动版可以在/rs/SDWebImage这个网站上下载SDWebImage开源包,加到我们的工程中。command+b一下会有8个错误,这时候我们导入MapKit.framework、ImageIO.framework两个框架就好了。然后#import &UIImageView+WebCache.h&一下就OK了。UIImageView+WebCache类是对UIImageView的扩展,所以这个类里的方法直接可以你所创建的UIImageView的对象调用。我们在网上找一个图片点右键复制它的网址。使用- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder success:(void (^)(UIImage *image))success failure:(void (^)(NSError *error))方法,简单的下载一个图片它会自己做缓存。代码如下:&[imageView setImageWithURL:[NSURL URLWithString:@&/upimg/allimg/1144O91.jpg&] placeholderImage:[UIImage imageNamed:@&有种想念叫做避而不见.jpg&] success:^(UIImage *image){} failure:^(NSError *error){} ];为了检查一下它有没有做缓存,我们用NSLog(@&%@&,NSHomeDirectory());输出下这个程序的沙盒路径。桌面上的Finder图标,桌面的左上角的菜单栏有前往,用鼠标点一下前往,按alt键会出前往下面会多一个选项资源库。打开资源库按照打印的路径找到沙盒文件夹,打开Library,再打开Caches文件夹,会发现imageCache文件夹。打开它后会发现一文件,双击打开就是我们下载的图片。简单的研究就到这里啦~~~~简单的Demo可以提供下载网址如下(欢迎下载):/c08aaaw651加载网络图片可以说是网络应用中必备的。如果单纯的去下载图片,而不去做多线程、缓存等技术去优化,加载图片时的效果与用户体验就会很差。一、自己实现加载图片的方法tips:*iOS中所有网络访问都是异步的.(自己开线程去下载)*普通为模型增加UIImage属性的方法做的是内存缓存(下次启动还需要从网络重新加载),&而要做本地缓存的话,还要自己手动存储网络上下载的图片.*为了加快访问,&还需要自己去弄缓存.(内存缓存或者本地缓存)*当图片没有下载完成时,还要设置占位图片。以下代码用NSOperation开异步线程下载图片,当下载完成时替换占位图片。[objc]&view plaincopy//&&//&&XNViewController.m&&//&&加载网络图片,&普通的用NSOperation来做.&&//&&//&&Created&by&neng&on&14-7-7.&&//&&Copyright&(c)&2014年&neng.&All&rights&reserved.&&//&&&&#import&&XNViewController.h&&&#import&&XNApp.h&&&&&@interface&XNViewController&()&&@property&(nonatomic,&strong)&NSArray&*appL&&@property&(nonatomic,&strong)&NSOperationQueue&*&&@end&&&&@implementation&XNViewController&&#pragma&mark&-&懒加载&&&&-&(NSOperationQueue&*)queue&{&&&&&&if&(!_queue)&_queue&=&[[NSOperationQueue&alloc]&init];&&&&&&return&_&&}&&&&//可抽取出来写到模型中&&-&(NSArray&*)appList&{&&&&&&if&(!_appList)&{&&&&&&&&&&//1.加载plist到数组中&&&&&&&&&&NSURL&*url&=&[[NSBundle&mainBundle]&URLForResource:@&apps.plist&&withExtension:nil];&&&&&&&&&&NSArray&*array&=&[NSArray&arrayWithContentsOfURL:url];&&&&&&&&&&//2.遍历数组&&&&&&&&&&NSMutableArray&*arrayM&=&[NSMutableArray&array];&&&&&&&&&&[array&enumerateObjectsUsingBlock:&^(id&obj,&NSUInteger&idx,&BOOLBOOL&*stop)&{&&&&&&&&&&&&&&[arrayM&addObject:[XNApp&appWithDict:obj]];&&//数组中存放的是字典,&转换为app对象后再添加到数组&&&&&&&&&&}];&&&&&&&&&&_appList&=&[arrayM&copy];&&&&&&}&&&&&&return&_appL&&}&&&&-&(void)viewDidLoad&{&&&&&&[super&viewDidLoad];&&&&&&&&self.tableView.rowHeight&=&88;&&&&//&&&&NSLog(@&appList-%@&,_appList);&&}&&&&#pragma&mark&-&数据源方法&&-&(NSInteger)tableView:(UITableView&*)tableView&numberOfRowsInSection:(NSInteger)section&{&&&&&&return&self.appList.count;&&}&&&&-&(UITableViewCell&*)tableView:(UITableView&*)tableView&cellForRowAtIndexPath:(NSIndexPath&*)indexPath&{&&&&&&static&NSString&*ID&=&@&Cell&;&&&&&&UITableViewCell&*cell&=&[tableView&dequeueReusableCellWithIdentifier:ID];&&&&&&&&//用模型来填充每个cell&&&&&&XNApp&*app&=&self.appList[indexPath.row];&&&&&&cell.textLabel.text&=&app.name;&&//设置文字&&&&&&&&//设置图像:&模型中图像为nil时用默认图像,并下载图像.&否则用模型中的内存缓存图像.&&&&&&if&(!app.image)&{&&&&&&&&&&cell.imageView.image&=&[UIImage&imageNamed:@&user_default&];&&&&&&&&&&&&[self&downloadImg:indexPath];&&&&&&}&&&&&&else&{&&&&&&&&&&//直接用模型中的内存缓存&&&&&&&&&&cell.imageView.image&=&app.image;&&&&&&}&&//&&NSLog(@&cell--%p&,&cell);&&&&&&&&return&&&}&&&&/**始终记住,&通过模型来修改显示.&而不要试图直接修改显示*/&&-&(void)downloadImg:(NSIndexPath&*)indexPath&{&&&&&&XNApp&*app&&=&self.appList[indexPath.row];&//取得改行对应的模型&&&&&&&&[self.queue&addOperationWithBlock:&^{&&&&&&&&&&NSData&*imgData&=&[NSData&dataWithContentsOfURL:[NSURL&URLWithString:app.icon]];&//得到图像数据&&&&&&&&&&UIImage&*image&=&[UIImage&imageWithData:imgData];&&&&&&&&&&&&//在主线程中更新UI&&&&&&&&&&[[NSOperationQueue&mainQueue]&addOperationWithBlock:&^{&&&&&&&&&&&&&&//通过修改模型,&来修改数据&&&&&&&&&&&&&&app.image&=&&&&&&&&&&&&&&&//刷新指定表格行&&&&&&&&&&&&&&[self.tableView&reloadRowsAtIndexPaths:@[indexPath]&withRowAnimation:UITableViewRowAnimationNone];&&&&&&&&&&}];&&&&&&}];&&}&&&&@end&&上述代码只是做了内存缓存,而每次重新进入应用时,还会从网上重新下载。如果要继续优化上面的代码,需要自己去实现本地缓存。二、使用第三方框架SDWebImage。(非常优秀)*特点&:依赖的库很少.功能全面。*自动实现磁盘缓存:*缓存图片名字是以MD5进行加密的后的名字进行命名.(因为加密那堆字串是唯一的)*[imageViewsd_setImageWithURL:v.fullImageURL&placeholderImage:[UIImage&imageNamed:@”xxxxx”]].*就一个方法就实现了多线程/带缓冲等效果.(可用带参数的方法,具体可看头文件)用SDWebImage修改上面的方法后的代码可简化为:[objc]&view%20plaincopy#pragma&mark&-&数据源方法&&-&(NSInteger)tableView:(UITableView&*)tableView&numberOfRowsInSection:(NSInteger)section&{&&&&&&return&self.appList.count;&&}&&&&-&(UITableViewCell&*)tableView:(UITableView&*)tableView&cellForRowAtIndexPath:(NSIndexPath&*)indexPath&{&&&&&&static&NSString&*ID&=&@&Cell&;&&&&&&UITableViewCell&*cell&=&[tableView&dequeueReusableCellWithIdentifier:ID];&&&&&&&&//用模型来填充每个cell&&&&&&XNApp&*app&=&self.appList[indexPath.row];&&&&&&cell.textLabel.text&=&app.name;&&//设置文字&&&&//&&//设置图像:&模型中图像为nil时用默认图像,并下载图像.&否则用模型中的内存缓存图像.&&//&&if&(!cell.imageView.image)&{&&//&&&&&&cell.imageView.image&=&[UIImage&imageNamed:@&user_default&];&&//&&//&&&&&&[self&downloadImg:indexPath];&&//&&}&&//&&else&{&&//&&&&&&//直接用模型中的内存缓存&&//&&&&&&cell.imageView.image&=&app.&&//&&}&&&&&&&&&&//使用SDWebImage来完成上面的功能.&针对ImageView.&&&&&&//一句话,&自动实现了异步下载.&图片本地缓存.&网络下载.&自动设置占位符.&&&&&&[cell.imageView&sd_setImageWithURL:[NSURL&URLWithString:app.icon]&placeholderImage:[UIImage&imageNamed:@&user_default&]];&&&&&&&&&&return&&&}&&&&/**始终记住,&通过模型来修改显示.&而不要试图直接修改显示*/&&//-&(void)downloadImg:(NSIndexPath&*)indexPath&{&&//&&XNApp&*app&&=&self.appList[indexPath.row];&//取得改行对应的模型&&//&&//&&[self.queue&addOperationWithBlock:&^{&&//&&&&&&NSData&*imgData&=&[NSData&dataWithContentsOfURL:[NSURL&URLWithString:app.icon]];&//得到图像数据&&//&&&&&&UIImage&*image&=&[UIImage&imageWithData:imgData];&&//&&//&&&&&&//在主线程中更新UI&&//&&&&&&[[NSOperationQueue&mainQueue]&addOperationWithBlock:&^{&&//&&&&&&&&&&//通过修改模型,&来修改数据&&//&&&&&&&&&&app.image&=&&&//&&&&&&&&&&//刷新指定表格行&&//&&&&&&&&&&[self.tableView&reloadRowsAtIndexPaths:@[indexPath]&withRowAnimation:UITableViewRowAnimationNone];&&//&&&&&&}];&&//&&}];&&//}&&&&@end&&SDWebImage中的一些参数:*SDWebImageRetryFailed = 1&& 0, &&默认选项,失败后重试*SDWebImageLowPriority = 1&& 1, & &使用低优先级*SDWebImageCacheMemoryOnly = 1&& 2, &&仅仅使用内存缓存*SDWebImageProgressiveDownload = 1&& 3, &&显示现在进度*SDWebImageRefreshCached = 1&& 4, & &刷新缓存*SDWebImageContinueInBackground =1 && 5, &&后台继续下载图像*SDWebImageHandleCookies = 1&& 6, & &处理Cookie*SDWebImageAllowInvalidSSLCertificates= 1 && 7, & &允许无效的SSL验证*SDWebImageHighPriority = 1&& 8, & &&高优先级*SDWebImageDelayPlaceholder = 1&& 9 & &&延迟显示占位图片转载请注明出处:http://blog.csdn.net/xn4545945&&随笔- 229&
&&&&&&&&&&&
iOS 下的相册与图片处理&
很多公司项目中都会使用到相册,以及相机,保存图片,从相册中选取图片等等操作。本文将详细介绍该功能如何实现优化,以及使用一些优秀的第三方库来辅助完成我们的需求。
photos framework 的使用
Photos Framework reference
PHAdjustmentData
When a user edits an asset, Photos saves a PHAdjustmentData
object along with the modified image or video data.
在用户编辑一个 asset 时,相册会存储该 asset 在修改 image 或者 video 数
据的过程中
PHAdjustmentData
什么是 asset?
A PHAsset object represents an image or video file that appears
in the Photos app, including iCloud Photos content.
一个 PHAsset 对象代表相册中或者云存储中的一个 image 或者 video 文件。
PHAssetChangeRequest
You create and use PHAssetChangeRequest objects within a photo
library change block to create, delete, or modify PHAsset
当你在相册中增删改 PHAsset 对象时需要使用 PHAssetChangeRequest 对象
PHAssetCreationRequest
A PHAssetCreationRequest object, used within a photo library
change block, constructs a new photo or video asset from data
resources, and adds it to the Photos library.
PHAssetCreationRequest 对象用于在照片库的增删改操作中,创建一个新的
image 和 video asset 从 data resources 中,然后将其加入 photos
library 中。
PHAssetCollectionChangeRequest
You create and use PHAssetCollectionChangeRequest objects
within a photo library change block to create, delete, or
modify PHAssetCollection objects.
当你对 photo library 即 assetCollection 进行增删改操作时,使用
PHAssetCollectionChangeRequest 对象
PHAssetResourceCreationOptions
You use a PHAssetResourceCreationOptions object to specify
options when creating a new asset from data resources with a
PHAssetCreationRequest object.
通过 PHAssetResourceCreationOptions 对象来指定当创建一个
新的 asset 的 options。
PHAssetResourceManager
The shared PHAssetResourceManager object provides methods for
accessing the underlying data storage for the resources
associated with a Photos asset.
PHAssetResourceManager 对象提供方法访问关联相机 asset 资源的基础数据存
PHAssetCollection
A PHAssetCollection object represents a collection of photo or &
video assets.
一个 PHAssetCollection 对象就代表一个相册
PHPhotoLibrary
The shared PHPhotoLibrary object represents the user&s Photos
library&the entire set of assets and collections managed by the
Photos app, including objects stored on the local device and
(if enabled) in iCloud Photos.
公共的 PHPhotoLibrary 对象代表用户的相册库,所有的图片和相册管理都
要 PHPhotoLibrary 管理。
保存图片到自定义相册
保存图片一般分为三个步骤:
保存图片到【相机胶卷】
拥有一个【自定义相册】
添加刚才保存的图片到【自定义相册】
需要用到的框架和函数:
c语言函数:只能完成第一个步骤,比较简单
AssetsLibrary 框架:有 bug
Photos 框架 :iOS8以后可以使用
如果单纯的只需要完成第一步则推荐使用一个 c 语言函数就可以搞定。但是如果要保存图片到自定义相册,则需要使用框架。iOS7以前使用 AssetsLibrary 框架,但是该框架的稳定性不高。而 iOS 8 以后的 Photos 框架将会取代 AssetsLibrary 框架完成这一功能。根据目前 app 市场的版本占有率,推荐使用 Photos。
将图片保存到相机胶卷(c 语言函数实现)
* 该 c 语言函数是将图片保存到相机胶卷中
* 第一个参数:image 图片
* 第二个参数:target
* 第三个参数:selector 方法名规定使用以下方法名 :- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextI
* 第四个参数:保存完毕后会将第四个参数传给函数调用者
* 方法作用:将图片保存到相机胶卷中,保存完毕后会调用 target 的 selector 方法
UIImageWriteToSavedPhotosAlbum(self.imageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
如果第三个参数方法名没有按照规范,则有可能会报如下错误:
错误信息:-[NSInvocation setArgument:atIndex:]: index (2) out of bounds [-1, 1]
错误解释:参数越界错误,方法的参数个数和实际传递的参数个数不一致
保存图片到相机胶卷(使用 Photos 框架)
由上面 Photos 框架的介绍可以看出,我们要对相册中的 asset 进行增删改操作时,用到 PHAssetChangeRequest 类,而在 PHAssetChangeRequest 的头文件可以看到,想要在相册胶卷中保存图片。要用到下面方法:
[PHAssetChangeRequest creationRequestForAssetFromImage:self.imageView.image];
但是单独使用时,程序会报错。错误如下:
错误信息:This method can only be called from inside of -
[PHPhotoLibrary performChanges:completionHandler:] or -
[PHPhotoLibrary performChangesAndWait:error:]
错误信息说的很清楚,这个方法只能在 PHPhotoLibrary 类中的这两个方法中
在 iOS app 中,任何对 photos 的增删改操作,都一定会放在上述错误信息的
两个方法中。
具体代码如下:
* 该方法是异步执行的,不会阻塞当前线程,而且执行完后会来到
* completionHandler 的 block 中。
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
& [PHAssetChangeRequest creationRequestForAssetFromImage:self.imageView.image];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
* 该方法是同步执行的。在当前线程 如果执行失败 error 将会有值。
NSError *error =
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
& [PHAssetChangeRequest creationRequestForAssetFromImage:self.imageView.image];
} error:&error];
上述代码执行的操作是:将图片保存到相机胶卷中。
拥有一个自定义相册
通过对 photos 框架的了解,我们知道,创建一个自定义相册,我们需要用到PHAssetCollectionChangeRequest 类。而进入其头文件发现,仍然必须在上述的 PHPhotoLibrary 类的两个 block 中执行操作。
代码如下:
#pragma mark - 使用 photo 框架创建自定义名称的相册 并获取自定义到自定义相册
#pragma mark -
- (PHAssetCollection *)createCustomAssetCollection
& &// 获取 app 名称
& &NSString *title = [NSBundle mainBundle].infoDictionary[(NSString *)kCFBundleNameKey];
& &NSError *error =
& &// 查找 app 中是否有该相册 如果已经有了 就不再创建
& & * & & 参数一 枚举:
& & * & & PHAssetCollectionTypeAlbum & & &= 1, 用户自定义相册
& & * & & PHAssetCollectionTypeSmartAlbum = 2, 系统相册
& & * & & PHAssetCollectionTypeMoment & & = 3, 按时间排序的相册
& & * & & 参数二 枚举:PHAssetCollectionSubtype
& & * & & 参数二的枚举有非常多,但是可以根据识别单词来找出我们想要的。
& & * & & 比如:PHAssetCollectionTypeSmartAlbum 系统相册 PHAssetCollectionSubtypeSmartAlbumUserLibrary 用户相册 就能获取到相机胶卷
& & * & & PHAssetCollectionSubtypeAlbumRegular 常规相册
& &PHFetchResult&PHAssetCollection *& *result = [PHAssetCollection fetchAssetCollectionsWithType:(PHAssetCollectionTypeAlbum)
& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & &subtype:(PHAssetCollectionSubtypeAlbumRegular)
& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & &options:nil];
& &for (PHAssetCollection *collection in result) {
& & & &if ([collection.localizedTitle isEqualToString:title]) { // 说明 app 中存在该相册
& & & & & &
& &/** 来到这里说明相册不存在 需要创建相册 **/
& &__block NSString *createdCustomAssetCollectionIdentifier =
& &// 创建和 app 名称一样的 相册
& & * 注意:这个方法只是告诉 photos 我要创建一个相册,并没有真的创建
& & * & & &必须等到 performChangesAndWait block 执行完毕后才会
& & * & & &真的创建相册。
& &[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
& & & &PHAssetCollectionChangeRequest *collectionChangeRequest = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title];
& & & &/**
& & & & * collectionChangeRequest 即使我们告诉 photos 要创建相册,但是此时还没有
& & & & * 创建相册,因此现在我们并不能拿到所创建的相册,我们的需求是:将图片保存到
& & & & * 自定义的相册中,因此我们需要拿到自己创建的相册,从头文件可以看出,collectionChangeRequest
& & & & * 中有一个占位相册,placeholderForCreatedAssetCollection ,这个占位相册
& & & & * 虽然不是我们所创建的,但是其 identifier 和我们所创建的自定义相册的 identifier
& & & & * 是相同的。所以想要拿到我们自定义的相册,必须保存这个 identifier,等 photos app
& & & & * 创建完成后通过 identifier 来拿到我们自定义的相册
& & & & */
& & & &createdCustomAssetCollectionIdentifier = collectionChangeRequest.placeholderForCreatedAssetCollection.localI
& &} error:&error];
& &// 这里 block 结束了,因此相册也创建完毕了
& &if (error) {
& & & &NSLog(@"创建相册失败");
& &return [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[createdCustomAssetCollectionIdentifier] options:nil].firstO
将相机胶卷的相片存储到自定义相册中
在 photos 框架中,我们并不能直接拿到相册 PHAssetCollection 类来进行增删改操作,需要一个中间类也就是上面所讲的 PHAssetCollectionChangeRequest 类。 步骤如下:
先通过 PHAssetCollection 对象创建 PHAssetCollectionChangeRequest对象通过 PHAssetCollectionChangeRequest 对象来进行增删改操作。
#pragma mark - 将图片保存到自定义相册中
#pragma mark -
- (void)saveImageToCustomAlbum
& &// 将图片保存到相机胶卷
& &NSError *error =
& &__block PHObjectPlaceholder *placeholder =
& &[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
& & & &placeholder = [PHAssetChangeRequest creationRequestForAssetFromImage:self.imageView.image].placeholderForCreatedA
& &} error:&error];
& &if (error) {
& & & &NSLog(@"保存失败");
& &// 获取自定义相册
& &PHAssetCollection *createdCollection = [self createCustomAssetCollection];
& &// 将图片保存到自定义相册
& & * 必须通过中间类,PHAssetCollectionChangeRequest 来完成
& & * 步骤:1.首先根据相册获取 PHAssetCollectionChangeRequest 对象
& & * & & &2.然后根据 PHAssetCollectionChangeRequest 来添加图片
& & * 这一步的实现有两个思路:1.通过上面的占位 asset 的标识来获取 相机胶卷中的 asset
& & * & & & & & & & & & & & 然后,将 asset 添加到 request 中
& & * & & & & & & & & & & 2.直接将 占位 asset 添加到 request 中去也是可行的
& &[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
& & & &PHAssetCollectionChangeRequest *request = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:createdCollection];
& & & &// [request addAssets:@[placeholder]]; 下面的方法可以将最新保存的图片设置为封面
& & & &[request insertAssets:@[placeholder] atIndexes:[NSIndexSet indexSetWithIndex:0]];
& &} error:&error];
& &if (error) {
& & & &NSLog(@"保存失败");
& &} else {
& & & &NSLog(@"保存成功");
最终代码:整理后可用于项目中
- (void)touchesBegan:(NSSet&UITouch *& *)touches withEvent:(UIEvent *)event
& &// 获取 当前 App 对 phots 的访问权限
& &PHAuthorizationStatus OldStatus = [PHPhotoLibrary authorizationStatus];
& &// 检查访问权限 当前 App 对相册的检查权限
& & * PHAuthorizationStatus
& & * PHAuthorizationStatusNotDetermined = 0, 用户还未决定
& & * PHAuthorizationStatusRestricted, & & & &系统限制,不允许访问相册 比如家长模式
& & * PHAuthorizationStatusDenied, & & & & & &用户不允许访问
& & * PHAuthorizationStatusAuthorized & & & & 用户可以访问
& & * 如果之前已经选择过,会直接执行 block,并且把以前的状态传给你
& & * 如果之前没有选择过,会弹框,在用户选择后调用 block 并且把用户的选择告诉你
& & * 注意:该方法的 block 在子线程中运行 因此,弹框什么的需要回到主线程执行
& &[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
& & & &dispatch_async(dispatch_get_main_queue(), ^{
& & & & & &if (status == PHAuthorizationStatusAuthorized) {
& & & & & & & &// & & & & & &[self cSaveToCameraRoll];
& & & & & & & &// & & & & & &[self photoSaveToCameraRoll];
& & & & & & & &// & & & & & &[self fetchCameraRoll];
& & & & & & & &// & & & & & &[self createCustomAssetCollection];
& & & & & & & &// & & & & & &[self createdAsset];
& & & & & & & &// & & & & & &[self saveImageToCustomAlbum2];
& & & & & & & &[self saveImageToCustomAlbum1];
& & & & & &} else if (OldStatus != PHAuthorizationStatusNotDetermined && status == PHAuthorizationStatusDenied) {
& & & & & & & &// 用户上一次选择了不允许访问 且 这次又点击了保存 这里可以适当提醒用户允许访问相册
& & & & & &}
& & & &});
#pragma mark - 将图片保存到自定义相册中 第一种写法 比较规范
#pragma mark -
- (void)saveImageToCustomAlbum1
& &// 获取保存到相机胶卷中的图片
& &PHAsset *createdAsset = [self createdAssets].firstO
& &if (createdAsset == nil) {
& & & &NSLog(@"保存图片失败");
& &// 获取自定义相册
& &PHAssetCollection *createdCollection = [self createCustomAssetCollection];
& &if (createdCollection == nil) {
& & & &NSLog(@"创建相册失败");
& &NSError *error =
& &// 将图片保存到自定义相册
& & * 必须通过中间类,PHAssetCollectionChangeRequest 来完成
& & * 步骤:1.首先根据相册获取 PHAssetCollectionChangeRequest 对象
& & * & & &2.然后根据 PHAssetCollectionChangeRequest 来添加图片
& & * 这一步的实现有两个思路:1.通过上面的占位 asset 的标识来获取 相机胶卷中的 asset
& & * & & & & & & & & & & & 然后,将 asset 添加到 request 中
& & * & & & & & & & & & & 2.直接将 占位 asset 添加到 request 中去也是可行的
& &[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
& & & &PHAssetCollectionChangeRequest *request = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:createdCollection];
& & & &// & & & &[request addAssets:@[placeholder]];
& & & &[request insertAssets:@[createdAsset] atIndexes:[NSIndexSet indexSetWithIndex:0]];
& &} error:&error];
& &if (error) {
& & & &NSLog(@"保存失败");
& &} else {
& & & &NSLog(@"保存成功");
#pragma mark - 获取保存到【相机胶卷】的图片
#pragma mark -
- (PHFetchResult&PHAsset *& *)createdAssets
& &// 将图片保存到相机胶卷
& &NSError *error =
& &__block NSString *assetID =
& &[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
& & & &assetID = [PHAssetChangeRequest creationRequestForAssetFromImage:self.imageView.image].placeholderForCreatedAsset.localI
& &} error:&error];
& &if (error)
& &return [PHAsset fetchAssetsWithLocalIdentifiers:@[assetID] options:nil];
#pragma mark - 使用 photo 框架创建自定义名称的相册 并获取自定义到自定义相册
#pragma mark -
- (PHAssetCollection *)createCustomAssetCollection
& &// 获取 app 名称
& &NSString *title = [NSBundle mainBundle].infoDictionary[(NSString *)kCFBundleNameKey];
& &NSError *error =
& &// 查找 app 中是否有该相册 如果已经有了 就不再创建
& & * & & 参数一 枚举:
& & * & & PHAssetCollectionTypeAlbum & & &= 1, 用户自定义相册
& & * & & PHAssetCollectionTypeSmartAlbum = 2, 系统相册
& & * & & PHAssetCollectionTypeMoment & & = 3, 按时间排序的相册
& & * & & 参数二 枚举:PHAssetCollectionSubtype
& & * & & 参数二的枚举有非常多,但是可以根据识别单词来找出我们想要的。
& & * & & 比如:PHAssetCollectionTypeSmartAlbum 系统相册 PHAssetCollectionSubtypeSmartAlbumUserLibrary 用户相册 就能获取到相机胶卷
& & * & & PHAssetCollectionSubtypeAlbumRegular 常规相册
& &PHFetchResult&PHAssetCollection *& *result = [PHAssetCollection fetchAssetCollectionsWithType:(PHAssetCollectionTypeAlbum)
& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & &subtype:(PHAssetCollectionSubtypeAlbumRegular)
& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & &options:nil];
& &for (PHAssetCollection *collection in result) {
& & & &if ([collection.localizedTitle isEqualToString:title]) { // 说明 app 中存在该相册
& & & & & &
& &/** 来到这里说明相册不存在 需要创建相册 **/
& &__block NSString *createdCustomAssetCollectionIdentifier =
& &// 创建和 app 名称一样的 相册
& & * 注意:这个方法只是告诉 photos 我要创建一个相册,并没有真的创建
& & * & & &必须等到 performChangesAndWait block 执行完毕后才会
& & * & & &真的创建相册。
& &[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
& & & &PHAssetCollectionChangeRequest *collectionChangeRequest = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title];
& & & &/**
& & & & * collectionChangeRequest 即使我们告诉 photos 要创建相册,但是此时还没有
& & & & * 创建相册,因此现在我们并不能拿到所创建的相册,我们的需求是:将图片保存到
& & & & * 自定义的相册中,因此我们需要拿到自己创建的相册,从头文件可以看出,collectionChangeRequest
& & & & * 中有一个占位相册,placeholderForCreatedAssetCollection ,这个占位相册
& & & & * 虽然不是我们所创建的,但是其 identifier 和我们所创建的自定义相册的 identifier
& & & & * 是相同的。所以想要拿到我们自定义的相册,必须保存这个 identifier,等 photos app
& & & & * 创建完成后通过 identifier 来拿到我们自定义的相册
& & & & */
& & & &createdCustomAssetCollectionIdentifier = collectionChangeRequest.placeholderForCreatedAssetCollection.localI
& &} error:&error];
& &// 这里 block 结束了,因此相册也创建完毕了
& &if (error)
& &return [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[createdCustomAssetCollectionIdentifier] options:nil].firstO
从相册中选取图片
从相册里面选择图片到 App 中
选择单张图片
& &UIImagePickerController
& &AssetsLibrary 框架
& &Photos 框架
选择多张图片(图片数量 &= 2)
& &AssetsLibrary 框架
& &Photos 框架
利用照相机拍一张照片到 App
使用 UIImagePickerController (界面已经写好了)
AVCaptureSession (AVFoundation框架下)
使用第三方框架获取多张照片
这里推荐大家使用 CTAssetsPickerController 第三方框架。
地址如下:CTAssetsPickerController
/chiunam/CTAssetsPickerController
如果您的项目是使用 pod 来管理第三方库的,直接pod &CTAssetsPickerController& 就可以了。其内部还依赖一个叫做 PureLayout 的库。
具体信息见代码:多图片访问
/lizhaoLoveIT/assetPhotoPicker
文/Ammar(简书作者)原文链接:/p/091e0198ae61
阅读(...) 评论()

我要回帖

更多关于 ios textview占位符 的文章

 

随机推荐