iOS开发之你可能未留意的细节(持续更新)

1.正确设置Lable圆角的姿势

需求如图(常用作标签):



常规做法:

    self.label.text = @"皮尔斯";
    self.label.backgroundColor = [UIColor brownColor];
    
    self.label.layer.cornerRadius = 5;
    self.label.layer.borderWidth = 1;
    self.label.layer.borderColor = [UIColor cyanColor].CGColor;
    self.label.layer.masksToBounds = YES;

我这里用模拟器调试如图:

标黄的地方是告诉我们这些地方引起了离屏渲染


(更新于2019年2月27日01:03:11)
离屏渲染简单概念:GPU在当前屏幕缓冲区之外开辟一个新的缓冲区进行渲染操作,产生额外开销,可能会造成卡顿
我们知道当FPS小于60的时候,我们肉眼会感到卡顿
FPS即每秒刷新数,即 1000 / 60 ≈ 16.7ms,即16.7ms以内刷新一次页面就不会感到卡顿,系统生成图像信号是靠 CPU + GPU 共同工作的,即CPU + GPU 共同工作生成图像需要 < 16.7ms,而如果CPU或者GPU工作压力太大,生成图像信号大于这个时间,那么就会放弃掉这一帧,而继续显示之前的图像
因为离屏渲染会增加GPU的压力,所以我们应该尽量避免离屏渲染的发生


现在修改一下代码

    self.label.text = @"皮尔斯";
    self.label.layer.backgroundColor = [UIColor brownColor].CGColor;
    
    self.label.layer.cornerRadius = 5;
    self.label.layer.borderWidth = 1;
    self.label.layer.borderColor = [UIColor cyanColor].CGColor;

效果如图:

哈哈,离屏渲染没有了!
精髓在于我们干掉了masksToBounds这行代码,而颜色的设置放到了layer层
以后碰到类似需求就这样做吧,思密达!


2.数组之泛型数组

        Person* p1 = [Person new];
        Person* p2 = [Person new];
        Person* p3 = [Person new];
        NSArray* arr = @[p1,p2,p3];
        for (int i = 0; i < arr.count; i++) {
            arr[0];
        }

如图arr数组里存储了3个Person实例,并进行遍历
这样写固然没有问题,但是我数组的初始化如果不是用字面量的方式,arr里元素到底存储了那些东西,我们是需要扒代码的,有些项目的代码复杂度远远超乎你的想象,此时是非常耗时间的

OC的数组是可以存储任何类型对象的,但是我强烈建议用泛型除非特殊需求(虽然我接过这样的需求)
代码改动下:

        Person* p1 = [Person new];
        Person* p2 = [Person new];
        Person* p3 = [Person new];
        NSArray<Person*>* arr = @[p1,p2,p3];

为什么建议用泛型呢?
1.在数组声明的时候就已经明确数组里元素的数据类型了
2.用enumerateObjectsUsingBlock遍历数组时,你会发现数组里元素类型IDE已经帮我们输入好了(超赞的)而且《52高效》的书推荐我们用这种方式遍历数组

3. ARC下如何打印retainCount(引用计数)

    // obj目标对象
    NSInteger retainCount = CFGetRetainCount((__bridge CFTypeRef)chen);
    NSLog(@"Retain count is %ld", retainCount);

4.category你是否这么用过?

之前在某项目看到这样的分类:

@interface NSString (Help)
- (BOOL)isEmpty;
@end

@implementation NSString (Help)
- (BOOL)isEmpty {
    if (self == nil) {
        return YES;
    }
    return NO;
}
@end

一个判断字符串是否为空的分类,按照代码逻辑当字符串对象为nil的时候,认为为空返回true
但是却犯了一个大问题:当字符串对象为nil的时候,isEmpty方法是永远不会执行的,逻辑上表现为一个为nil的字符串对象他不认为是空的,返回false(这样做逻辑不就中奖了么?)

为什么会这样呢?
当字符串对象为nil的时候即[nil isEmpty],我们向nil对象发送了一条消息,OC的机制向nil发送消息是允许的,但是方法永远不会执行,这样做逻辑你说会不会中奖?

5.将view 放到的图层最上端

  // 目标view假设为topView
  // 1
  [self.view insertSubview:topView atIndex:[self.view subviews].count];
  // 2
  [[topView superview] bringSubviewToFront:topView];

6.UI妹子眼中一根线的粗细到底是多少?

#define  SINGLE_LINE_HEIGHT   (1 / [UIScreen mainScreen].scale)

为什么要这样呢:
scale的官方解释:


中文:
与屏幕相关的自然比例因子。
此值反映从默认逻辑坐标空间转换到此屏幕的设备坐标空间所需的缩放因子。 使用点测量默认逻辑坐标空间。 对于标准分辨率显示器,比例因子为1.0,一点等于一个像素。 对于Retina显示器,比例因子为2.0,一个点由四个像素表示。


7.这个细节你是否留意到了?

直接上图(以某大厂出的app举例)


这种控件现在越来越多的项目在用,但是呢,这个细腻的地方在于:
滑到“全部”这个页面的时候,再次右滑是可以pop的,虽说看起来一样的控件,但是我发现很多app是没有处理这个滑动pop逻辑的

我们自己的项目中也大面积使用了这种方式,当然这种细腻的体验我当然是要加进来的(o)/

直接上代码(如果有更好的思路希望提出来,共同学习哈!)

假设如图例子的UI结构是:ScrollView里添加了5个子View

// 给VC的view添加pan手势
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] init];
panGesture.delegate = self;
[self.view addGestureRecognizer:panGesture];
// 实现此代理
// 询问一个手势接收者是否应该开始解释执行一个触摸接收事件
#pragma mark - UIGestureRecognizerDelegate
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    // 这个_pageIndex就是记录当前滑到了哪个title下
    // 比如说在这里_pageIndex == 0 就是“全部”这个title下的页面
    if (_pageIndex == 0) {

        CGPoint translatedPoint = [(UIPanGestureRecognizer *)gestureRecognizer translationInView:self.view];

        NSLog(@"%f  %f",translatedPoint.x,translatedPoint.y);

        // 当在“全部”title下,且右滑的情况下,禁止scrollView滚动
        self.scrollView.scrollEnabled = translatedPoint.x < 0;
    }
    return NO;
}

8.这个细节你是否留意到了?

直接上图

example.gif

这种相册预览相信大家已经见过太多了,但是请注意个小细节,图片是由模糊渐渐变清晰的(微信图片浏览器就有这个细节)
这么做好处在哪里呢?
I/O操作是比较号资源的,我们先拿小图即缩略图展示出来,提高展示效率,其次获取高清图之后再替换,既提高了效率又加强了交互体验,一箭双雕,nice。

如果有更好的实现方式,请留言或者联系我

代码的实现方式请参考我的dolin_demo


以前碰到的都忘记总结了,就想起了这些,不过后续会持续更新

如果给你带来了一点点帮助,就点个赞吧😆

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

推荐阅读更多精彩内容