iOS开发中的那些的约定俗成(1)————《编写高质量iOS与OS X代码的52个有效方法》读书笔记(第一章)

iOS开发中的那些的约定俗成(1)

————《编写高质量iOS与OS X代码的52个有效方法》读书笔记(第一章)

前言

“我要成为一个高产的开发人员。”“想要混的好,就得多努力。”
写这些东西是因为毕竟看了书,但是看书看过去之后,也许印象不是很深刻,有些东西现在也理解不了,那我就把我理解的,现在就可以用到的东西,简单的写出来就好,让自己今后看到就能明白其中的意思。
还有就是锻炼一下表达,编辑能力,慢慢的提升自己,随时随地的都要有一个锻炼的心。
最后当然就是为了和大家分享一下,大家一起讨论讨论其实也满有必要的。
欢迎大家批评指教!

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

  • 主要是为了避免两个类相互调用导致编译错误,特别是两个类都声明了协议方法的时候,也许不会出现直接相互调用(相互依赖)的情况,但是要是出现第三个文件导致的相互调用的报错,那就喜感了,找起来相当费劲。
  • 防止这种情况,一般尽量使用@class 关键词进行处理,并且注意协议代理的声明。
  • 对于协议的定义的方法,我们大可将该协议定义到一个单独的 .h 文件中,当然也许还有别的情况,但是以我目前看到的情况就是这个样子,要是还有其他的情况,等我以后了解后再说吧。
  • 还有就是相互调用头文件将会造成编译时间的增加,也许这就是我们菜鸟的程序员写的程序不如老鸟那样的高效的原因吧。

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

  • 什么是字面量语法就是,定义比如NSArray,NSDictionary,NSString,NSNumber这些对象时,采用的一些更加简单的方法,如下:定义变量名称后缀为“1”的都是传统的定义方法,当然还有对应的类方法,这里我没有写。变量名称后缀为“2”的即是字面量语法。
    NSDictionary *dict1 = [[NSDictionary alloc] initWithObjectsAndKeys:@"object", @"key", nil];
    NSDictionary *dict2 = @{@"key": @"object"};

    NSArray *array1 = [[NSArray alloc] initWithObjects:@"object", nil];
    NSArray *array2 = @[@"object1",@"object2",@"object1"];

    NSString *string1 = [[NSString alloc] initWithString:@"string"];
    NSString *string2 = @"string";

    NSNumber *number1 = [[NSNumber alloc] initWithInt:1];
    NSNumber *number2 = @1;

其中NSArray,NSDictionary还有对应的取值操作:

    NSString *value1 = [dict1 objectForKey:@"key"];
    NSString *value2 = dict2[@"key"];

    NSString *str1 = [array1 objectAtIndex:1];
    NSString *str2 = array2[1];

使用字面量的语法主要有两点好处:

  • 代码更加简洁易懂,objective-c 咱们都懂,所以使用这样的语法可有效的让我们的代码更加易于阅读,便于维护。
  • 还有很重要的一点就是当使用传统的alloc方法或者类方法时,如果你的数组内要放入三个元素,当第二个元素为nil的时候,编译器不会出现任何异常,只会创建一个只有第一个元素的数组,这样导致的结果就是你的程序无法按照你想的方式进行运行,而且在你编译测试的时候你可能无法及时的发现这个问题,这样就会比较麻烦了。
    但是当然你使用字面量语法时,编译器会抛出一个类似于:
    异常图片
    的异常的。这样我觉得是可以及时发现并进行处理的。

使用字面量的语法创建的变量都是不可变的,这个时候我们需要将其复制一份:

    NSMutableArray *array3 = [array2 mutableCopy];

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

在开发过程中,当我们需要固定某一个常量时,比如播放动画的时间,发送通知的name参数时,我们也许会这样做:

#define ANIMATION_DURATION 0.3
#define kPushNotificationName @"pushNotificationName"

但是使用预处理指令会存在这样几个问题:

  • 这样定义出来的常量没有类型信息,常量的命名也许不能明确指出该常量代表的类型,而且在编译过程中,编译器会将所有的“ANIMATION_DURATION”一律替换为0.3,这样的话加入在其他问题引用了该头文件,那就会把所有的“ANIMATION_DURATION”都进行替换。
  • 并且使用该方法,不能保证在程序运行的过程中该指令的值不发生改变。

那么对于这样的情况,我们可以使用如下的方式进行定义:

static const NSTimeInterval kAnimationDuration = 0.3;
  • 变量使用 static 修饰可以保证该变量仅在定义此变量的编译单元可见。静态变量修饰符,保证变量一直到所在编辑单元(类似于ViewController)释放后才会释放,不会每次重新开辟地址空间。
  • 变量使用 const 修饰则可以保证变量不会改变,当试图修改 const 修饰的变量时,编译器就会报错。
  • 当一个变量既声明为 static,有声明为 const,那么编译器根本不会创建符号,而是会像 #define 预处理指令一样,把所有遇到的变量都替换为常值。
  • 不过使用该方法定义的时候带有类型信息。

一般来说使用该方法直接定义的变量,一般是用在 实现文件(.m文件)中,即当前文件可用,尽量不要将它定义到头文件(.h 文件)中。那么类似于 NSNotification 定义时用到的 name 参数,用来标记通知名称的常量不太适合直接用这样的方法来定义,因为一般来说 NSNotification 我们需要在 Post(发送通知),addObserver (添加通知进行接收)都要用到 name 常量,并且可能很多处都需要用到该常量,那么这个时候我们就需要采用如下的方法了:

// .h 文件中
#import <Foundation/Foundation.h>

@interface LoginManager : NSObject

extern NSString *const loginManagerPushNotification;

@end
// .m 文件中
#import "LoginManager.h"

NSString *const loginManagerPushNotification = @"LoginManagerPushNotification";

@implementation LoginManager

@end
  • 使用这样的方法声明一个外界可见的常值变量,这样注册者无须知道实际字符串值,只需以常值变量来注册自己想要接受的通知即可。
  • 关键字 extern ,该关键字会告诉编辑器,在全局符号表中将会有一个名叫 “loginManagerPushNotification” 的符号,也就是说,编译器无须查看其定义,即允许代码使用该常量。因为它知道,当链接成二进制文件后,肯定能找到这个常量。

最后说明一下,我们关于一些常量我们应该尽量避免使用 #define 预处理指令,而不是说不使用 #define 预处理指令,一些像这样的:

// 屏幕的尺寸
#define kScreenBounds ([[UIScreen mainScreen] bounds])
#define kScreenWidth (kScreenBounds.size.width)
#define kScreenHeight (kScreenBounds.size.height)
// 生成对应颜色
#define lUIColorFromRGB(rgbValue) [UIColor \
colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \
green:((float)((rgbValue & 0xFF00) >> 8))/255.0 \
blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]

// 系统版本判断
#define kSysVer ([[[UIDevice currentDevice] systemVersion] floatValue])

#define iOS9Later (kSysVer >= 9.0f)
#define iOS8Later (kSysVer >= 8.0f)
#define iOS7Later (kSysVer >= 7.0f)
#define iOS6Later (kSysVer >= 6.0f)

#define iOS7 (kSysVer >= 7.0f && kSysVer < 8.0f)

// 系统当前语言
#define lLanguages   [[NSLocale preferredLanguages] objectAtIndex:0]

我们还是可以使用的。

用枚举标示状态、选项、状态吗

由于Objective-C 基于 C 语言,所以 C 语言的有的功能他都有。其中之一就是枚举类型:enum 。在以一系列常量来表示错误状态码或可组合的选项时,极宜使用枚举为其命名。有关枚举的语法,我在这就不多说了。
一般最简单的用法是:

typedef enum : NSInteger {
    MessageUpdateSuccess,
    MessageUpdateFailed
} MessageUpdateStatus;

当然我们也可以制定底层数据类型,就像这样:

typedef enum : NSInteger {
    MessageUpdateSuccess = 1,
    MessageUpdateFailed,
} MessageUpdateStatus;

就我个人而言目前以上两种用法就已经满足我的需求了,但是还有这样的一种情况,我现在悟的不是很明白,就姑且贴出来给大家看看吧。

typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
    UIViewAutoresizingNone                 = 0,
    UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,
    UIViewAutoresizingFlexibleWidth        = 1 << 1,
    UIViewAutoresizingFlexibleRightMargin  = 1 << 2,
    UIViewAutoresizingFlexibleTopMargin    = 1 << 3,
    UIViewAutoresizingFlexibleHeight       = 1 << 4,
    UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};

枚举

此外系统还有定义了一些辅助的宏,用这样宏来指定保存枚举值的底层数据类型。这个我还是不是很明白,可能是目前还一直用不到的关系吧,这里我就不说了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值