熟悉Objective-C

2017-07-18  本文已影响12人  Mark_Lin

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

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

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

字面数值
NSNumber *Number = [NSNumber numberWithInt:1];
NSNumber *newNumber = @1;
字面数组

如果数组元素对象中有nil,则会抛出异常,因为字面量语法实际上只是一种“语法糖”(syntactic sugar),其效果等于是先创建了一个数组,然后把方括号内的所有对象都加入到这个数组中。
因此,如下面这两个数组的第二位都未nil时,array里面会只有@“one”一个对象,而newArray将会抛出异常。这种微妙的差别表明,使用字面量语法更为安全。抛出异常令程序中止执行,这比创建好数组之后才发现元素个数少了要好,因为向数组中插入nil通常就是说明程序有错,最终结果往往就是数组越界崩溃,而现在我们却可以通过异常可以更快地发现这个错误。

NSArray *array = [NSArray arrayWithObjects:@"one",@"two",@"three", nil];
NSArray *newArray = @[@"one",@"two",@"three"];
字面字典

与数组一样,用字面量语法创建字典时也有一个问题,那就是一旦有值为nil,便会抛出异常。

NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:
                        @"Mark",@"firstname",
                        @"Lin",@"lastname",nil];

NSDictionary *newDic = @{@"firstname" : @"Mark",
                         @"lastname" : @"Lin",
                         @"age" : @28};

大家可以很直观地看出两种创建实例变量的方法有什么区别,使用字面量的方式不仅可以令到代码看起来更加地整洁,而且字面量语法也更为精简,因为声明中只包含数值,而没有多余的语法成分。

局限性

字面量语法有一个小小的局限,就是除了字符串以外,所创建出来的对象必须属于Foundation框架才行。

而使用字面量语法创建的字符串、数组、字典都是不可变的(immutable),若想要可变版本的对象可以参考以下写法:

NSMutableArray *mutable = [@[@"one", @"two", @"three"] mutableCopy];

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

常量为什么一定要同时使用static与const来声明呢???
因为如果有人试图修改有const修饰符所声明的变量时,那编译就会报错,而这就是我们所需要达到的目的!!!

而static修饰符则是意味着该常量仅在定义此常量的编译单元中可见。

编译器每收到一个编译单元,就会输出一份“目标文件”(object file),在Objective-C的语境下,“编译单元”一词通常指每个类的实现文件,因此在上述代码中声明的kAnimationDuration,其作用域仅限于由MarkAnimatedView.m所生成的目标文件中。

假如声明此常量时不加static,则编译器会为它创建一个“外部符号”(external symbol),此时如若另一个编译单元中声明了同名常量,则会报错。

而有时候确实是需要对外公开某个常量的时候,我们有应该如何处理呢?(如在类代码中调用NSNotificationCenter)

此类常量则应放在“全局符号表”(global symbol table)中,以便可以在定义常量的编译单元之外使用。具体实现如下:

```
//  MarkAnimatedView.h
#import <UIKit/UIKit.h>

extern NSString *const MarkLoginNotification;

@interface MarkAnimatedView : UIView

- (void)animate;

@end

//  MarkAnimatedView.m
#import "MarkAnimatedView.h"

static const NSTimeInterval kAnimationDuration = 0.3;

NSString *const MarkLoginNotification = @"MarkLoginNotification";

@implementation MarkAnimatedView

- (void)animate
{
   [UIView animateWithDuration:kAnimationDuration animations:^{
        //Perform animations
    }];
}

- (void)doNotificationAction
{
    [[NSNotificationCenter defaultCenter] postNotificationName:MarkLoginNotification object:nil];
}

@end
```

注意const修饰符在常量类型中的位置,常量定义应从右至左解读,所以在本例子中,MarkLoginNotification和kAnimationDuration就是“一个常量,而这个常量是指针,指向NSString对象”。

extern这个修饰符会告诉编译器,在全局符号表中将会有一个MarkLoginNotification的符号,编译器无须查看其定义,因为它知道当链接成二进制文件之后,肯定能找到这个常量。

这样定义常量要优于#define预处理指令,因为编译器会确保常量值不变,而且一旦定义好之后,即可随处使用。

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

使用NS_ENUM与NS_OPTIONS宏来定义枚举类型,并指明其底层数据类型,这样做可以确保枚举是用开发者所选的底层数据类型实现出来,而不会采用编译器所选的类型。
在处理枚举类型的swith语句中不要实现default分支,这样就可以在加入新枚举之后,编译器自动提示开发者:swith语句并未处理所有枚举。

上一篇 下一篇

猜你喜欢

热点阅读