概述
本篇一起来学习如何优化UICollectionView实现的网格布局,这里只是展示图片和文字,但是图片比较大,而且比较多。在优化之前,很明显的一卡一卡的。
在优化之后,FPS达到了平稳的58~60,快速滚动时,基本都是60,而且在优化后通过Core Animations检测已经没有离屏渲染、图层混合等。
优化后的FPS
效果图
这是在前一篇讲如何实现网格布局的文章中的效果图,也是本篇文章要优化的内容。如果对网格布局不太懂,可以先阅读【UICollectionView网格布局】
优化图片
优化第一步:直接使用UIView,而不是UIImageView,这样更轻量:
1
2
3
|
@property
(
nonatomic
,
strong
)
UIView
*imageView
;
|
优化第二步:裁剪图片大小至控件的大小
裁剪前的效果图。裁剪前,很明显被压缩得很厉害,已经变形了,效果很差:
裁剪后的效果图。裁剪后,图片大小按照一定的比例裁剪,且图片的大小与控件的大小正好一致,也就没有了color mismatch images的问题了:
因为这里的背景的黑色,所以使用不透明。裁剪图片的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
-
(
UIImage
*
)
clipImage
:
(
UIImage
*
)
image
toSize
:
(
CGSize
)
size
{
UIGraphicsBeginImageContextWithOptions
(
size
,
YES
,
[
UIScreen
mainScreen
]
.
scale
)
;
CGSize
imgSize
=
image
.
size
;
CGFloat
x
=
MAX
(
size
.
width
/
imgSize
.
width
,
size
.
height
/
imgSize
.
height
)
;
CGSize
resultSize
=
CGSizeMake
(
x
*
imgSize
.
width
,
x
*
imgSize
.
height
)
;
[
image
drawInRect
:CGRectMake
(
0
,
0
,
resultSize
.
width
,
resultSize
.
height
)
]
;
UIImage
*finalImage
=
UIGraphicsGetImageFromCurrentImageContext
(
)
;
UIGraphicsEndImageContext
(
)
;
return
finalImage
;
}
|
异步去剪裁图片,在剪裁完成后再更新:
1
2
3
4
5
6
7
8
9
10
|
dispatch_async
(
dispatch_get_global_queue
(
0
,
0
)
,
^
{
UIImage
*image
=
[
UIImage
imageNamed
:model
.
imageName
]
;
image
=
[
self
clipImage
:image
toSize
:self
.
imageView
.
frame
.
size
]
;
dispatch_async
(
dispatch_get_main_queue
(
)
,
^
{
model
.
clipedImage
=
image
;
self
.
imageView
.
layer
.
contents
=
(
__bridge
id
_Nullable
)
(
model
.
clipedImage
.
CGImage
)
;
}
)
;
}
)
;
|
优化第三步:缓存剪裁的图片
在实际开发中,我们如果要优化,可以将剪裁后的图片缓存到本地。不过这里为了简单,只是将裁剪后的图片缓存到内存中,避免重复裁剪。我们给model增加一个字段,记录剪裁后的图片,然后在加载图片的地方,判断一下:
1
2
3
4
5
|
if
(
model
.
clipedImage
)
{
self
.
imageView
.
layer
.
contents
=
(
__bridge
id
_Nullable
)
(
model
.
clipedImage
.
CGImage
)
;
}
|
这里使用的是UIView来呈现图片,这样就更轻量一些。