YYKit : 一组功能强大的iOS组件集合,支持iOS6.0及以上。
各组件之间有比较强的依赖关系,但原作者为了方便其他开发者使用,已将其拆分成以下独立组件。
YYModel — 高性能的 iOS JSON 模型框架。
YYCache — 高性能的 iOS 缓存框架。
YYImage — 功能强大的 iOS 图像框架。
YYWebImage — 高性能的 iOS 异步图像加载框架。
YYText — 功能强大的 iOS 富文本框架。
YYKeyboardManager — iOS 键盘监听管理工具
YYDispatchQueuePool — iOS 全局并发队列管理工具
YYAsyncLayer — iOS 异步绘制与显示的工具
YYCategories — 功能丰富的 Category 类型工具库
集成可使用Cocoapods或Carthage或手动安装
CocoaPods
- 在 Podfile 中添加 pod ‘YYKit’
- 执行 pod install 或 pod update
- 导入
<YYKit/YYKit.h>
Carthage
- 在 Cartfile 中添加 github “ibireme/YYKit”
- 执行 carthage update –platform ios 并将生成的 framework 添加到你的工程
- 导入
<YYKit/YYKit.h>
- 注意: carthage framework 并没有包含 webp 组件。如果你需要支持 webp,可以用 CocoaPods 安装,或者手动安装
手动安装
- 下载 YYKit 文件夹内的所有内容
- 将 YYKit 内的源文件添加(拖放)到你的工程
- 为 NSObject+YYAddForARC.m 和 NSThread+YYAdd.m 添加编译参数 -fno-objc-arc
- 链接以下 frameworks:
- UIKit
- CoreFoundation
- CoreText
- CoreGraphics
- CoreImage
- QuartzCore
- ImageIO
- AssetsLibrary
- Accelerate
- MobileCoreServices
- SystemConfiguration
- sqlite3
- libz
- 如果你需要支持 WebP,可以将 Vendor/WebP.framework(静态库) 加入你的工程
- 导入
YYModel.h
提到的WebP
是Google
新推出的影像技术,它可让网页 图档有效进行压缩,同时又不影响图片格式、兼容与实际清晰度,进而让整体网页下载速度加快。与JPEG
相同,WebP
是一种“有损压缩“,利用”预测编码“技术。但谷歌表示,这种格式的主要优势在于高效率。他们发现,“在质量相同的情况下,WebP
格式图像的体积要比JPEG
格式图像小40%。
更详细的使用文档可到CocoaDocs查看
这是作者使用YYKit提供的项目中的使用技巧。
注意:原作者并不建议直接使用YYKit
这个库,而是根据需求单独使用这些组件
接下来分别探究下各个组件
YYModel
安装
CocoaPods
- 在
Podfile
中添加pod 'YYModel'
- 执行
pod install
或pod update
- 导入
<YYModel/YYModel.h>
Carthage
- 在
Cartfile
中添加github "ibireme/YYModel"
- 执行
carthage update --platform ios
并将生成的framework
添加到你的工程- 导入
<YYModel/YYModel.h>
手动安装
- 下载 YYModel 文件夹内的所有内容
- 将 YYModel 内的源文件添加(拖放)到你的工程
- 导入 YYModel.h
实现原理
使用OC运行时函数将模型类进行解析,包括所有的属性、方法、实例变量等,然后将模型按照名字进行索引调用相应的set方法,模型类通常是固定的,并不用对每次转换的类进行解析,利用缓存机制,每个模型类只用解析一次,固性能会很高。
提供的演示Demo地址: https://github.com/ibireme/YYModel
使用了六种模型转换方法来对比各自的性能。分别是
- 手动转换、
- YYModel、
- FastEasyMapping、
- JSONModel、
- Mantle、
- MJExtension.
除了手动转换外其余均使用了第三方的开源库,我个人之前常用的是手动转换和MJExtension
手动转换一般是这样
也就是对象之间的映射手动完成。上图也列举了系统的这个方法setValuesForKeysWithDictionary
,这个方法用起来也还不错,不需要一一的来给对象赋值而直接从字典初始化即可,但用的不好会经常崩溃。
举个例子
创建PersonInfoModel
@interface PersonInfoModel : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *age;
@property (nonatomic, strong) NSString *address;
@end
PersonInfoModel *personInfoModel = [[PersonInfoModel alloc]init];
[personInfoModel setValuesForKeysWithDictionary:dic];
这是比较标准的使用方法,使用时完全没问题。如果我在`PersonInfoModel中再加一个属性
这样也没有出错,可以正常使用,也就是说用字典初始化对象时,只要对象中都包含了这些键值,是可以正常初始化的,我们再在字典中添加一个键值对
这样就会直接导致程序崩溃,因为该对象中没有 sex 这个属性,解决方法就是,实现一个方法setValue:forUndefinedKey:,然后实现这个方法,这样就会过滤掉给不存在的键值赋值。
如果有个属性是id,而id本身就是系统自身关键字,不能够当做属性使用,这时可以这么做。
setValue:forUndefinedKey:这个方法是关键,只有存在这个方法后,才可以过滤掉不存在的键值对而防止崩溃。在项目中使用时可以创建一个Model基类,添加这个方法setValue:forUndefinedKey:
并实现。之后的Model继承自这个基类Model,这时候如果存在model中没有的键,可以重载父类的setValue:forUndefinedKey方法即可,否则会崩溃。
另外,程序在获取Json数据的时候可能会出现这种数据 "somevalue": null
,也就是没有返回值,通过一些第三方的库可能会解析成这样 somevalue = "<null>"
;这种数据不是nil也不是string,如果向这个对象发送消息就会崩溃。
在AFNetworking中有这个方法可以解决,将这个空值去除
AFJSONResponseSerializer *responseSerializer = [[AFJSONResponseSerializer alloc] init];
responseSerializer.removesKeysWithNullValues = true;
而网上有个Category
,叫做NullSafe
,下载地址
https://github.com/nicklockwood/NullSafe
是在运行时操作把空值置为nil,因为nil是安全的,可以向nil对象发送消息不会奔溃,只需将这个category加入项目即可。
作者给出了这几种开源库的比较结果,YYModel的性能仅次于手动转换。
YYModel的优势
- 高性能: 模型转换性能接近手写解析代码。
- 自动类型转换: 对象类型可以自动转换,详情见下方表格。
- 类型安全: 转换过程中,所有的数据类型都会被检测一遍,以保证类型安全,避免崩溃问题。
- 无侵入性: 模型无需继承自其他基类。
- 轻量: 该框架只有 5 个文件 (包括.h文件)。
- 文档和单元测试: 文档覆盖率100%, 代码覆盖率99.6%。
部分使用方法
简单的 Model 与 JSON 相互转换
JSON
{
"uid":123456,
"name":"Harry",
"created":"1965-07-31T00:00:00+0000"
}
Model
@interface User : NSObject
@property UInt64 uid;
@property NSString *name;
@property NSDate *created;
@end
// 将 JSON (NSData,NSString,NSDictionary) 转换为 Model:
User *user = [User yy_modelWithJSON:json];
// 将 Model 转换为 JSON 对象:
NSDictionary *json = [user yy_modelToJSONObject];
当 JSON/Dictionary 中的对象类型与 Model 属性不一致时,YYModel 将会进行如下自动转换。自动转换不支持的值将会被忽略,以避免各种潜在的崩溃问题。
将 Model 的属性匹配到指定的 JSON/NSDictionary 键值
JSON
:
{
"n":"Harry Pottery",
"p": 256,
"ext" : {
"desc" : "A book written by J.K.Rowing."
}
}
Model:
@interface Book : NSObject
@property NSString *name;
@property NSInteger page;
@property NSString *desc;
@end
`@implementation Book
+ (NSDictionary *)modelCustomPropertyMapper {
return @{@"name" : @"n",
@"page" : @"p",
@"desc" : @"ext.desc"};
}
@end
通过实现 协议中的 modelCustomPropertyMapper,可以将 Model 属性的名字对应到 JSON/NSDictionary 相应的字段。可以把一个或一组 json key (key path) 映射到一个或多个属性。如果一个属性没有映射关系,那默认会使用相同属性名作为映射。
在 json->model 的过程中:如果一个属性对应了多个 json key,那么转换过程会按顺序查找,并使用第一个不为空的值。
在 model->json 的过程中:如果一个属性对应了多个 json key (key path),那么转换过程仅会处理第一个 json key (key path);如果多个属性对应了同一个 json key,则转换过过程会使用其中任意一个不为空的值。
Model 包含其他 Model
JSON
{
"author":{
"name":"J.K.Rowling",
"birthday":"1965-07-31T00:00:00+0000"
},
"name":"Harry Potter",
"pages":256
}
Model
: 什么都不用做,转换会自动完成
@interface Author : NSObject
@property NSString *name;
@property NSDate *birthday;
@end
@interface Book : NSObject
@property NSString *name;
@property NSUInteger pages;
@property Author *author;
//Book 包含 Author 属性
@end
注意,Book中的属性author
必须和Json串中键author
相同。
容器类属性
@class Shadow, Border, Attachment;
@interface Attributes
@property NSString *name;
@property NSArray *shadows; //Array<Shadow>
@property NSSet *borders; //Set<Border>
@property NSMutableDictionary *attachments; //Dict<NSString,Attachment>
@end
@implementation Attributes
// 返回容器类中的所需要存放的数据类型 (以 Class 或 Class Name 的形式)。
+ (NSDictionary *)modelContainerPropertyGenericClass {
return @{@"shadows" : [Shadow class],
@"borders" : Border.class,
@"attachments" : @"Attachment" };
}
@end
黑名单与白名单
@interface User
@property NSString *name;
@property NSUInteger age;
@end
@implementation Attributes
// 如果实现了该方法,则处理过程中会忽略该列表内的所有属性
+ (NSArray *)modelPropertyBlacklist {
return @[@"test1", @"test2"];
}
// 如果实现了该方法,则处理过程中不会处理该列表外的属性。
+ (NSArray *)modelPropertyWhitelist {
return @[@"name"];
}
@end
如果同时实现modelPropertyBlacklist
方法和modelPropertyWhitelist
方法,且忽略和处理属性相同, 则所有属性都不会有值。
iOS JSON 模型转换库评测 这篇文章作者对比了几个库的优劣,可以看看
YYCache
安装
CocoaPods
- 在
Podfile
中添加pod 'YYCache'
- 执行
pod install
或pod update
- 导入
<YYCache/YYCache.h>
Carthage
- 在
Cartfile
中添加github "ibireme/YYCache"
- 执行
carthage update --platform ios
并将生成的framework
添加到你的工程- 导入
<YYCache/YYCache.h>
手动安装
下载
YYCache
文件夹内的所有内容将
YYCache
内的源文件添加(拖放)到你的工程链接以下的
frameworks
:
- UIKit
- CoreFoundation
- QuartzCore
- sqlite3
4.导入
YYCache.h
提供的演示Demo地址: https://github.com/ibireme/YYCache
通常一个缓存是由内存缓存和磁盘缓存组成,内存缓存提供容量小但高速的存取功能,磁盘缓存提供大容量但低速的持久化存储.
作者比较了三个第三方的开源库YYCache
、PINCache
、TMCache
。内存缓存方面分别比较了
- NSDictionary
- NSDict+Lock
- YYMemoryCache
- NSCache
- PINMemoryCache
- TMMemoryCachee
得出的性能结果如下
上图TMMemoryCache的测试结果因为性能太差并没有显示出来。
磁盘缓存的实现技术大致分为
- 基于文件读写
- 基于mmap文件内存映射
- 基于数据库
TMDiskCache, PINDiskCache, SDWebImage 等缓存,都是基于文件系统的,即一个 Value 对应一个文件,通过文件读写来缓存数据。
FastImageCache 采用的是 mmap 将文件映射到内存。
NSURLCache、FBDiskCache 都是基于 SQLite 数据库的。SQLite 写入性能比直接写文件要高,但读取性能取决于数据大小:当单条数据小于 20K 时,数据越小 SQLite 读取性能越高;单条数据大于 20K 时,直接写为文件速度会更快一些。
所以磁盘缓存最好是把 SQLite 和文件存储结合起来:key-value 元数据保存在 SQLite 中,而 value 数据则根据大小不同选择 SQLite 或文件存储。YYDiskCache 就是采用的 SQLite 配合文件的存储方式,参数inlineThreshold,默认20KB,小于它存数据库,大于它存文件。
作者对比了YYDiskCache
、PINDiskCache
、TMDiskCache
三种磁盘存储方式,得出的性能结果如下
YYCache
的优势包括
- LRU: 缓存支持 LRU (least-recently-used) 淘汰算法。
- 缓存控制: 支持多种缓存控制方法:总数量、总大小、存活时间、空闲空间。
- 兼容性: API 基本和 NSCache 保持一致, 所有方法都是线程安全的。
- 内存缓存
- 对象释放控制: 对象的释放(release) 可以配置为同步或异步进行,可以配置在主线程或后台线程进行。
- 自动清空: 当收到内存警告或 App 进入后台时,缓存可以配置为自动清空。
- 磁盘缓存
- 可定制性: 磁盘缓存支持自定义的归档解档方法,以支持那些没有实现 NSCoding 协议的对象。
- 存储类型控制: 磁盘缓存支持对每个对象的存储类型 (SQLite/文件) 进行自动或手动控制,以获得更高的存取性能。
部分方法使用
- (BOOL)containsObjectForKey:(NSString *)key;
返回一个布尔值,指示是否一个给定的关键是在缓存中。这种方法可能会阻塞调用线程,直到文件读取完成。
- (void)containsObjectForKey:(NSString *)key withBlock:(void ( ^ ) ( NSString *key , BOOL contains ))block
返回一个布尔值表示的块是否一个给定的关键字在缓存中。该方法立即返回,调用时在后台通过块队列操作完成。
- (instancetype)initWithPath:(NSString *)path
根据指定的名称创建一个新的实例。具有相同名称的多个实例将使缓存不稳定。
- (void)objectForKey:(NSString *)key withBlock:(void ( ^ ) ( NSString *key , id<NSCoding> object ))block
返回给定的键相关联的值。该方法立即返回,调用时在后台通过块队列操作完成。
- (void)removeObjectForKey:(NSString *)key withBlock:(void ( ^ ) ( NSString *key ))block
在缓存中移除指定键的值。该方法立即返回,调用时在后台通过块队列操作完成。
- (void)removeAllObjects
清空缓存。这种方法可能会阻塞调用线程,直到文件删除了。
- (void)removeAllObjectsWithBlock:(void(^)(void))block;
清空缓存。该方法立即返回,调用时在后台通过块队列操作完成。
YYCache 设计思路与技术细节 这篇文章作者讲述了部分设计思路和实现细节,可以看看
YYImage
安装
CocoaPods
- 将 cocoapods 更新至最新版本.
- 在 Podfile 中添加 pod ‘YYImage’
- 执行 pod install 或 pod update
- 导入
<YYImage/YYImage.h>
- 注意:pod 配置并没有包含 WebP 组件, 如果你需要支持 WebP,可以在 Podfile 中添加 pod ‘YYImage/WebP’。你可以调用 YYImageWebPAvailable() 来检查一下 WebP 组件是否被正确安装
Carthage
- 在 Cartfile 中添加 github “ibireme/YYImage”。
- 执行 carthage update –platform ios 并将生成的 framework 添加到你的工程。
- 导入
<YYImage/YYImage.h>
- 注意:carthage framework 并没有包含 WebP 组件。如果你需要支持 WebP,可以用 CocoaPods 安装,或者手动安装。
手动安装
- 下载 YYImage 文件夹内的所有内容
- 将 YYImage 内的源文件添加(拖放)到你的工程
3 . 链接以下 frameworks:
- UIKit
- CoreFoundation
- QuartzCore
- AssetsLibrary
- ImageIO
- Accelerate
- MobileCoreServices
- libz
4 . 导入
YYImage.h
5 . 注意:如果你需要支持 WebP,可以将 Vendor/WebP.framework(静态库) 加入你的工程。你可以调用 YYImageWebPAvailable() 来检查一下 WebP 组件是否被正确安装
提供的演示Demo地址: https://github.com/ibireme/YYImage
特性:
- 支持以下类型动画图像的播放/编码/解码:
- WebP, APNG, GIF。
- 支持以下类型静态图像的显示/编码/解码:
- WebP, PNG, GIF, JPEG, JP2, TIFF, BMP, ICO, ICNS。
- 支持以下类型图片的渐进式/逐行扫描/隔行扫描解码:
*PNG, GIF, JPEG, BMP。 - 支持多张图片构成的帧动画播放,支持单张图片的 sprite sheet 动画。
- 高效的动态内存缓存管理,以保证高性能低内存的动画播放。
- 完全兼容 UIImage 和 UIImageView,使用方便。
- 保留可扩展的接口,以支持自定义动画。
- 每个类和方法都有完善的文档注释。
图片本身有 3 种常见的编码方式
第一种baseline,即逐行扫描。默认情况下JPEG、PNG、GIF 都是这种保存方式
第二种interaced,即隔行扫描。PNG 和 GIF 在保存时可以选择这种格式
第三种是progressive,即渐进式。JPEG 在保存时可以选择这种方式。
在下载图片时,首先用 CGImageSourceCreateIncremental(NULL)
创建一个空的图片源,随后在获得新数据时调用CGImageSourceUpdateData(data, false)
来更新图片源,最后在用 CGImageSourceCreateImageAtIndex()
创建图片来显示。
部分方法使用
显示动画类型的图片
UIImage *image = [YYImage imageNamed:@"ani.gif"];
UIImageView *imageView = [[YYAnimatedImageView alloc]initWithImage:image];
[self.view addSubView:imageView];
播放帧动画
NSArray *paths = @[@"/ani/frame1.png", @"/ani/frame2.png", @"/ani/frame3.png"];
NSArray *times = @[@0.1, @0.2, @0.1];
UIImage *image = [YYFrameImage alloc] initWithImagePaths:paths frameDurations:times repeats:YES];
UIImageView *imageView = [YYAnimatedImageView alloc]
initWithImage:image];
[self.view addSubView:imageView];
播放 sprite sheet 动画
UIImage *spriteSheet = [UIImage imageNamed:@"sprite-sheet"];
NSMutableArray *contentRects = [NSMutableArray new];
NSMutableArray *durations = [NSMutableArray new];
for (int j = 0; j < 12; j++) {
for (int i = 0; i < 8; i++) {
CGRect rect;
rect.size = CGSizeMake(img.size.width / 8, img.size.height / 12);
rect.origin.x = img.size.width / 8 * i;
rect.origin.y = img.size.height / 12 * j;
[contentRects addObject:[NSValue valueWithCGRect:rect]];
[durations addObject:@(1 / 60.0)];
}
}
YYSpriteSheetImage *sprite;
sprite = [[YYSpriteSheetImage alloc] initWithSpriteSheetImage:img
contentRects:contentRects
frameDurations:durations
loopCount:0];
YYAnimatedImageView *imageView = [YYAnimatedImageView new];
imageView.size = CGSizeMake(img.size.width / 8, img.size.height / 12);
imageView.image = sprite;
[self.view addSubView:imageView];
动画播放控制
YYAnimatedImageView *imageView = ...;
// 暂停:
[imageView stopAnimating];
// 播放:
[imageView startAnimating];
// 设置播放进度:
imageView.currentAnimatedImageIndex = 12;
// 获取播放状态:
image.currentIsPlayingAnimation;
图片解码
// 解码单帧图片:
NSData *data = [NSData dataWithContentOfFile:@"/tmp/image.webp"];
YYImageDecoder *decoder = [YYImageDecoder decoderWithData:data scale:2.0];
UIImage image = [decoder frameAtIndex:0 decodeForDisplay:YES].image;
// 渐进式图片解码 (可用于图片下载显示):
NSMutableData *data = [NSMutableData new];
YYImageDecoder *decoder = [[YYImageDecoder alloc] initWithScale:2.0];
while(newDataArrived) {
[data appendData:newData];
[decoder updateData:data final:NO];
if (decoder.frameCount > 0) {
`` UIImage image = [decoder frameAtIndex:0 decodeForDisplay:YES].image;``
// progressive display...
}
}
[decoder updateData:data final:YES];
UIImage image = [decoder frameAtIndex:0 decodeForDisplay:YES].image;
// final display...
图片编码
// 编码静态图 (支持各种常见图片格式):
YYImageEncoder *jpegEncoder = [[YYImageEncoder alloc] initWithType:YYImageTypeJPEG];
jpegEncoder.quality = 0.9;
[jpegEncoder addImage:image duration:0];
NSData jpegData = [jpegEncoder encode];
// 编码动态图 (支持 GIF/APNG/WebP):
YYImageEncoder *webpEncoder = [[YYImageEncoder alloc] initWithType:YYImageTypeWebP];
webpEncoder.loopCount = 5;
[webpEncoder addImage:image0 duration:0.1];
[webpEncoder addImage:image1 duration:0.15];
[webpEncoder addImage:image2 duration:0.2];
NSData webpData = [webpEncoder encode];
图片类型探测
// 获取图片类型
YYImageType type = YYImageDetectType(data);
if (type == YYImageTypePNG) ...
Demo展示效果如下
这两篇文章是作者的相关解读。
YYWebImage
安装
CocoaPods
- 将 cocoapods 更新至最新版本
- 在 Podfile 中添加 pod ‘YYWebImage’
- 执行 pod install 或 pod update
- 导入
<YYWebImage/YYWebImage.h>
- 注意:pod 配置并没有包含 WebP 组件, 如果你需要支持 WebP,可以在 Podfile 中添加 pod ‘YYImage/WebP’。你可以调用 YYImageWebPAvailable() 来检查一下 WebP 组件是否被正确安装
Carthage
- 在 Cartfile 中添加 github “ibireme/YYWebImage”
- 执行 carthage update –platform ios 并将生成的 framework 添加到你的工程。
- 导入
<YYWebImage/YYWebImage.h>
- 注意: carthage framework 并没有包含 webp 组件。如果你需要支持 WebP,可以用 CocoaPods 安装,或者手动安装
手动安装
- 下载 YYWebImage 文件夹内的所有内容。
- 将 YYWebImage 内的源文件添加(拖放)到你的工程。
- 链接以下 frameworks:
- UIKit
- CoreFoundation
- QuartzCore
- AssetsLibrary
- ImageIO
- Accelerate
- MobileCoreServices
- sqlite3
- libz
4.导入 YYWebImage.h。
5.注意:如果你需要支持 WebP,可以将 Vendor/WebP.framework(静态库) 加入你的工程。你可以调用 YYImageWebPAvailable() 来检查一下 WebP 组件是否被正确安装
提供的Demo演示地址: https://github.com/ibireme/YYWebImage
YYWebImage是一个异步图片加载框架,目的是为了试图替代SDWebImage
、PINRemoteImage
、FLAnimatedImage
等开源框架。支持这些开源框架的大部分功能,同时增加了大量新特性、并且有不小的性能提升。其底层用 YYCache 实现了内存和磁盘缓存, 用 YYImage 实现了 WebP/APNG/GIF 动图的解码和播放。
相关特性
- 异步的图片加载,支持 HTTP 和本地文件。
- 支持 GIF、APNG、WebP 动画(动态缓存,低内存占用)。
- 支持逐行扫描、隔行扫描、渐进式图像加载。
- UIImageView、UIButton、MKAnnotationView、CALayer 的 Category 方法支持。
- 常见图片处理:模糊、圆角、大小调整、裁切、旋转、色调等。
- 高性能的内存和磁盘缓存。
- 高性能的图片设置方式,以避免主线程阻塞。
- 每个类和方法都有完善的文档注释。
部分方法使用
从 URL 加载图片
// 加载网络图片
imageView.yy_imageURL = [NSURL URLWithString:@"http://github.com/logo.png"];
// 加载本地图片
imageView.yy_imageURL = [NSURL fileURLWithPath:@"/tmp/logo.png"];
加载动图
// 只需要把 UIImageView
替换为 YYAnimatedImageView
即可。
UIImageView *imageView = [YYAnimatedImageView new];
imageView.yy_imageURL = [NSURL URLWithString:@"http://github.com/ani.webp"];
渐进式图片加载
// 渐进式:边下载边显示
- [imageView yy_setImageWithURL:url options:YYWebImageOptionProgressive];
// 渐进式加载,增加模糊效果和渐变动画
- [imageView yy_setImageWithURL:url options:YYWebImageOptionProgressiveBlur | YYWebImageOptionSetImageWithFadeAnimation];
加载、处理图片
- 下载图片
- 获得图片下载进度
- 调整图片大小、加圆角
- 显示图片时增加一个淡入动画,以获得更好的用户体验
[imageView yy_setImageWithURL:url
placeholder:nil
options:YYWebImageOptionSetImageWithFadeAnimation
progress:^(NSInteger receivedSize, NSInteger expectedSize) {
progress = (float)receivedSize / expectedSize;
}
transform:^UIImage *(UIImage *image, NSURL *url) {
image = [image yy_imageByResizeToSize:CGSizeMake(100, 100) contentMode:UIViewContentModeCenter];
return [image yy_imageByRoundCornerRadius:10];
}
completion:^(UIImage *image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error) {
if (from == YYWebImageFromDiskCache) {
NSLog(@"load from disk cache");
}
}];
图片缓存
YYImageCache *cache = [YYWebImageManager sharedManager].cache;
// 获取缓存大小
cache.memoryCache.totalCost;
cache.memoryCache.totalCount;
cache.diskCache.totalCost;
cache.diskCache.totalCount;
// 清空缓存
[cache.memoryCache removeAllObjects];
[cache.diskCache removeAllObjects];
// 清空磁盘缓存,带进度回调
[cache.diskCache removeAllObjectsWithProgressBlock:^(int
removedCount, int totalCount) {
// progress
} endBlock:^(BOOL error) {
// end
}];
YYText
安装
CocoaPods
- 在 Podfile 中添加 pod ‘YYText’
- 执行 pod install 或 pod update
- 导入
<YYText/YYText.h>
Carthage
- 在 Cartfile 中添加 github “ibireme/YYText”
- 执行 carthage update –platform ios 并将生成的 framework 添加到你的工程
- 导入
<YYText/YYText.h>
手动安装
- 下载 YYText 文件夹内的所有内容
- 将 YYText 内的源文件添加(拖放)到你的工程
- 链接以下 frameworks:
- UIKit
- CoreFoundation
- CoreText
- QuartzCore
- Accelerate
- MobileCoreServices
- 导入 YYText.h
提供Demo地址:https://github.com/ibireme/YYText
YYText是功能强大的富文本编辑与显示框架
相关特性
- API 兼容 UILabel 和 UITextView
- 支持高性能的异步排版和渲染
- 扩展了 CoreText 的属性以支持更多文字效果
- 支持 UIImage、UIView、CALayer 作为图文混排元素
- 支持添加自定义样式的、可点击的文本高亮范围
- 支持自定义文本解析 (内置简单的 Markdown/表情解析)
- 支持文本容器路径、内部留空路径的控制
- 支持文字竖排版,可用于编辑和显示中日韩文本
- 支持图片和富文本的复制粘贴
- 文本编辑时,支持富文本占位符
- 支持自定义键盘视图
- 撤销和重做次数的控制
- 富文本的序列化与反序列化支持
- 支持多语言,支持 VoiceOver
- 支持 Interface Builder
- 全部代码都有文档注释
已知问题
- YYText 并不能支持所有 CoreText/TextKit 的属性,比如 NSBackgroundColor、NSStrikethrough、NSUnderline、NSAttachment、NSLink 等,但 YYText 中基本都有对应属性作为替代。
- YYTextView 未实现局部刷新,所以在输入和编辑大量的文本(比如超过大概五千个汉字、或大概一万个英文字符)时会出现较明显的卡顿现象。
- 竖排版时,添加 exclusionPaths 在少数情况下可能会导致文本显示空白。
- 当添加了非矩形的 textContainerPath,并且有嵌入大于文本排版方向宽度的 RunDelegate 时,RunDelegate 之后的文字会无法显示。这是 CoreText 的 Bug(或者说是 Feature)。
部分效果图
部分使用方法
YYKeyboardManager
安装
CocoaPods
- 在 Podfile 中添加 pod ‘YYKeyboardManager’
- 执行 pod install 或 pod update
- 导入
<YYKeyboardManager/YYKeyboardManager.h>
Carthage
- 在 Cartfile 中添加 github “ibireme/YYKeyboardManager”
- 执行 carthage update –platform ios 并将生成的 framework 添加到你的工程
- 导入
<YYKeyboardManager/YYKeyboardManager.h>
手动安装
- 下载 YYKeyboardManager 文件夹内的所有内容
- 将 YYKeyboardManager 内的源文件添加(拖放)到你的工程
- 导入 YYKeyboardManager.h
提供的Demo地址:https://github.com/ibireme/YYKeyboardManager
YYKeyboardManager是一个iOS键盘监听管理工具类。兼容 iPhone / iPad / iPod,兼容 iOS 6 / 7 / 8 / 9, 并且能很好的处理屏幕旋转。我之前一直使用的监听键盘工具主要是TPKeyboardAvoiding、IQKeyboardManager和自己写的一个工具类,大体可以满足需求。
使用方法
YYDispatchQueuePool
安装
CocoaPods
- 在 Podfile 中添加 pod ‘YYDispatchQueuePool’
- 执行 pod install 或 pod update
- 导入
<YYDispatchQueuePool/YYDispatchQueuePool.h>
Carthage
- 在 Cartfile 中添加 github “ibireme/YYDispatchQueuePool”
- 执行 carthage update –platform ios 并将生成的 framework 添加到你的工程
- 导入
<YYDispatchQueuePool/YYDispatchQueuePool.h>
手动安装
- 下载 YYDispatchQueuePool 文件夹内的所有内容
- 将 YYDispatchQueuePool 内的源文件添加(拖放)到你的工程
- 导入 YYDispatchQueuePool.h
YYDispatchQueuePool是iOS全局并发队列管理工具。
提供的下载地址: https://github.com/ibireme/YYDispatchQueuePool
使用方法
// 从全局的 queue pool 中获取一个 queue
dispatch_queue_t queue = YYDispatchQueueGetForQOS(NSQualityOfServiceUtility);
// 创建一个新的 serial queue pool
YYDispatchQueuePool *pool = [[YYDispatchQueuePool alloc] initWithName:@"file.read" queueCount:5 qos:NSQualityOfServiceBackground];
dispatch_queue_t queue = [pool queue];
YYAsyncLayer
安装
CocoaPods
- 在 Podfile 中添加 pod ‘YYAsyncLayer’
- 执行 pod install 或 pod update
- 导入
<YYAsyncLayer/YYAsyncLayer.h>
Carthage
- 在 Cartfile 中添加 github “ibireme/YYAsyncLayer”。
- 执行 carthage update –platform ios 并将生成的 framework 添加到你的工程。
- 导入
<YYAsyncLayer/YYAsyncLayer.h>
手动安装
- 下载 YYAsyncLayer 文件夹内的所有内容。
- 将 YYAsyncLayer 内的源文件添加(拖放)到你的工程。
- 导入 YYAsyncLayer.h。
YYAsyncLayer是iOS异步绘制与显示的工具类。
提供的下载地址: https://github.com/ibireme/YYAsyncLayer
简单使用方法
YYCategories
安装
CocoaPods
- 在 Podfile 中添加 pod ‘YYCategories’。
- 执行 pod install 或 pod update。
- 导入
<YYCategories/YYCategories.h>
######Carthage
- 在 Cartfile 中添加 github “ibireme/YYCategories”。
- 执行 carthage update –platform ios 并将生成的 framework 添加到你的工程。
- 导入
<YYCategories/YYCategories.h>
手动安装
- 下载 YYCategories 文件夹内的所有内容。
- 将 YYCategories 内的源文件添加(拖放)到你的工程。
- 为 NSObject+YYAddForARC.m 和 NSThread+YYAdd.m 添加编译参数 -fno-objc-arc
- 链接以下 frameworks:
- UIKit
- CoreGraphics
- QuartzCore
- Accelerate
- ImageIO
- CoreText
- CoreFoundation
- libz
- 导入 YYCategories.h。
YYCategories是功能丰富的 Category 类型工具库。
提供的下载地址:https://github.com/ibireme/YYCategories
以上,YYDispatchQueuePool
和YYAsyncLayer
这两个工具类并没有花时间好好去研究,使用方法只是照搬过来,对于文中作者所讲的鉴于水平有限仍然有些疑惑,以后有时间再去研究。
YYKit包含的知识容量太过庞大,知识体系要求也更为全面,在研究之初对于文中的很多点并没有直观的认识,现在再去通读一遍感受也更为真切,更为深刻的认识只能在以后项目使用中再去体会!
如有任何疑问或问题请联系我:fishnewsdream@gmail.com,欢迎交流,共同提高!
Objective-C/Swift技术开发交流群201556264,讨论何种技术并不受限,欢迎各位大牛百家争鸣!
微信公众号OldDriverWeekly
,欢迎关注并提出宝贵意见
老司机iOS周报,欢迎关注或订阅
刚刚在线工作室,欢迎关注或提出建设性意见!
刚刚在线论坛, 欢迎踊跃提问或解答!
如有转载,请注明出处,谢谢!