iOS 之 坑系列

Posted by Elliot on December 25, 2016

版权声明:本文为博主原创文章,未经博主允许不得转载

这里主要记录一些以前遇到的有些坑当做笔记,分享出来让自己不要犯同样的错误,也让大家少走弯路;

会持续更新;

坑:

iOS10 出来之后,有一个坑很多APP中招了,那就是 CTFrameDraw绘制时,如果存在文字换行的情况下,最后一行绘制不出;这是iOS系统的一个bug,不知道以后 APPLE 会不会改过来;

解决办法就是:需要将绘制区域高度加4-5的高度

效果图就不贴了,估计很多人都中招了

/*关键*/
CGRect rect = CGRectMake(0, origY, width, height+5);
CGMutablePathRef firstColumnPath = CGPathCreateMutable();
CGPathAddRect(firstColumnPath, NULL, rect);
CTFrameRef firstColumnFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, string.length), firstColumnPath, NULL);
CTFrameDraw(firstColumnFrame, context);

坑:

NSMutableAttributedString计算高度时,如果同时存在CFNS的属性,那么计算的高度可能会存在偏差;

例子:

NSMutableAttributedString *str = ...;
NSStringDrawingOptions opts = NSStringDrawingUsesLineFragmentOrigin |
 NSStringDrawingUsesFontLeading;
CGSize sizeContent =[str boundingRectWithSize:CGSizeMake(self.width, 100000)
                                                  options:opts
                                                  context:nil].size;

[str addAttribute:(NSString*)kCTForegroundColorAttributeName
                      value:(id)highlightColor.CGColor
                      range:match.range];
[str addAttribute:NSForegroundColorAttributeName
                      value:highlightColor
                      range:match.range];

sizeContent =[str boundingRectWithSize:CGSizeMake(self.width, 100000)
                                                  options:opts
                                                  context:nil].size;

两次计算的sizeContent可能不一样,非常诡异,所以最好是只用一种方式计算;官方推荐用NS方式

坑:

UIView 动画的坑

很多系统的API中动画效果都会带有animation的参数,比如: - (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated;。这些APIanimation自带的动画都是transition动画,transition动画会另开一个动画线程,然后在主线程执行,这个时候如果你去进行UI操作,就会打断动画的执行,比如tableviewreloadData(可能会让动画卡顿)

另一种动画就是UIView的属性动画block,这种动画在主线程执行,不会被其他UI操作打断动画的执行

遇到的坑就是,下拉刷新的时候,使用的是系统自带的API- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated; 如果数据比较复杂且tableviewreload比较频繁,就会导致animation动画很卡顿;

解决办法就是换成属性动画或者block动画;

动画的继承结构

CAAnimation{
    CAPropertyAnimation{
            CABasicAnimation{
                    CASpringAnimation
            }
            CAKeyframeAnimation
    }
    CATransition
    CAAnimationGroup
}

坑:

曾经遇到过一个很诡异的问题,就是列表从服务器下载图片缓存在本地,讲图片的hash作为key缓存起来;讲道理如果图片不一样,hash应该是不一样的,但是有很小的概率会遇到加载一样的图片出来,百思不得解,最后定位问题发现取缓存时是hash值一样,但是再次加载hash又不一样;真是无语!

最后Google之。。。

  1. _updateHash方法中有改变hash值的方法,location.hashlocation.replace两个,不管执行的是哪个,hash值不会立即改变!也就是说早ios9中hash在地址栏中变化有延迟!地址

  2. iOS: [NSString hash]出现同样的hash值问题地址

第2种是hash冲突,不符合我遇到的问题;我遇到的应该是第一种情况了;

但是第一种解决办法有点麻烦,我们不需要那么麻烦,只需要再加一些其他参数作为key唯一就行了,比如宽高size等等

坑:

调用类方法,在父类中最好不要使用self调用,最好用类名调用,因为在子类中,会先遍历子类的类方法List,发现没有就去父类的方法List中找,这样效率比较低。

坑:

touch事件的几个方法中

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesCancelled:(nullable NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;

当触摸时会调用began,然后当移动的时候可能会调用move,为什么说可能呢?因为当移动非常非常快时是可能捕获不到move事件的,这个时候就会调用cancle,最后当松开的时候可能会调用end,但是也有可能松开时手指已经不在事件区域了,所以会调cancle

iOS 9UITouch事件的坑

6s 以后的触摸事件内部运行机制不同,不管有没有move(猜测可能是重按也算move),都会马上调touchesMoved