<<Effective Objective -C 2.0>>阅读笔记(一)

<<Effective Objective -C 2.0>>阅读笔记只是作为骚栋的自己的心得,建议各位看官自己去看<<Effective Objective -C 2.0>>,五星推荐,推荐理由:面试储备必备、内存性能优化、提高代码质量.非广告~


前言


<<Effective Objective -C 2.0>>只是做阅读的笔记,所有的笔记只是把52个相关有效方法进行总结以及阐述骚栋的观点.<<Effective Objective -C 2.0>>这本书对实际开发过程中还是有着很大帮助的,尤其是项目的性能优化方面有着巨大的帮助,而且如果你想当一个iOS面试官,或者说你要去面试iOS,那么<<Effective Objective -C 2.0>>这本书我推荐给你.我将按照读书的每一个方法进行记录.看官们可以自行查看.


熟悉Objective-C(第一章标题)


全书总共分为7个章节,这一篇文章,我们主要说一下第一章节熟悉Object-C的内容.这一章节总共有五条建议,下面我们一一道来.

  • 了解 Objective-C的起源

这个前面就说了一堆关于OC的家族史,我们就暂时跳过了,但是我们要说说这个OC中独有的"消息结构",其实我更喜欢称之为"消息发送机制".首先从语法外表上来说,相比于C语言的"函数调用"和其他语言例如java,js中通过调用某一个对象中的某一个方法都是使用"点语法".而OC中使用的是一个[]来表明某一个对象调用了某一个方法.如下示例所示.那么从本质上来说,OC语言是总是在运行的时候才去查找所需要执行的方法.(可以查看<<Effective Objective -C 2.0>>补充(一):OC中的消息机制(转载))

    NewObject *object = [[NewObject alloc]init];

    [object action];

另外这一部分还说了一个名词,那就是指针,指针是什么?有一本书的名字诠释指针的定义,叫做"指针是C语言中一个闪亮的星星",如果C语言中什么最重要,那么无疑是三样,一是指针,二是链表,三是结构体.在OC中我们到处可见的就是*,作为指针,OC中没有想C中那么要求严格了,但是这里有一个问题,可能连作为资深的你都不知道,那就是 我们都知道OC中的对象是存储在堆区的,那么作为指向对象地址的指针是存储在什么区?难道也是堆区?,正确答案是栈区.

OC作为C语言的超集,添加了面向对象的特性.作为一个iOS开发人员,我们使用对象那真是到了如火纯青的地步了.在OC中我们也会经常用到结构体,比如CGRect,在C语言中结构体的存在意义类似于OC中的对象。下面我们就比较一下两者的区别。
首先,结构体是存储于内存的栈区的,而OC中的对象则是存储在内存的堆区;再者,C语言中的结构体要比OC的对象中对内存性能的影响更小。主要是原因是在于OC对象的创建需要额外的开销,比如分配及释放堆内存等。


  • 在类的头文件中尽量少引入其他头文件

我们在一个类中经常会使用到另外的一个类,那么我通常需要到导入头文件,通常我们导入使用#import来导入头文件,我们看下面一种情况,我们需要把NewObject这个类的对象作为ViewController的一个属性,而且需要暴露出来,所以把属性写在View Controller的头文件中.我们可能就是用#import "NewObject.h"来导入到头文件中.如下所示.

#import <UIKit/UIKit.h>
#import "NewObject.h"

@interface ViewController : UIViewController

@property(nonatomic,strong)NewObject* obj;
@end

虽然这样是可行,但是却不够优雅,在编译的时候,我们只需要知道NewObject这个类是存在的即可,我们不需要这个类的全部细节,所以这里我们使用@class导入对象的头文件即可.如下所示.

#import <UIKit/UIKit.h>
@class NewObject;

@interface ViewController : UIViewController

@property(nonatomic,strong)NewObject* obj;
@end

那么这么做到底有什么好处呢?或者说,这么做到底有什么样的优势呢?使用@class将引入头文件的时机尽量延后,只在确有需要时才引入,这样就可以减少类的使用者所需引入的头文件数量.假设使用#import "NewObject.h"来导入到头文件中,那么会一并引入NewObject的所有内容.若此过程持续下去,则要引入许多根本用不到的内容,会大大的增加编译时间.另外使用@class还解决了另外的一个问题,那就是循环引用问题.下面我们就举例说明一下关于@class解决循环引用的示例.

我们假设有两个类,分别叫FirstObject和SecondObject,在FirstObject中有一个SecondObject属性对象,同时在SecondObject中有一个FirstObject属性对象,同时我们都是使用#import导入头文件,所以两个类的情况就如下所示了.

#import <Foundation/Foundation.h>
#import "SecondObject.h"

@interface FirstObject : NSObject

@property(nonatomic,strong)SecondObject *sencondObject;

@end

#import <Foundation/Foundation.h>
#import "FirstObject.h"

@interface SecondObject : NSObject

@property(nonatomic,strong)FirstObject *firstObject;

@end

但是,这样就会出现循环引用问题,这是为什么呢?当解析其中的一个头文件的时候,编译器会发现它引入另一个头文件,而那个头文件又回过头来引入第一个头文件,这样反反复复,会最终导致一个类无法被正确编译.如下图所示.

那么我们改如何解决这种循环引用问题呢?我们只需要把两个头文件的任意一个导入换成@class方式即可,前面我们说过@class只是说明有这个类的存在,并不会导入这个类的全部信息.比如我们把FirstObject中的头文件如下修改,然后就不会再出现编译错误了.

#import <Foundation/Foundation.h>
@class SecondObject;

@interface FirstObject : NSObject

@property(nonatomic,strong)SecondObject *sencondObject;

@end


  • 多用字面量语法,少用与之等价的方法

其中,对于字面量语法,这几年学习的iOS童鞋都会使用.这种字面量语法从Objective-C 1.0就开始出现了.时代已经相当久远了~对于从iOS 6走过来的我们来说,我们只需要知道如何使用即可,像NSString、NSArray、NSDictionary、NSNumber这种不可变类型的对象都可以使用字面量语法.示例如下所示.

NSString *string = @"字面量语法";
NSArray *array = @[@"栋哥",@"菜哥",@"狗哥"];
NSDictionary *dictionary = @{@"key":@"value"};
NSNumber *number = @1;

使用字面量语法,到底有什么优势呢?其实主要是更为简单易读.我们看下面两种创建方式.我们发现使用字面量语法创建字符串更加的简答易懂.

NSString *string = @"字面量语法";
NSString *string = [NSString stringWithString:@"字面量语法"];

而且,现在如何使用下面的那种方式创建,那么会出现警告.如下图所示.


  • 多用类型常量,少用#define预处理指令

在实际开发的过程中,我们经常会使用预处理指令来定义我们常用的常量,例如我们定义一个int类型的常量,如下所示.

#define  KLength  12

但是这样使用预处理指令到底会出现什么弊端呢?其实,整体上来说还是规范的问题,首先使用预处理指令没有表明常量的类型信息,所有不能很好的表明的描述常量的定义;而且,预处理过程会把碰到的所有的KLength替换成12,这样的话,假设此指令声明在某个头文件中,那么所有引入了这个头文件的代码,KLength都会被替换掉.

那么,我们该如何解决上面阐述的两个问题呢,我们可以使用以下的代码来定义KLength这个常量.我们这样定义之后,既解决了引入头文件无故替换问题,而且还包含常量的类型信息.

static const int KLength = 12;


  • 用枚举表示状态、选项、状态码

使用枚举来表示状态应该是一个很常见的使用,比如我以前写过的SDLaunch:一个杂七杂八,却功能完整的广告引导页,SDLaunch的类型就有四种,我在使用过程中就是用了枚举来表示不同的类型如下所示.

typedef enum {
    ADLaunchViewController,//广告类型
    GreenhandLaunchViewController,//轮播图新手导引类型
    GifBackgroundLaunchViewController,//gif图背景类型
    RollImageLaunchViewController//滚动图片类型
} LaunchViewControllerType;

还有使用枚举来表示选项,这个是我们经常在一些头文件中看到的,用枚举来表示选项和枚举来表示状态是不一样的,一般我们用枚举来表示状态的时候是会选择其中的一个枚举值,而用枚举来表示选项则是可能是多种多样的选择组合.换句话说就是状态是单选,而选项是多选的.

那么我们如何使用枚举来表示选项呢?如下所示.

//正确的选项枚举示例
typedef enum {
    firstType   = 0,
    secondType  = 1<<0,
    thirdType   = 2<<0,
    fourthType  = 3<<0
}enumType;

这里我们看到了我们使用了移位符<<,首先说明一下什么叫移位符.

位移位运算符是将数据看成二进制数,对其进行向左或向右移动若干位的运算。位移位运算符分为左移和右移两种,均为双目运算符。第一运算对象是移位对象,第二个运算对象是所移的二进制位数。

也就是说1<<0的值为二级制的10,2<<0的值为二级制的100,那么为什么要这么做呢?我们假设不使用移位符,那么我们直接使用1,2,3,4来给枚举赋值.如下所示.

//错误的选项枚举示例
typedef enum {
    firstType   = 0,
    secondType  = 1,
    thirdType   = 2,
    fourthType  = 3
}enumType;

假设我们需要是的thirdType和secondType两个选项,我们可以通过"按位或操作符"来组合.如下所示.但是这样就真的没有错误了吗?使用"按位或操作符"其实是组合两个枚举值的值,也就说newType现在的值是3,那么跟enumType newType = fourthType;这样是一个意义了,并不能表达选择了多个枚举值.

    enumType newType = secondType|thirdType;

假设我们使用了移位符<<那一套的枚举值就不会这样的问题了,我们来看一下这是为什么呢?我们还是使用** enumType newType = secondType|thirdType;这时候,newType的枚举值是多少呢?是二进制的110,如果说enumType newType = fourthType;**,那么枚举值也会发生改变为1000,两者并不是相等的,这样我们就区分开了.示例图像如下所示.

和枚举经常配合使用的经常的switch分支语句,我们知道switch分支语句在最后都会默认的实现default语句,这里,书中不建议我们把这个分支进行实现,这样的话,如果加入新枚举之后,那么编译器就会提醒开发者,switch并没有处理所有的枚举.


结束


关于<<Effective Objective -C 2.0>>中的第一章的五个注意点就写到这里,由于本文为笔记形式,所以需要更深刻的理解书中内容,还是建议读者去自行阅读<<Effective Objective -C 2.0>>这本书,下面发一个PDF的书籍传送门.大家可以去看PDF版的,如果有任何问题欢迎联系骚栋,我们一同探讨.谢谢大家.

--> <<Effective Objective -C 2.0>>PDF版传送门🚪


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

推荐阅读更多精彩内容