YYKit探究


YYKit : 一组功能强大的iOS组件集合,支持iOS6.0及以上。

各组件之间有比较强的依赖关系,但原作者为了方便其他开发者使用,已将其拆分成以下独立组件。

集成可使用Cocoapods或Carthage或手动安装

CocoaPods
  1. 在 Podfile 中添加 pod ‘YYKit’
  2. 执行 pod install 或 pod update
  3. 导入<YYKit/YYKit.h>
Carthage
  1. 在 Cartfile 中添加 github “ibireme/YYKit”
  2. 执行 carthage update –platform ios 并将生成的 framework 添加到你的工程
  3. 导入 <YYKit/YYKit.h>
  4. 注意: carthage framework 并没有包含 webp 组件。如果你需要支持 webp,可以用 CocoaPods 安装,或者手动安装
手动安装
  1. 下载 YYKit 文件夹内的所有内容
  2. 将 YYKit 内的源文件添加(拖放)到你的工程
  3. 为 NSObject+YYAddForARC.m 和 NSThread+YYAdd.m 添加编译参数 -fno-objc-arc
  4. 链接以下 frameworks:
    • UIKit
    • CoreFoundation
    • CoreText
    • CoreGraphics
    • CoreImage
    • QuartzCore
    • ImageIO
    • AssetsLibrary
    • Accelerate
    • MobileCoreServices
    • SystemConfiguration
    • sqlite3
    • libz
  5. 如果你需要支持 WebP,可以将 Vendor/WebP.framework(静态库) 加入你的工程
  6. 导入 YYModel.h

提到的WebPGoogle新推出的影像技术,它可让网页 图档有效进行压缩,同时又不影响图片格式、兼容与实际清晰度,进而让整体网页下载速度加快。与JPEG相同,WebP是一种“有损压缩“,利用”预测编码“技术。但谷歌表示,这种格式的主要优势在于高效率。他们发现,“在质量相同的情况下,WebP格式图像的体积要比JPEG格式图像小40%。

更详细的使用文档可到CocoaDocs查看

iOS 保持界面流畅的技巧

这是作者使用YYKit提供的项目中的使用技巧。

注意:原作者并不建议直接使用YYKit这个库,而是根据需求单独使用这些组件

接下来分别探究下各个组件

YYModel

安装

CocoaPods
  1. Podfile 中添加 pod 'YYModel'
  2. 执行 pod installpod update
  3. 导入<YYModel/YYModel.h>
Carthage
  1. Cartfile 中添加 github "ibireme/YYModel"
  2. 执行 carthage update --platform ios 并将生成的 framework 添加到你的工程
  3. 导入<YYModel/YYModel.h>
手动安装
  1. 下载 YYModel 文件夹内的所有内容
  2. 将 YYModel 内的源文件添加(拖放)到你的工程
  3. 导入 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
  1. Podfile 中添加 pod 'YYCache'
  2. 执行 pod installpod update
  3. 导入 <YYCache/YYCache.h>
Carthage
  1. Cartfile 中添加 github "ibireme/YYCache"
  2. 执行 carthage update --platform ios 并将生成的 framework 添加到你的工程
  3. 导入 <YYCache/YYCache.h>
手动安装
  1. 下载 YYCache 文件夹内的所有内容

  2. YYCache 内的源文件添加(拖放)到你的工程

  3. 链接以下的 frameworks:

  • UIKit
  • CoreFoundation
  • QuartzCore
  • sqlite3

4.导入 YYCache.h

提供的演示Demo地址: https://github.com/ibireme/YYCache

通常一个缓存是由内存缓存和磁盘缓存组成,内存缓存提供容量小但高速的存取功能,磁盘缓存提供大容量但低速的持久化存储.

作者比较了三个第三方的开源库YYCachePINCacheTMCache。内存缓存方面分别比较了

  • 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,小于它存数据库,大于它存文件。

作者对比了YYDiskCachePINDiskCacheTMDiskCache三种磁盘存储方式,得出的性能结果如下

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
  1. 将 cocoapods 更新至最新版本.
  2. 在 Podfile 中添加 pod ‘YYImage’
  3. 执行 pod install 或 pod update
  4. 导入 <YYImage/YYImage.h>
  5. 注意:pod 配置并没有包含 WebP 组件, 如果你需要支持 WebP,可以在 Podfile 中添加 pod ‘YYImage/WebP’。你可以调用 YYImageWebPAvailable() 来检查一下 WebP 组件是否被正确安装
Carthage
  1. 在 Cartfile 中添加 github “ibireme/YYImage”。
  2. 执行 carthage update –platform ios 并将生成的 framework 添加到你的工程。
  3. 导入 <YYImage/YYImage.h>
  4. 注意:carthage framework 并没有包含 WebP 组件。如果你需要支持 WebP,可以用 CocoaPods 安装,或者手动安装。
手动安装
  1. 下载 YYImage 文件夹内的所有内容
  2. 将 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展示效果如下

移动端图片格式调研

iOS 处理图片的一些小 Tip

这两篇文章是作者的相关解读。

YYWebImage

安装

CocoaPods
  1. 将 cocoapods 更新至最新版本
  2. 在 Podfile 中添加 pod ‘YYWebImage’
  3. 执行 pod install 或 pod update
  4. 导入 <YYWebImage/YYWebImage.h>
  5. 注意:pod 配置并没有包含 WebP 组件, 如果你需要支持 WebP,可以在 Podfile 中添加 pod ‘YYImage/WebP’。你可以调用 YYImageWebPAvailable() 来检查一下 WebP 组件是否被正确安装
Carthage
  1. 在 Cartfile 中添加 github “ibireme/YYWebImage”
  2. 执行 carthage update –platform ios 并将生成的 framework 添加到你的工程。
  3. 导入 <YYWebImage/YYWebImage.h>
  4. 注意: carthage framework 并没有包含 webp 组件。如果你需要支持 WebP,可以用 CocoaPods 安装,或者手动安装
手动安装
  1. 下载 YYWebImage 文件夹内的所有内容。
  2. 将 YYWebImage 内的源文件添加(拖放)到你的工程。
  3. 链接以下 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是一个异步图片加载框架,目的是为了试图替代SDWebImagePINRemoteImageFLAnimatedImage 等开源框架。支持这些开源框架的大部分功能,同时增加了大量新特性、并且有不小的性能提升。其底层用 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];

加载、处理图片

    1. 下载图片
    1. 获得图片下载进度
    1. 调整图片大小、加圆角
    1. 显示图片时增加一个淡入动画,以获得更好的用户体验

[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
  1. 在 Podfile 中添加 pod ‘YYText’
  2. 执行 pod install 或 pod update
  3. 导入 <YYText/YYText.h>
Carthage
  1. 在 Cartfile 中添加 github “ibireme/YYText”
  2. 执行 carthage update –platform ios 并将生成的 framework 添加到你的工程
  3. 导入 <YYText/YYText.h>
手动安装
  1. 下载 YYText 文件夹内的所有内容
  2. 将 YYText 内的源文件添加(拖放)到你的工程
  3. 链接以下 frameworks:
    • UIKit
    • CoreFoundation
    • CoreText
    • QuartzCore
    • Accelerate
    • MobileCoreServices
  4. 导入 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
  1. 在 Podfile 中添加 pod ‘YYKeyboardManager’
  2. 执行 pod install 或 pod update
  3. 导入 <YYKeyboardManager/YYKeyboardManager.h>
Carthage
  1. 在 Cartfile 中添加 github “ibireme/YYKeyboardManager”
  2. 执行 carthage update –platform ios 并将生成的 framework 添加到你的工程
  3. 导入 <YYKeyboardManager/YYKeyboardManager.h>
手动安装
  1. 下载 YYKeyboardManager 文件夹内的所有内容
  2. 将 YYKeyboardManager 内的源文件添加(拖放)到你的工程
  3. 导入 YYKeyboardManager.h

提供的Demo地址:https://github.com/ibireme/YYKeyboardManager

YYKeyboardManager是一个iOS键盘监听管理工具类。兼容 iPhone / iPad / iPod,兼容 iOS 6 / 7 / 8 / 9, 并且能很好的处理屏幕旋转。我之前一直使用的监听键盘工具主要是TPKeyboardAvoiding、IQKeyboardManager和自己写的一个工具类,大体可以满足需求。

使用方法

YYDispatchQueuePool

安装
CocoaPods
  1. 在 Podfile 中添加 pod ‘YYDispatchQueuePool’
  2. 执行 pod install 或 pod update
  3. 导入 <YYDispatchQueuePool/YYDispatchQueuePool.h>
Carthage
  1. 在 Cartfile 中添加 github “ibireme/YYDispatchQueuePool”
  2. 执行 carthage update –platform ios 并将生成的 framework 添加到你的工程
  3. 导入 <YYDispatchQueuePool/YYDispatchQueuePool.h>
手动安装
  1. 下载 YYDispatchQueuePool 文件夹内的所有内容
  2. 将 YYDispatchQueuePool 内的源文件添加(拖放)到你的工程
  3. 导入 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
  1. 在 Podfile 中添加 pod ‘YYAsyncLayer’
  2. 执行 pod install 或 pod update
  3. 导入 <YYAsyncLayer/YYAsyncLayer.h>
Carthage
  1. 在 Cartfile 中添加 github “ibireme/YYAsyncLayer”。
  2. 执行 carthage update –platform ios 并将生成的 framework 添加到你的工程。
  3. 导入 <YYAsyncLayer/YYAsyncLayer.h>
手动安装
  1. 下载 YYAsyncLayer 文件夹内的所有内容。
  2. 将 YYAsyncLayer 内的源文件添加(拖放)到你的工程。
  3. 导入 YYAsyncLayer.h。

YYAsyncLayer是iOS异步绘制与显示的工具类。

提供的下载地址: https://github.com/ibireme/YYAsyncLayer

简单使用方法

YYCategories

安装

CocoaPods
  1. 在 Podfile 中添加 pod ‘YYCategories’。
  2. 执行 pod install 或 pod update。
  3. 导入 <YYCategories/YYCategories.h>

######Carthage

  1. 在 Cartfile 中添加 github “ibireme/YYCategories”。
  2. 执行 carthage update –platform ios 并将生成的 framework 添加到你的工程。
  3. 导入 <YYCategories/YYCategories.h>
手动安装
  1. 下载 YYCategories 文件夹内的所有内容。
  2. 将 YYCategories 内的源文件添加(拖放)到你的工程。
  3. 为 NSObject+YYAddForARC.m 和 NSThread+YYAdd.m 添加编译参数 -fno-objc-arc
  4. 链接以下 frameworks:
    • UIKit
    • CoreGraphics
    • QuartzCore
    • Accelerate
    • ImageIO
    • CoreText
    • CoreFoundation
    • libz
  5. 导入 YYCategories.h。

YYCategories是功能丰富的 Category 类型工具库。

提供的下载地址:https://github.com/ibireme/YYCategories


以上,YYDispatchQueuePoolYYAsyncLayer这两个工具类并没有花时间好好去研究,使用方法只是照搬过来,对于文中作者所讲的鉴于水平有限仍然有些疑惑,以后有时间再去研究。

YYKit包含的知识容量太过庞大,知识体系要求也更为全面,在研究之初对于文中的很多点并没有直观的认识,现在再去通读一遍感受也更为真切,更为深刻的认识只能在以后项目使用中再去体会!


如有任何疑问或问题请联系我:fishnewsdream@gmail.com,欢迎交流,共同提高!

Objective-C/Swift技术开发交流群201556264,讨论何种技术并不受限,欢迎各位大牛百家争鸣!

微信公众号OldDriverWeekly,欢迎关注并提出宝贵意见

老司机iOS周报,欢迎关注或订阅

刚刚在线工作室,欢迎关注或提出建设性意见!

刚刚在线论坛, 欢迎踊跃提问或解答!

如有转载,请注明出处,谢谢!

本站总访问量 本文总阅读量