简单记录iOS开发中的一些小问题和解决办法

pop动画的严重性能问题

之前一个界面打开的时候有一点卡,直觉告诉我可能是pop动画的锅,一调试,果然,pop的renderTime这个函数耗时太久了。
这一个页面用了6,7个POP动画,我的看法是很多大多数动画能用CA实现的,就不要用POP。
iOS动画渲染的机制是这样的,如果是一个CA隐式动画,计算好要数据之后会提交给一个backBoard后台进程,然后我们APP就不管了,这意味着这个动画的后续的每一帧计算我们已经不用再提交了。而POP相反,每一帧都要去提交backBoard后台进程(核心是CADisplaylink),就产生了性能问题。

顺便提一句动画是为了让用户更好的交互,比如一个工具栏会在右边隐藏,那么开场的飞入动画能提示用户右边有个工具栏。
每一个动画应该都有他的交互意义存在,不是单纯为了炫酷。比如写出lottie动画库的airbnb,无意义动画太多,就导致app看上去很乱,很卡,甚至首页的列表滑动的时候出现了卡帧,性能问题没解决,做那么多炫酷的动画难免有点头重脚轻。

各种动画的适用场景,什么时候用约束做动画

做动画无非两板斧:先解构动画组成,再一步步实现。
但是不同的场景有不同的实现,ca也好,pop也好,改transform也好。但以前总觉得用约束做动画是一个异类,没啥好处,却很诡异。
这一期却让我学到了约束动画的好处-联动。
具体业务场景不描述了,原本是打算做一个假的透明的headview没能实现需求。
用约束却很容易也很完美地实现了。
其实用什么做动画都可以,具体场景具体分析。但尽量不要改变frame去做动画。

简单地更改响应链,以配合UI的反人类设计

场景:先想象一个简单的表,有headview,但是上滑的时候headview是被表盖住,并且!他能响应交互事件。
实现:如果不响应相互事件,只要简单的将headview写成一个独立view,再给表一个透明的与独立view一样大小的view即可。
其实要响应交互也很简单,只要部分禁用表的交互就可以了,如下:
需要注意的是判断frame的时候,要取透明view相对于整一个视图的坐标,需要转换坐标系。

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    UICollectionReusableView *reusableView = [self.mainCV supplementaryViewForElementKind:UICollectionElementKindSectionHeader atIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]];
    NSLog(@"+++%f",self.mainCV.contentOffset.y);
    if (reusableView) {
        CGRect clearViewFrame = reusableView.frame;
        clearViewFrame.origin.y = clearViewFrame.origin.y -self.mainCV.contentOffset.y;
        BOOL isContained = CGRectContainsPoint(clearViewFrame, point);
        if (isContained) {
            return NO;
        } else {
            return [super pointInside:point withEvent:event];
        }
    } else {
        return [super pointInside:point withEvent:event];
    }
}

实现多个竖排文字的排列

最近在解决一些组里遗留下的一些没解决的BUG。
之前同事的解决方法是写一个分类,每一个字/n换行。这个网上也一查就能查到,但是。。。只能显示1列。
我的建议是因为之前看到过YYText有类似的实现,只不过从从右到左排列。可以使用YYText或者自己使用CoreText,但同事反馈有时候渲染不出来,我对此存疑但也没有深究。
这期我花时间看了一下之后,采取的方法是使用苹果自带的NSStringDrawing,我先计算出每一个字需要在的位置和大小,再用以下的方法将字绘制出来。这种办法无论几列,无论从左到右,从上到下,从右到左都可以实现。也比CoreText上层的多。

@interface NSString(NSStringDrawing)
- (CGSize)sizeWithAttributes:(nullable NSDictionary<NSAttributedStringKey, id> *)attrs NS_AVAILABLE(10_0, 7_0);
- (void)drawAtPoint:(CGPoint)point withAttributes:(nullable NSDictionary<NSAttributedStringKey, id> *)attrs NS_AVAILABLE(10_0, 7_0);
- (void)drawInRect:(CGRect)rect withAttributes:(nullable NSDictionary<NSAttributedStringKey, id> *)attrs NS_AVAILABLE(10_0, 7_0);
@end

UITabview或者UICollectionView数据错乱的问题

一个复杂的UICollectionView数据错乱的bug,最后发现居然只是赋值的时候写了xx.view.xx属性=新属性,但view没有任何的接受方法(比如一个set方法更新UI),只在layoutview里写了赋值。

体会如下:遇到数据错乱先去调试赋值的时候model是否正确(一般不会出现数据源错乱的),基本都是因为赋值到UI的时候出现的问题。
比如下载图片的时候判断了url的length>0才开始下载,else却什么都没写,else难道不用将图片置为默认图片吗。这个问题这份代码里也存在。

还有一个情况是如果用了异步下载更新图片,当cell滑出屏幕,进入重用池,再被唤起,上一个下载图片的任务才执行完毕,回调更新UI,就更新到了错误的Cell上。所以SDWebimage采取了滑出屏幕取消任务的做法。
cell写许多block回调,同样道理,如果没有做处理,在将cell滑出屏幕的时候,就会出现问题。(之前我这么写没发现问题,需要review一下代码)

对3D旋转的理解

     CATransform3D trans = CATransform3DIdentity;
            trans.m34 = -1/100.0;
            trans = CATransform3DRotate(trans, M_PI/10.0*yOffset, 0, 1, 0);
            attr.transform3D =trans;

trans.m34 = -1/100.0; 是开启透视效果,0, 1, 0可以看做一个向量,所以010和050是没有区别的,但这种办法做的3d旋转view的边上会有锯齿,暂时不知道怎么解决。

对重写layout两个方法的理解

因为项目里最近遇到的动画,和不同的布局越来越多,自己重写的layout已经有3个。以前一直分不清两个方法的区别。

返回对应于indexPath的位置的cell的布局属性

-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath

返回rect中的所有的元素的布局属性

-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect

有的人只重写第二个方法,有的重写2个,第二个的实现依赖第一个。
其实:layoutAttributesForElementsInRect:的rect是可见部分的rect;layoutAttributesForItemAtIndexPath:是对于任意indexpath而言的。前面一个的实现往往依赖于后者,根据rect取得可见的indexpath,再根据后者取得layout attributes,加入数组,然后返回。

KVO无法捕捉动力动画中的小球的frame变化

KVO的本质无非是isa指向一个新的派生类,在派生类的set方法里添加副作用
为什么不在原来的类里添加?原因很明显,太多的副作用会影响set的纯洁性。
题目的原因是动画过程中的view 他本身的frame实际上没有发生变化。

实现uicollectionview的headview 悬浮

最简单的方法是iOS9之后有一个bool值可开关。但无奈现在还要适配iOS8,唯一的办法是重写一个layout
但大部分人如果用了mjrefresh会有冲突的,上拉的时候会有一闪的效果,主要还是因为mj改了conteninset,我的解决方法自己简单写了一个上拉。舍弃了mj。
可参考这个第三方:
https://github.com/CSStickyHeaderFlowLayout/CSStickyHeaderFlowLayout
我用的自己写的。感觉此库已经年久失修。

并且重写layout已经不是新鲜的做法了,许多酷炫的效果都可以通过这个方法实现。

如何reload collectionview 但是只改变高度 不走数据源代理

因为需求中有一个是动态改变headview的高度 当然如果是一个headview的话,直接改layout即可,但这里的需求有多个。
我一开始简单地reload了collectionview,但是会有一闪的感觉,网上也没说有好的办法。
后来我去查看了collectionview的接口找到这样一个方法。效果很好。

   [self.cvDiamond setCollectionViewLayout:self.layout animated:YES];

AVPlayer与系统pop右滑手势的冲突

如果你写过视频,肯定用过苹果原生的AVPlayer,那么我相信你们家只要有测试,就会发现这样一个bug。在视频页面右滑返回上一页面,左右来回移动,不真正的返回,回来会有卡帧。这是苹果自己AVPlayer的bug。
有一个解决方法。AOP替换方法,替换pop手势,替换viewdidload,在每打开一个界面的时候保留一张截图,左滑返回的时候并不是真的返回,而是用pan手势,改变frame,先显示上一个界面的截图,等手势结束判断返回上一个界面还是停留。
具体写法参考ZFPlayer,git上有。
但我个人觉得这个方案不好,因为每个大一点的app都会有自己的nav,都会有自己的左滑效果。这样一来这个效果就没了。
当然你也可以简单的暂停播放。

SVHud 不断重复调用 的BUG

一个场景:SVHud (对,就是那个出名第三方),在PDF下载前的有进度的HUD 会出现消失很缓慢的情况,简单地说就是PDF已经下载结束了,他还在转动。
原因:看了源代码,他是使用了NSOperation不断地去添加重绘的任务,然而AFNetworing的下载回调是0.00001数量级s就有一次的,因此导致前一个绘制任务还没结束就不断继续添加。主要还是SVHud得BUG,没有做取消操作。其他组同事写的图片上传的没有出现类似问题是因为,上传图片我们用的又拍云,它对上传进度回调做了处理,每0.1数量级左右才回调一次。
解决办法:自己写了一个HUD。

scrollview自动适应导致真实位置上下偏移

场景:导航栏隐藏,自定义View成为导航栏。在一个ScollView中嵌套左右可以滑动的2个tabview,下拉刷新的时候发生了奇怪的抖动。
原因:因为scrollview不能上下滑动的前提是contensize.height==tabview.height
而这个automaticallyAdjustsScrollViewInsets属性会导致scrollview的inset在我不知道的情况下发生了变化。
所以两个视图的手势都响应了。tabview 和scrollview的手势冲突了,两个都响应了滑动。ios9 和ios10 应该都有问题。
解决办法是:self.automaticallyAdjustsScrollViewInsets = NO; 改了这个属性就好了,iOS 11中automaticallyAdjustsScrollViewInsets属性被废弃了,self.automaticallyAdjustsScrollViewInsets = NO就等于没有设置(默认是YES),于是顶部就多了一定的contentInset。
如果你的APP中使用的是自定义的navigationbar,隐藏掉系统的navigationbar,并且tableView的frame为(0,0,SCREENWIDTH, SCREENHEIGHT)开始,那么系统会自动调整SafeAreaInsets值为(20,0,0,0)。

解决方法:

if (@available(iOS 11.0, *)) {
     self.xxView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
} else {
     self.automaticallyAdjustsScrollViewInsets = NO;

CAAnimation 由协议变成了 强引用的delegate

在iOS10之后,CAAnimation 由协议变成了 强引用的delegate,为什么是强引用呢?
苹果官方也说是一个特例,但我们并不需要担心它的循环引用。
因为animation是跟随layer->view的生命周期的,需要特定的设置释放,所以循环引用的问题不作考虑。

SDWebImage 图片错乱的问题

一个比较常见的问题:cell中的图片错乱,原因主要是2点1:自己写了图片下载,没有取消滑出屏幕的cell下载任务。
2:自己对图片异步做了裁剪,更新的时候没处理好。
解决办法1:使用SDWebimage 因为他处理了这个情况,滑出屏幕的任务会取消2:使用url匹配,在下载回调回来之后的block里比较cell的url和图片url是否匹配。

reloaddata 回到顶部

relaodData不会滑动到顶部,是因为新的数据是加在后面的,这个时候relaodData确实不会滑动
但是你试试将数据insert到前面,然后relaodData,就会滑到顶部
只好刷新单行

阴影在两个情况下不会渲染

1背景是clear color
2view设置了cliptobounds

如果设置增加cv的contentsize

为了满足各种奇特的UI 需要将表的数据扩充到一个屏幕那么大
1在reloaddata之后并不能立刻拿到正确的contentsize 要调用[self.mainCV layoutIfNeeded];
2因为头部加了一个透明的headview 计算contensize的时候 会将这个高度高度(headview)计算进来

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,019评论 4 62
  • 今天我的好闺蜜微信告诉我她要结婚了,在十月份,听到这个消息的第一时间我替她感到高兴!她和他的男朋友是家里人...
    栀寒九暖阅读 211评论 0 0