iOS 开发中你是否遇到这些经验问题(一)

作者: 判若两人丶 | 来源:发表于2016-08-07 08:50 被阅读13996次

    前言

    小伙伴们在开发中难免会遇到问题, 你是如何解决问题的?不妨也分享给大家!如果此文章其中的任何一条问题对大家有帮助,那么它的存在是有意义的! 反正不管怎样遇到问题就要去解决问题, 在解决问题的同时也是提高开发经验的渠道!

    1.既然有问题我们该怎样解决 ?

    首先大部分人都会去百度搜索来解决问题, 谁都不例外, 可是百度这东西会有很多误解, 甚至误人子弟, 同时解决问题的效率也不是很高, 如果是技术问题可以去:

    • Google 简单来说比百度搜索的答案相对要多,要更准确效率更高, 建议使用英文搜索
    • Stack Overflow 一个与程序相关的IT技术问答网站, 简单来说工作中的70%问题在这里都能解决

    搜索是解决问题的一种办法, 那么剩余30%的问题还是需要自己独立去解决, 那么有人会问有没有能提高独立解决问题的办法呢 ? 比如: 积累所遇到的崩溃信息, 学会查看崩溃信息, 查看官方文档的技巧等等) 本文暂时不会详解, 有时间的话需要单独写一篇文章来探究如何高效的解决崩溃问题!

    2.用断点调试崩溃问题的小技巧
    • (1)如果当前断点指向内存, 那么就是初始化时分配内存时有问题
    • (2)添加全局断点的问题:
      添加全局断点.png
      全局断点的目的就是当产生异常崩溃能够停留在异常或者崩溃发生的地方而不是跳转到主函数
    崩溃断点.png
    但是添加全局断点后会跳转到主函数, 会遇到如上图的情况, 那么80%的问题就是storyboard或者xib拖线没有及时清理掉坏线如下图:
    拖线没有清除.png
    这条Button的连线在代码中已经删除了不用了, 但是没有及时清理掉,所以会造成崩溃!
    3.NSString使用stringWithFormat拼接的相关知识
    • 保留2位小数点
    //.2代表小数点后面保留2位(2代表保留的数量)
    NSString *string = [NSString stringWithFormat:@"%.2f",M_PI];
    //输出结果是: 3.14
    NSLog(@"%@", string);
    
    • 0补全的方法
    NSInteger count = 5;
      //02代表:如果count不足2位 用0在最前面补全(2代表总输出的个数)
      NSString *string = [NSString stringWithFormat:@"%02zd",count];
    //输出结果是: 05
    NSLog(@"%@", string);
    
    • 字符串中有特殊符号%怎么办
    NSInteger count = 50;
     //%是一个特殊符号 如果在NSString中用到%需要如下写法
      NSString *string = [NSString stringWithFormat:@"%zd%%",count];
    //输出结果是: 50%
     NSLog(@"%@", string);
    
    • 字符串中有特殊符号"怎么办
    NSInteger count = 50;
    //"是一个特殊符号, 如果在NSString中用到"需要用\进行转义
    NSString *string = [NSString stringWithFormat:@"%zd\"",count];
    //输出结果是: 50"
     NSLog(@"%@", string);
    
    4.判断是否为gif/png图片的正确姿势

    首先我们先想想如果是你, 你会怎么去判断一个从网络获取的图片URL是否为gif图片, 是否是这样呢 ? 如下:

      //假设这是一个网络获取的URL
      NSString *path = @"http://pic3.nipic.com/20090709/2893198_075124038_2.gif";
      // 判断是否为gif
      NSString *extensionName = path.pathExtension;
       if ([extensionName.lowercaseString isEqualToString:@"gif"]) {
           //是gif图片
       } else {
           //不是gif图片
       }
    

    什么难道你不是这么判断的么 ? 哦~ 我懂了, 难道你使用字符串截取来判断的吗 ? 哈哈开个玩笑!
    以上判断看似是可以的,但是这不严谨的, 在不知道图片扩展名的情况下, 如何知道图片的真实类型 ? 其实就是取出图片数据的第一个字节, 就可以判断出图片的真实类型那该怎么做呢如下:

    //通过图片Data数据第一个字节 来获取图片扩展名
    - (NSString *)contentTypeForImageData:(NSData *)data {
        uint8_t c;
        [data getBytes:&c length:1];
        switch (c) {
            case 0xFF:
                return @"jpeg";
            case 0x89:
                return @"png";     
            case 0x47:
                return @"gif";        
            case 0x49:   
            case 0x4D:
                return @"tiff";        
            case 0x52:  
                if ([data length] < 12) {
                    return nil;
                }
                NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
                if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) {
                    return @"webp";
                }
                return nil;
        }
        return nil;
    }
    

    其实图片数据的第一个字节是固定的,一种类型的图片第一个字节就是它的标识, 我们来调用一下这个方法:

     //假设这是一个网络获取的URL
        NSString *path = @"http://pic.rpgsky.net/images/2016/07/26/3508cde5f0d29243c7d2ecbd6b9a30f1.png";
        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:path]];
        //调用获取图片扩展名
        NSString *string = [self contentTypeForImageData:data];
        //输出结果为 png
        NSLog(@"%@",string);
    
    5.Button禁止触摸事件的2种方式

    大家应该知道, 有很多需求是在规定内不允许点击Button, 并且让用户知道这个按钮是不可以点击的,那我们应该这样设置:

    //会改变按钮的状态,颜色会变灰
    button.enabled = NO;```
    但是又有一个需求是既不能点击也不要改变Button颜色:
    

    //保持按钮原来的状态,颜色不会变
    button.userInteractionEnabled = NO;

    #####6.跟xib一起走过的坑
    (1) 如果在`xib`中有一个控件, 已经明确设置尺寸了,输出的`frame`也是对的, 但是显示出来的效果不一样(比如尺寸变大了), 如果是这种情况一般就是`autoresizingMask`自动伸缩属性在搞鬼! 解决办法如下:
    

    //xib的awakeFromNib方法中设置UIViewAutoresizingNone进行清空

    • (void)awakeFromNib {
      self.autoresizingMask = UIViewAutoresizingNone;
      }
    (2)如果你的控制器的`view`是用`xib`创建的, 当你拿到`view`的尺寸是不准确的, 在这里我们就需要通过`[UIScreen mainScreen].bounds`拿到尺寸, 但是`storyboard`的尺寸是准确的!
    
    #####7.你是用什么方法设置图片圆角?
    首先你是否是这么设置的:
    
    //cornerRadius 设置为self.iconImage图片宽度的一半(圆形图片)
    self.iconImage.layer.cornerRadius = 20;
    self.iconImage.layer.masksToBounds = YES;
    
    或者是在`xib`&`storyboard`中点击要设置圆角的图片:
    ![xib或者storyboard设置圆角.png](https://img.haomeiwen.com/i2353624/cce526062c2d783a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    在此之后建议大家尽量不要这么设置, 因为使用`图层`过量会有卡顿现象, 特别是弄圆角或者阴影会很卡, 如果设置图片圆角我们一般用`绘图`来做:
    

    /** 设置圆形图片(放到分类中使用) */

    • (UIImage *)cutCircleImage {
      UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0);
      // 获取上下文
      CGContextRef ctr = UIGraphicsGetCurrentContext();
      // 设置圆形
      CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
      CGContextAddEllipseInRect(ctr, rect);
      // 裁剪
      CGContextClip(ctr);
      // 将图片画上去
      [self drawInRect:rect];
      UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
      UIGraphicsEndImageContext();
      return image;
      }
    这个方法就是设置圆角图片, 效率很高, 不会造成卡顿现象, 大家要把这个方法单独放到分类中使用
    
    #####8. ## 与 @# 在宏里面该怎样使用 
    * `##`的使用, 首先我们添加一个宏
    

    define LRWeakSelf(type) __weak typeof(type) weak##type = type;

    `##`是连接的作用, 即当使用上面的宏会把`weak`与输入的`type`值连接起来如下图:
    ![## 的使用.png](https://img.haomeiwen.com/i2353624/51d711f56b8df62b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    * `#`的意思是紧跟着它的后面的标识符添加一个双引号`""`
    * `@#`的使用, 我们添加一个普通的宏:
    

    //随便写一个宏

    define LRToast(str) [NSString stringWithFormat:@"%@",str]

    //这个宏需要这样写
    LRToast(@"温馨提示");
    NSLog(@"%@",LRToast(@"温馨提示"));

     强调下我只是随便定义一个宏来做示例, 以上代码是正常的使用,我们在来看看添加`@#`是怎么使用的:
    

    //随便写一个宏
    #define LRToast(str) [NSString stringWithFormat:@"%@",@#str]
    //这个宏需要这样写
    LRToast(温馨提示);
    //正常运行, 打印不会报错
    NSLog(@"%@",LRToast(温馨提示));

    我们可以看出来 `LRToast(温馨提示);`与`LRToast(@"温馨提示");`区别, 也就是说`@#`可以代替`@""` 那么我们以后开发就省事了, 不用再添加`@""`了!
    
    
    #####9.自动布局Autolayout口诀
    在`storyboard`或者`xib`使用自动布局, 如果控件比较多而且布局复杂, 一不小心就会报一大堆错误警告, 那么这个口诀是必备良药, 跟着这个口诀走再也不用害怕`Autolayout`恐惧症了 !
    ![Autolayout.png](https://img.haomeiwen.com/i2353624/78f21c084c43ee8a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    按照如上图从上到下顺序读就是当前这条约束的状态, 在`xib`中`Constant`与`Multiplier`不用区分顺序问题, 通过网友(落水雨辰)的提醒, 如果在代码中需要先`Multiplier` 在`Constant`(苹果官方的解释):
    `First Item`(登录按钮的顶部)`Relation`(等于) `Second Item`(父类View的顶部) ` Multiplier`(乘以 1) `Constant`(加上 10)  
    
    #####10.App迭代开发版本号的规则
    
    在iOS中简单的版本号是怎样管理的呢? 首先我们的`App`第一版本首次上线, 比如以`1.0.0`为首次上线的版本号:
    
    1.上线后突然发现一个严重的`Bug`那我们就要修复更新版本, 此时我们的版本号为`1.0.1`
    所以说如果修复`Bug`或者优化功能, 我们只修改叠加第三位数字, 其他不变
    
    2.如果有了新的需求, 在原来的基础上增加了一个新功能, 那么我们的版本号变为`1.1.0`, 需要清空第三位数字为`0`, 来叠加修改第二位数字
    
    3.如果`App`需求功能大改, 更新量非常大, 那我们的版本号变为`2.0.0`, 需要叠加修改第一位数字, 清空其他数字为`0`
    
    
    
    >喜欢的小伙伴请点赞一下吧!如果有不足的地方,请大家及时帮忙纠正与补充,顺便谈谈你的建议!
    相关文章: [iOS开发中你是否遇到这些经验问题(二)](http://www.jianshu.com/p/a924b4a17686)

    相关文章

      网友评论

      • 你好牛:👍一个
      • Society2012:写多点就更好了。
      • 纠结的哈士奇:其他不做评论,对第7个 设置圆角的问题,我的结论是这样:
        我用原始方法和楼主的方法都测试过一轮,用cornerRadius设置圆角,sd_sd_setimgae读取网络图片,fps基本都是60,然后再用楼主的类别方法,绘图设置圆角,真的,卡成翔。。。fps都掉到个位数了。。。

        不知道其他人的结论是什么?
        希望有简友测试完告知我结论,不知道是不是我的方法错了。
        判若两人丶: @纠结的哈士奇 圆角的问题是吧?这个方法不能放到主线程里执行,需要在子线程完成,然后回到主线程设置值。
      • 楼上那只猫:设置圆角那个,感觉不是很实用啊,比如我有一个imageview,宽200,高100,如果用平常用的方法设置圆角,cornerRadius=10(并不是宽的一半),这个时候用这个就不行了啊
        判若两人丶:@楼上那只猫 没关系,方法可以自己可以随时改嘛
      • f6867b07eaf8:你好,设置圆角那个能设置圆角的弧度吗?
      • C丶丶H:请问用 XIB 拖控件, 是根据屏幕比例适配大小的. 这种情况下在哪个方法里面设置圆角合适 ?
      • 一舟孤月:这一个口诀好像不够用吧,不还有些是对齐之类的约束吗?
      • 唱跳rap:支持一下
      • 丰田李:谢谢分享,受益匪浅
      • LovelyYilia:厉害的总结
      • zhou天天:赞你
        判若两人丶: @zhou天天 谢谢支持。
      • 六月的第三天:那个@#确实遇到过 赞一个
        判若两人丶: @占峰 谢谢支持
      • 405a4e4fb4b0:哇哦,很酷
      • 这个昵称就很帅:第4条,如果图片是jpg格式的呢?能否穷举或者大部分穷举图片格式对应的第一个字节数据。
        判若两人丶:@这个昵称就很帅 jpeg就是jpg
      • 司机王:你问我兹次不兹次,我当然兹次! 受益匪浅!
      • 李国安:不错哟 确实这些都是经验 没遇到过的就会坑 遇到过的就简单多了! 总结的好!
      • CoderFarmer:这个要顶
      • mingmingsky:楼主,最后一个版本迭代的,想问下你是怎么判断新版本提示更新的,转成floatvalue吗。
        判若两人丶: @mingmingsky 一般就是获取当前版本,在获取最新版本号进行比较,如果不相等就提示更新。
      • Pusswzy:真的是很好的文
      • a706aa61f4d8:写的挺好的,为了来点赞,注册了一个账号
        a706aa61f4d8:@判若两人丶 现在技术不够啊,看到AutoLayout口诀,有种莫名的喜感。
        判若两人丶: @a706aa61f4d8 哈哈,以后也可以一直玩简书
      • 释放想象力:经验是非常好的东西!
      • 三秒嗨:图片圆角的那个为什么我用了你的方法会很卡?难道是姿势不对。 我在对Cell 进行赋值的时候对图片进行处理。
        UIImage *headImg=[UIImage imageNamed:@"conpBG.png"];
        UIImage *headImg1=[headImg cutCircleImage];
        self.im_headV.image=headImg1;
        三秒嗨:@判若两人丶 :joy: 我没用到sdWeb.我去揣摩一下
        判若两人丶:@三秒嗨 一般图片处理都会用到SDWebImage,这个方法结合这个框架实用,尤其是cell中有图片
        判若两人丶:@三秒嗨 你需要这么设置, //circleImage 就是文章中的方法
        UIImage *placeholder = [[UIImage imageNamed:@"occupying_image"] circleImage];
        __weak typeof(self) weakView = self;
        [self.commodityImage sd_setImageWithURL:[NSURL URLWithString:_shopGoodsInfo.thumb] placeholderImage:placeholder completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
        weakView.commodityImage.image = image ? [image circleImage] : placeholder;
        }];
      • 三秒嗨:很好,经验这种东西就是需要分享。同一件事两个人去做,收获的都有可能是不一样的。
      • 嫌疑人zx:写的不错,涨姿势了
      • 丶偏执怪人:挺喜欢的
      • 老板娘来盘一血:谢谢,总结的非常好,支持一下,
      • 小鲁靠谱:很实用
      • 穿越1990:可以,这很ios。
      • 47号同学:什么时候出一篇如何利用官方文档解决问题的文章呢?
      • SekIne:圆角设置在之前会卡帧数,现在已经不会卡了。
        判若两人丶:@SekIne 都可以设置圆角,可能你方法不对,用一两个图层不会看出来卡顿,如果用多了就会展现出来了
        SekIne:@判若两人丶 不是...是用最开始的方法,两个属性设置就行了.
        如果用图形上下文的方法设置圆角,图片会有锯齿,而且占位图片无法设置成圆角..这点不知道为什么会这样.

        这两个
        判若两人丶: @SekIne 是用到文章中的方法后不卡了么?
      • 42e1c79aee08:顶起,但是圆角那个不怎么理解,还望楼主指教
        判若两人丶:@不要安逸的过 把设置图形图片方法拿到分类中使用,在外面调用就可以了,这个方法主要是用到图形上下文的知识
        492b9b7cf804:@不要安逸的过 ios 的绘画,是将这个图片画到指定的地方而不是设置为,你可以百度下iOS的绘制
      • 谢谢生活:autolayout 计算表达有点不规范 应该是:First Item(登录按钮的顶部)Relation(等于) Second Item(父类View的顶部) Multiplier(乘以 1) 再Constant(加上 10) 即: one.top = two.top * Multiplier + constant。其中constant可更改,multiplier只读,更改constant可用layoutifnend。更改multiplier要用移除以前的加新的约束。
        XH小子:@谢谢生活 我也认为你说的是对的,如果是先constant在Multiplier的话,xib里面修改Multiplier间距会变大,然而并没有变大
        判若两人丶:@谢谢生活 有的约束是没有Multiplier,如果有在xib中是可以修改Multiplier,并且这个公式在xib中设置没有先加或者先乘的顺序
      • TS洛洛:楼主,关于第九点我的理解是先乘以Multiplier,然后再加上Constant,是我理解错了吗:joy::joy:
        判若两人丶: @洛水雨辰 你说这个问题我看了,如果在xib中设置这个比例是独立的,所以就不存在顺序关系,如果你用纯代码设置约束,那我还真没试过,我从来不用代码写官方自带的约束,最后只要记住这个口诀关系就可以了,如果你弄明白了,可以告诉我,我学习学习。
        TS洛洛:@判若两人丶 你说的顺序是图上的顺序吗?但是NSLayoutConstraint的设置autolayout的方法,constant是放到multiplier的后面,而且苹果的官方文档解释也是这样子的:
        Constraints represent linear equations of the form view1.attr1 <relation> multiplier × view2.attr2 + c
        判若两人丶:@洛水雨辰 一定要按顺序来
      • Lol刀妹:请教一下,设置圆角那个具体步骤
        JackSuIce:为什么我创建了UIImageview 来调用分类中的方法,UIimage没得任何反应
        Lol刀妹:@判若两人丶 可以,很强势
        判若两人丶:@无夜之星辰 首先给UIImage扩展一个分类,然后把文章中的方法复制到分类中,最后在外面调用就可以了。
      • 84ba9b78918e:第8条有天刚好看到不知道啥意思,今天受教了
        判若两人丶:@大碗陈醋 互相学习
      • 一年级二班的小李:很好,很强大!
      • Yokihr:非常棒,支持 :+1:
        判若两人丶: @Yokihr 谢谢支持
      • Lol刀妹:可以,很强势
        一年级二班的小李:@无夜之星辰 奶强,很不错呀,我都好久木有看了,麻辣个🐔,大神,以后带我飞
        Lol刀妹:@TuringLi 因缺斯婷:sunglasses:
        一年级二班的小李:@无夜之星辰 奶强,每次都是这句台词,哈哈
      • 睡前思悟:干货 :+1:
        判若两人丶: @睡前思悟 后续还有第二篇文章,还在整理中。。
      • 冰三尺:第8条还从来没有用过,:+1:🏻。
        判若两人丶:@倩影如梦 可以尝试下,哈哈
      • 308459bd4007:非常棒
      • 漫步的小蚂蚁:赞一个,多谢作者分享
      • 廖马儿:非常不错
        判若两人丶:@Aircraft 谢谢支持,一起加油
      • YungFan:非常好,赞一个:+1:
        廖马儿:@判若两人丶 非常棒
        判若两人丶: @YungFan 有帮助就足够啦!

      本文标题:iOS 开发中你是否遇到这些经验问题(一)

      本文链接:https://www.haomeiwen.com/subject/tnbxsttx.html