编写高质量iOS与OS X代码的52个有效方法 Day1 2017-09-24 周日

扯会淡

       这周项目有点忙,又要新版本的提测,又要老版本适配iOS 11,确实没有什么成段的时间可以静下心来好好看看书,只能周日的早上迎着”朝阳“看看书(其实是阴天,冷死,杭州这几天天天下雨,I hate rainy days),最近可能会对于项目中适配iOS 11的东西,写一篇文章(看心情吧,哈哈)。

       今天就先对《Effective Objective-C 2.0》的前5条做一个记录和总结。话说这本书好像有很多人推荐,看了一会觉得确实对于代码的细节会有一个深刻的反思,我觉得是本可以细细咀嚼的书。

第一条:了解Objective-C语言的起源

       OC是基于C编写的,这个应该大家都知道,所以OC支持c,c++的混编,我个人觉得一个真正厉害的OC程序员,应该对于三者混编应该有自己独到的理解(轻喷)。但是OC跟c++,Java等面向对象的语言有一个很大的不同,就是消息结构机制,而不是函数调用机制。

         //Message (OC):

         Object *obj = [Object new];

         [obj performWith:parameter and:parameter1];

         //Function Calling (c++)

         Object *obje = new Object;

         obj->perform(parameter,parameter1);

       这在程序的编译和执行时有很大的区别,最关键的一点区别是:使用消息结构的语言,在运行的时候,怎么执行是由运行环境决定的,就是在编译的时候,根本不关心接收消息的对象是何类型;而使用函数调用的语言,则是由编译器来决定,在编译的时候就已经明确的知道这个函数是谁来执行。

       OC的重要工作都依赖于OC独有的一个运行期组件(Runtime Component)。运行期组件本质上就是一种与开发者写的代码链接的动态库(dynamic library),其功能就是把开发者的所有代码粘合起来。

       想要理解OC的内存模型以及“引用计数”(reference counting)机制,首先需要明白一个前提:Objective-C语言中的指针是用来指示对象的。就是对象多占内存总是分配在堆中,而指向这个对象的指针是分配在栈中。OC将堆内存管理抽象出来了,不需要用malloc和free来分配或释放对象所占内存。OC运行期环境把这一部分工作抽象为一套内存管理架构,名为“引用计数”。

       在OC代码中,有时会遇到不含*的变量,也就是基本数据类型,它们使用的是可能是“栈空间”。比如我们设置frame,经常用到的CGRect,它是个c结构体,

struct CGRect {

    CGPoint origin;

    CGSize size;

};

typedef struct CGRect CGRect;

       OC的整个系统框架,可以看到很多这种结构体,因为相比创建对象来说,节省了分配及释放堆内存的额外开销。如果只需保存基本数据类型,那么通常使用这种c结构体。

第二条:在类的头文件中尽量少引入其他头文件

       关于这一点,我想所有的程序员应该多多少少都有体会,如果在类A的头文件中引用类B的头文件,又在类B的头文件中引用类A的头文件,就会造成循环引用。对于这一点OC有一个专门的引用指令#import相比#include指令,虽然不会导致死循环,但这却意味着两个类中有一个类无法被正确编译。

       所以正确的做法应该是向前声明,就是只在头文件中声明有另一个类,并不需要知道另一个类的全部细节。就是在类A的头文件中使用@class B;而在实现文件中正确的引入类B#import “B.h”

       //A.h

       #import <Foundation/Foundation.h>

       @class B;

       @interface A : NSObject

       @property (nonatomic, strong) B *b;

        //...

        @end

         //A.m

         #import "A.h"

         #import "B.h"

         @implementation A

         //...

         @end

       有时无法使用向前声明,比如要声明某个类遵循一项协议。这种情况下,尽量把“该类遵循某协议”的这条声明移至“class-continuation分类”中。如果不行的话,就把协议单独放在一个头文件中,然后将其引入。

       ”class-continuation“分类就是.m文件中的@interface那一块。

第三条:多用字面量语法,少用与之等价的方法

         什么是字面量语法?

NSString *string = @"hello world!";         //字符串字面量

NSNumber *intNumber = @1;                   //字面数值

NSNumber *floatNumber = @2.5f;

NSNumber *doubleNumber = @3.14159;

NSNumber *boolNumber = @YES;

NSNumber *charNumber = @'a';

int i = 5;

folat f = 5.3f;

NSArray *array = @[@"cat",@"dog",@"pig"];       //字面量数组

NSString *dog = array[1];

NSDictionary *dic = @{@"firstName":@"tao",@"lastName":@"bingzhi",@"age":@25};

       以上都是一些字面量的写法,那么有什么好处呢?很直白的一点是,代码清晰明了易读,没有多余的语法。

       同时在声明数组和字典时,如果有一个元素是nil,这样还会报错,而如果用数组或字典的类初始方法创建的话“arrayWithObjects:”会一次处理各个参数,知道发现nil停止,不至于莫名其妙创建好数组之后发现元素少了。

       当然也有一定的局限性,除了字符串之外,所创建出来的对象必须属于Foundation框架才行。如果自定义了这些类的子类,则无法用字面量语法创建其对象。还有就是字面量创建出来的字符串、数组和字典都是不可变的(immutable)。如果想变成可变的,需要mutaleCopy以下。

NSMutableArray *mutableArr = [@[@"hh",@"ss",@"tt"] mutableCopy];

第四条:多用类型常量,少用#define预处理指令

       写代码时常常需要定义常量,那么怎么定义常量才是正确且合适的,常量定义的位置又有什么讲究呢?

       如果我们用#define来预处理一个宽度,可能会这么写

#define kIconWidth 30;

         这虽然能解决,但是这样定义出来的常量没有类型,代码不易读,可以使用下面这行代码:

static const CGFloat kIconWidth = 30;

       同时还要注意常量名称,常用的:若常量局限于某实现文件内,则在前面加子母“k”;若常量在类之外可见,则通常以类名为前缀。

       定义常量的位置也很重要,若不打算公开这个常量,则应将其定义在使用该常量的实现文件里。

       这里需要理解一下const和static两个关键字的意思,

       const:如果试图修改由const修饰符所声明的变量,那么编译器就会报错,不能被更新;

       static:就是限制了变量的可用范围,如果是在实现文件中用static声明了一个变量,那么变量的可用域就是该类所生成的目标文件,如果是在方法内用static声明,那么可用域就是这个代码块。

       最主要的一点还是,用这种方法声明常量带有类型信息。

       有的时候你需要公开一个常量,就是无需知道这个常量名背后的意义,只是需要用到这个常量名,例如通知名称的公开定义。这种时候,可以将常量放在“全局符号表“中,此时应该这么声明:

       //.h

       extern NSString *const WLLoginControllerNotification;

       //.m

      NSString *const WLLoginControllerNotification = @"WLLoginControllerNotification"
;

      个人更多的还是在pch文件中,直接写一个通知名static const NSString * WLLoginControllerNotification = @“WLLoginControllerNotification”;

第五条:用枚举表示状态、选项、状态码

       在日常开发中,枚举是很好用的一个东西,可以用来表示状态,传递给方法的选项以及状态码等值,需要主要的是,新的C++11标准修订了枚举的一项改动:可以指明用何种“底层数据类型”来保存枚举类型的变量。这样做的好处是可以向前声明枚举变量,编译器在用到枚举的时候,就知道该给枚举变量分配多少内存空间了。

       如果把传递给某个方法的选项表示为枚举类型,而多个选项又可以同时用,那么就将各选项值定义为2的幂,以便通过换位或操作将其组合起来。

       这里要注意一点:如果想要通过换位或操作的话,定义枚举是就不能用NS_ENUM来定义,而需要使用另一种方式定义,NS_OPTIONS,以便省去类型转换过程。

       最后一个小的tip,在处理枚举类型的switch语句中不要事先default分支,这样的话,加入新枚举之后,编译器会提示开发者:switch语句并未处理所有枚举。

总结

       今天状态不好,写的时候一直是很赶的情绪,不知道为什么,就没有静下心,很急,很抱歉。可能起太早了,天气又阴沉沉的,还没吃早饭,情绪不太对。sorry sorry。

       最后的最后,还是要说,换季了,大家不要感冒,出门上班可以带件外套。希望大家身体健康,吃嘛嘛香。


Better Late Than Never!
努力是为了当机会来临时不会错失机会。

                 共勉!

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

推荐阅读更多精彩内容