1、了解Objective-C語言的起源
- OC語言使用“消息結構” 而非“函數調用”
消息結構:
Object *obj = [Object new];
[obj performWith:parameter1 and:parameter2];
特點:運行時的代碼由運行環境來決定。
函數結構:
Object *obj = new Object;
obj->perform(parameter1,parameter2);
特點:運行時的代碼由編譯器來決定。
- OC是C的“超集”,所以C語言的所有功能在編寫OC代碼時依然適用!
OC中的內存模型:
NSString *nameString = @“小伙子”;
上面就是說:聲明了一個名為 nameString 的變量 ,其類型為NSString *
也就是說,此變量為指向NSString 的指針。當然了不止NSString這樣聲明,所有Objective-C的對象都必須這樣聲明。原因:對象所占內存總是分配在“堆空間”中,而不會分配到“棧”上。 - 在OC中,你還會碰到一些不需要 *的變量。他們可能會使用“棧空間” 這些變量保存的不是Objective-C對象。舉個例子
struct CGRect {
CGPoint origin;
CGSize size;
};
typedef struct CGRect CGRect;
系統框架都在使用結構體。因為使用Objective-C來做的話會影響性能(創建對象、分配內存、釋放內存)。如果只是保存int、float、double、char這些“非對象類型” 通常使用CGRect結構體就可以了。
2、在類的頭文件中盡量少引入其他頭文件
- 現象:
Objective-C創建文件分為.h(頭文件)和.m(實現文件)
假如在某個頭文件中引入一些根本用不到的頭文件。那么程序也會引入頭文件的內容。這樣會增加編譯時間。 - 建議:
除非確實有必要,否則不要引入頭文件。
應該在實現文件中引入要使用的頭文件,降低類之間的耦合。
3、多用字面量語法,少用與之等價的方法
- 實現
語法創建:
//多種類型的數值
NSNumber *number = [NSNumber numberWithInt:1];
//數組創建
NSArray *array = [NSArray arrayWithObjects:@"1",@"2",@"3", nil];
//字典的創建
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@"Mary",@"name",@"Secr",@"name1" ,nil];
字面量創建
//數值創建
NSNumber *number = @1;
int a = 1;
float b = 4.23f;
//數組創建
NSArray *array = @[@"1",@"2",@"3"];
//字典的創建
NSDictionary *dictionary = @{@"Mary":@"name",@"Secr":@"name1"};
- 結論
- 使用字面量語法創建字符串、數值、數組、字典。與創建此類對象的常規方法相比,這么做更加簡明扼要。
- 用字面量創建數組或者字典時,若值中有nil,則會拋出異常。因此,務必確保值里不含nil。
4、多用類型常量,少用#define預處理指令
- 編寫代碼時候經常要定義常量。
例如一個動畫的播放時間
#define ANIMATION_DURATION 0.3
預處理指令會把源代碼中的ANIMATION_DURATION字符串替換為0.3。
but、這樣定義出來的常量沒有類型信息。- 名字(duration)這個詞看上去與時間有關,但是代碼中并沒有標出。
- 假如其他文件中有ANIMATION_DURATION ,也會一律替換成0.3
- 可以這樣解決:
static const NSTimeInterval kAnimationDuration = 0.3;- 包括了類型信息、有助于編寫開發文檔、讓接手代碼的人更易讀。
- 試圖修改const修改的變量,那么編譯器會報錯。
- 注意:
- 常量的命名規則:
常量局限于實現文件之內,在前面加字母k。
若是常量在類之外可見,那么要以類名為前綴。比如SCViewClassAnimationDuration。
- 常量的命名規則:
- 外界可見的常值變量:
- 這種常量放在“全局符號表”中,以便可以在定義該常量的編譯單元之外使用!
.h中
- 這種常量放在“全局符號表”中,以便可以在定義該常量的編譯單元之外使用!
extern NSString *const SCNameStringConstant;
.m中
NSString *const SCNameStringConstant = @"Peter";
- 原理:
編譯器看到頭文件中的extern關鍵字后,就知道在全局符號表中有一個名叫 SCNameStringConstant 的符號。
編譯器無需查看其定義,允許代碼使用此常量。因為它知道肯定能找到這個常量。 - 注意:
此常量必須要定義且只能定義一次。通常是定義在與聲明常量的頭文件相關的實現文件里。鏈接器會把此目標文件和其他目標文件相鏈接,形成二進制文件,凡是用到SCNameStringConstant的地方都能解析。
因為符號要放在全局符號表里,所以命名的時候一定要注意。最好是用與之相關的類名做前綴!
5、用枚舉表示狀態、選項、狀態碼
- 枚舉:enum
系統框架中頻繁用到此類型:
比如創建UIButton時候
typedef NS_ENUM(NSInteger, UIButtonType) {
UIButtonTypeCustom = 0, // no button type
UIButtonTypeSystem NS_ENUM_AVAILABLE_IOS(7_0), // standard system button
UIButtonTypeDetailDisclosure,
UIButtonTypeInfoLight,
UIButtonTypeInfoDark,
UIButtonTypeContactAdd,
UIButtonTypeRoundedRect = UIButtonTypeSystem, // Deprecated, use UIButtonTypeSystem instead
};
枚舉只是一種常量命名方式。每種狀態用一個易讀的值來表示,這樣更方便理解。編譯器會為枚舉分配一個獨有的編號,從0開始,每個枚舉遞增1。
- 比如狀態一般分為“OK”和“Error”。只能選擇其中一種,不可能出現2種。
我們可能通過枚舉這樣做
typedef enum _TTGState {
TTGStateOK = 0,
TTGStateError,
TTGStateUnknow
} TTGState;
//指明枚舉類型
TTGState state = TTGStateOK;
用的時候就這樣:
- (void)dealWithState:(TTGState)state {
switch (state) {
case TTGStateOK:
//...
break;
case TTGStateError:
//...
break;
case TTGStateUnknow:
//...
break;
}
}
```
- 選項:就是說一個“選項變量”的類型要能夠同時表示一個或多個組合的選擇。
比如說iPhone 可以支持多個方向。
//方向,可同時支持一個或多個方向
typedef enum _TTGDirection {
TTGDirectionNone = 0,
TTGDirectionTop = 1 << 0,
TTGDirectionLeft = 1 << 1,
TTGDirectionRight = 1 << 2,
TTGDirectionBottom = 1 << 3
} TTGDirection;
好處就是我們選項變量可以如下表示:
//用“或”運算同時賦值多個選項
TTGDirection direction = TTGDirectionTop | TTGDirectionLeft | TTGDirectionBottom;
//用“與”運算取出對應位
if (direction & TTGDirectionTop) {
NSLog(@"top");
}
if (direction & TTGDirectionLeft) {
NSLog(@"left");
}
if (direction & TTGDirectionRight) {
NSLog(@"right");
}
if (direction & TTGDirectionBottom) {
NSLog(@"bottom");
}
一般來說,我們不能指定枚舉變量的實際類型是什么,就是說,我們不知道枚舉最后是int型,還是其他的什么類型。但是從C++ 11開始,我們可以為枚舉指定其實際的存儲類型。
enum TTGState : NSInteger {/*...*/};
Foundation框架中定義了一些輔助的宏,這些宏具備了向后兼容的能力(判斷編譯器是否支持新的枚舉特性,不支持就用老的語法來定義枚舉)。
- 在iOS程序中,最好所有的枚舉都用“NS_ENUM”和“NS_OPTIONS”定義,保證統一。
### 接下來也將會繼續整理。如果覺得有用請點個喜歡!
### 您的支持將是我繼續寫作的動力!謝謝。
[觀“編寫高質量iOS與OC X代碼的52個有效方法”有感(一)· 熟悉Objective-C](http://www.lxweimin.com/p/0876e60d3160)
[觀“編寫高質量iOS與OC X代碼的52個有效方法”有感(二)· 對象、消息、運行時](http://www.lxweimin.com/p/1aac4fb98888)
[觀“編寫高質量iOS與OC X代碼的52個有效方法”有感(三)· 接口與API設計](http://www.lxweimin.com/p/5d9e61db2a01)
[觀“編寫高質量iOS與OC X代碼的52個有效方法”有感(四)· 協議與分類](http://www.lxweimin.com/p/0944e1e276ff)