<EffectiveObjective-C2.0编写高质量iOS与OS X代码的52个有效方法>读书笔记(一)

本人有若干成套学习视频, 可试看! 可试看! 可试看, 重要的事情说三遍 包含Java, 数据结构与算法, iOS, 安卓, python, flutter等等, 如有需要, 联系微信tsaievan.

这是一本很经典的OC的书, 不过一直没时间看, 最近想好好撸一遍, 于是就想写一点读书心得, 按照章节来吧, 这本书分为7个章节:

Chapter 1. 熟悉Objective-C
Chapter 2. 对象, 消息, 运行时
Chapter 3. 接口与API设计
Chapter 4. 协议与分类
Chapter 5. 内存管理
Chapter 6. Block与GCD
Chapter 7. 系统框架

今天先介绍下第一章的内容: 熟悉OC

这一章内容不多, 也很简单, 大家都知道的事情我就不多说了, 就说两个需要注意的点:

  • 类型常量与#define预处理指令
  • 位移枚举的使用
(一)类型常量与#define预处理指令

当你在写代码的时候, 有时候直接写上魔法数字是一种很low的做法, 这个时候, 有两种解决方案:

  1. #define预处理指令
  2. 类型常量

比如你要定义一个动画的持续时间为0.5秒, 你可以:

#define kAnimationDuration 0.5

也可以:

static const NSTimeInterval kAnimationDuration = 0.5;

但这两种方案其实效果差不多, 但是第二种方案包含了常量的类型, 你明确地知道它是NSTimeInterval类型的, 虽然NSTimeInterval就是double类型,但这个类型转换明显增强了代码可读性, 让阅读代码的人明确知道, 这个变量就是与动画持续时间相关的.

如果你不打算公开这个常量供外界使用的话, 就写在.m文件里
staticconst两个关键字要同时使用.

原因如下:

♦︎ 如果试图修改const修饰符所声明的变量, 那么编译器就会报错.

static const NSTimeInterval kAnimationDuration = 0.5;

像这种类型的变量我们只需要使用即可, 不希望被改动, 那么就需要用const关键字来修饰

♦︎ 而static关键字则意味着该变量仅仅在此变量的编译单元中可见.
编译器每收到一个编译单元(.m文件<你可以这么理解>), 就会输出一份"目标文件"(object file).

♦︎ 假如你声明变量的时候不加static, 则编译器会为它创建一个"外部符号"(external symbol). 此时若是另一个.m文件也声明了同名变量, 那么编译器就会抛出错误消息.

♦︎ 实际上, 如果一个变量既声明为static, 又声明为const, 那么编译器根本不会创建符号, 而是直接像#define预处理指令一样, 把所有遇到的变量都替换为常量, 不同的是:(再强调一遍) 这种方法是带有类型信息的

但如果你的类型常量就是要公开给全局使用, 那么就需要用extern关键字来修饰, 最常见的比如一些通知的名称:

UIApplicationDidEnterBackgroundNotification
UIApplicationWillEnterForegroundNotification

比如在.h中你这样声明:

extern NSString *const UIApplicationDidEnterBackgroundNotification;

在.m文件中定义:

NSString *const UIApplicationDidEnterBackgroundNotification = @"UIApplicationDidEnterBackgroundNotification";

这样全局的命名必须在前面加上类名.

像之前那个例子, 只是在自己的编译单元使用的, 只需要加上小写字母k即可:

static const NSTimeInterval kAnimationDuration = 0.5;
(二)位移枚举
系统已经为我们提供了一些快速创建枚举变量的宏, 比如NS_ENUM, NS_OPTIONS, 前者相信大家都很熟悉了, 我来说说后者:

无论是在系统框架中, 还是在SDWebImage这样的第三方框架里, 位移枚举都是广泛使用的, 位移枚举可以使你同时使用多个枚举值:

比如在SDWebImage中, 你就常常见到这样的代码:

            SDWebImageDownloaderOptions downloaderOptions = 0;
            if (options & SDWebImageLowPriority) downloaderOptions |= SDWebImageDownloaderLowPriority;
            if (options & SDWebImageProgressiveDownload) downloaderOptions |= SDWebImageDownloaderProgressiveDownload;
            if (options & SDWebImageRefreshCached) downloaderOptions |= SDWebImageDownloaderUseNSURLCache;
            if (options & SDWebImageContinueInBackground) downloaderOptions |= SDWebImageDownloaderContinueInBackground;
            if (options & SDWebImageHandleCookies) downloaderOptions |= SDWebImageDownloaderHandleCookies;
            if (options & SDWebImageAllowInvalidSSLCertificates) downloaderOptions |= SDWebImageDownloaderAllowInvalidSSLCertificates;
            if (options & SDWebImageHighPriority) downloaderOptions |= SDWebImageDownloaderHighPriority;
            if (options & SDWebImageScaleDownLargeImages) downloaderOptions |= SDWebImageDownloaderScaleDownLargeImages;

我举一个简单的例子来说明一下:

假设我现在创建了一个关于方向的位移枚举:

typedef NS_OPTIONS(NSUInteger, YFDirection){
    YFDirectionNone = 0,    // 没有方向
    YFDirectionEastward = 1 << 0,    // 向东
    YFDirectionWestward = 1 << 1,    // 向西
    YFDirectionSouthward = 1 << 2,    // 向南
    YFDirectionNorthward = 1 << 3,    // 向北
};

比如我想判断一个物体的加速度方向, 一个物体可能在多个方向上都有加速度, 那么这个就是普通枚举无法完成的, 这个时候就需要用到上面的位移枚举

- (void)judgeDiretionWithOptions:(YFDirection)directionOption;

当我点击屏幕的时候, 就调用上面这个方法:

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [self judgeDiretionWithOptions: kNilOptions];
}

- judgeDiretionWithOptions:方法的实现:

- (void)judgeDiretionWithOptions:(YFDirection)directionOption {
    if (directionOption & YFDirectionEastward) {
        NSLog(@"向东");
    }
    if (directionOption & YFDirectionWestward) {
        NSLog(@"向西");
    }
    if (directionOption & YFDirectionSouthward) {
        NSLog(@"向南");
    }
    if (directionOption & YFDirectionNorthward) {
        NSLog(@"向北");
    }
    NSLog(@"%zd", directionOption);
}

如果我传的参数为YFDirectionEastward | YFDirectionSouthward, 就相当于是既有向东的加速度, 又有向南的加速度.
控制台的打印为:

控制台的打印结果
至于位移的原理, 这里就不再赘述了. 希望大家能够将位移枚举灵活地运用到项目当中.

PS. 本人有若干成套学习视频, 包含Java, 数据结构与算法, iOS, 安卓, python, flutter等等, 如有需要, 联系微信tsaievan.

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

推荐阅读更多精彩内容