1. 程式人生 > >Effective Objective-C 2.0 總結與筆記(第一章)—— 熟悉Objective-C

Effective Objective-C 2.0 總結與筆記(第一章)—— 熟悉Objective-C

第一章:熟悉Objective-C

​ 本章主要是對Objective-C進行一個瞭解,通過介紹Objective-C的語法,來講解Objective-C的基礎知識。

第1條:瞭解Objective-C語言的起源

  • Objective-C語言採用“訊息結構”而非“函式呼叫”,雖然也是一門面向物件的語言,但是語法比較特別。
//訊息結構:(Objective-C)
Object *obj = [Object new];
[obj doSomethingWith:someParams];

//函式呼叫:(C++)
Object *obj = new Object();
obj->doSomething(someParams);

採用訊息結構的語言:執行程式碼由執行環境決定。

採用函式呼叫的語言:執行程式碼由編譯器決定。

  • Objective-C的物件所佔記憶體分配在堆空間,不能在棧空間中分配Objective-C物件。通常Objective-C物件型別有一個*
/*
someString -> 分配在堆裡的某塊 含有一個叫"the string"的NSString物件 的記憶體
anotherString -> someString 指向的那塊記憶體

只有1個NSString例項,2個變數(指標)在棧幀中被分配了兩個記憶體,記憶體的值都是上面的堆記憶體地址
*/
NSString *someString = @"the string";
NSString *anotherString = someString;

在Objective-C中不含*的可能會使用棧記憶體,例如CGFloatCGRect etc.

第2條:在類的標頭檔案中儘量少引入其他標頭檔案

  • 引入有必要的標頭檔案,防止耦合。
  • 當只需要知道這個類名,而不需要使用到裡面的一些方法,我們可以使用向前宣告的方式代替#import方案。
//向前宣告
@class someClass;
  • 如果在各自的標頭檔案裡引入對方的標頭檔案,雖然不會像C++那樣導致死迴圈,但是會導致某個類無法被正確編譯。

第3條:多用字面量語法,少用與之等價的方法

  • 什麼是字面量語法?

以一種簡潔的方式就可以建立物件的方法,而不需要使用alloc

init來分配記憶體並進行初始化。並且除了字串以外,所建立的物件必須屬於Foundation框架。

example:

NSString *someString = @"the String";
  • 字面量的各種例子:
//字面量字串
NSString *someString = @"the String";

//字面量數值
NSNumber *intNumber = @1;
NSNumber *floatNumber = @1.5;

//字面量陣列
NSArray *animals = @[@"cat", @"dog", @"mouse"];
NSString *dog = animals[1];

//字面量字典
NSDictionary *personData = @[@"firstName" : @"Matt",
                              @"lastName" : @"Gallway",
                                   @"age" : @25];
NSString *firstName = personData[@"firstName"];
  • 使用字典或者陣列的時候,如果值中有nil,則會丟擲異常。

第4條:多用型別常量,少用#define預處理指令

  • 由於Objective-C裡沒有名稱空間的概念,所以如果使用預處理指令放在標頭檔案裡,那麼引入該標頭檔案的所有相關屬性都會被替換,當常量名稱可能衝突的時候,就可能存在一些隱藏的bug。
  • 儘量不要在標頭檔案裡宣告常量,應該在實現的程式碼裡去宣告。同時為了防止佔用系統的名稱空間,通常每個工程對常量的命名都有自己的命名規範,一般在前面加k。

example:

//  EOCAnimatedView.h
#import <UIKit/UIKit.h>


@interface EOCAnimatedView : UIView

- (void)animate;

@end
    
//  EOCAnimatedView.m

#import "EOCAnimatedView.h"

static const NSTimeInterval kAnimationDuration = 0.3;

@implementation EOCAnimatedView

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


@end

一定要用const和static來同時修飾該常量,const表示不可被修改,而static則意味著該變數僅在定義此變數的編譯單元可見。

  • 可以定義一個常量為其他檔案所用,此類常量通常放在“全域性符號表”中。

example:

//header file
extern NSString *const EOCStringConstant;

//implementation file
NSString *const EOCStringConstant = @"VALUE";

編譯器看到extern關鍵字,就知道在全域性符號表裡有一個名為EOCStringConstant的符號,編譯器無需檢視定義,允許程式碼使用,因為連結成二進位制檔案後可以找到這個常量。

第5條:用列舉表示狀態、選項、狀態碼

  • 一般情況下,編譯器會為列舉分配一個獨有的編號,從0開始,每次遞增1。
  • 建議使用如下方式來宣告列舉:
typedef NS_ENUM(NSUInteger, EOCConectionState) {
    EOCConectionStateDisConnected, //default 0
    EOCConectionStateConnecting, //default 1
    EOCConectionStateConnected //default 2
} ;

是這樣在使用的時候就可以直接使用EOCConectionState作為型別進行宣告列舉。其實EOCConectionState本質就是NSUInteger

  • 列舉的命名應當通俗易懂,意義區分明顯,不要出現混淆的情況。