我們這裡來考慮一下一個堆疊的程式碼:
@implementation Stack {
NSMutableArray *_array;
}
- (id)init {
if (self = [super init])
_array = [[NSMutableArray array] retain];
return self;
}
- (void) push :(id) x {
[_array addObject: x];
}
- (id) pop {
id x = [_array lastObject];
[_array removeLastObject];
return x;
}
- (void) dealloc { [_array release];
[super dealloc];
}
@end
雖然我們很直覺的寫了上述的程式碼,但是應用程式 Crash 了。因為程式碼有一個很大的問題。眼尖的人可能看出來了 pop 這個方法是錯的,為什麼?
根據蘋果官方的統計,記憶體漏洞在所有 Mac, iOS 應用發生 Crash 的原因中排行第一;同時也是被 App Store 否決掉的最主要原因。但,就跟 C 語言一樣,Objective-C 的記憶體的管理依然是相當複雜且耗時的工程,那,到底有沒有什麼比較好的解決方案呢?
91 年,Java 出現,同時也將 Garbage Collection (GC) 這項技術發揚光大。Java 不僅繼承了 C 語言的許多特性、完整的物件導向支援,更好的是,我們不用繼續在 malloc 跟 free 之間打轉。可惜,沒有多長的光景,GC 的缺點便一覽無遺。確實,只要程式語言支援 GC,程式設計師就不必再耗上無謂的時間在撰寫記憶體管理的程式碼,也省去了在錯綜複雜的宣告中尋找 bug 所需要花上的多餘人力與成本,但隨之而來的,卻是 GC 所佔用龐大的記憶體空間、系統必須提供 GC 運作所需要的 CPU Time,甚至執行中的應用程式都有被暫停下來,好讓 GC runtime 先運作的現象:這個問題對及時性高的系統是絕大的致命傷。就在程式設計師們期待能夠省去記憶體管理的工程,又可以有絕佳效能的時候,Automatic Reference Counting (ARC) 誕生了。
ARC 是一種在編譯期間時運作的技術。這項技術的工作便是在程式碼編譯的時候分析原始碼,並且在適當的位置填補、加入記憶體管理的程式後才進入編譯的階段。也就是:release, retain, autorelease 這些老朋友,即使你不去寫,他也會自己幫你加入。其實,你甚至沒有辦法再繼續使用這些過去與我們朝夕相伴的方法了,在啟用 ARC 之後,新的編譯器會直接對這些老兵們報錯。可憐他們只有離去一途。
所以說,撰寫 ARC 程式碼!就是:少寫一些 Objective-C 的程式碼!
以下是四點我們將舊有的程式改為 ARC 的方法:
1. 移除掉所有的 retain, release, autorelease
2. 修改 property,將 retain 改成 strong,將 assign 改成 weak
3. NSAutoreleasePool class 無法繼續使用,改用 @autoreleasepool 語法
4. 移除回傳 block 時所用的 copy autorelease
ARC 除了上述講的優點之外,他還有其他的優勢存在。
使用 ARC 所產生的程式碼,將會較原先的程式碼執行速度還要快速:
NSObject retain/release -- 2.6x faster
@autoreleasepool -- 6x faster
objc_msgSend -- 33% faster
你有什麼原因不用它呢?
下一篇:深入探討 ARC
指標動態產生陣列的兩三事
張貼者:
Ehrippura
|
7/04/2012
星星,其實是指標
對大多數程式設計師而言,是能不用就不用的東西。其實先進的程式語言,幾乎都會把指標這種東西排除在外。最主要的原因不外乎就是它難以駕馭的問題;只要稍有疏失,就可能導致整個應用程式不穩定。其實今天這篇文章要談的不是該怎麼用指標的,而是使用指標分配二維陣列記憶體的問題。因為這個地方很容易產生一個嚴重的迷思。
相信大家都知道,用單一指標、再分配某個變數實質佔有空間的乘積之後,變成了如同陣列一般的區塊。
好比如說,我們希望有一個 int [5] 的空間,這裡就會用:
int *a = malloc(sizeof(int) * 5) 來宣告。
當然,不要忘記要釋放:free(a);
那,如果我希望有個 int [5][5] 的空間呢?
喔,不就是雙重指標嗎?
所以就是:
int **a = malloc (sizeof(int) * 5 * 5);
簡單嘛!
錯,而且錯很大,錯到你可能 de 不出 bug 在哪邊。
這也是很多人會犯下的錯誤。
我們把動作拆開來看第一項,當我們想要產生 int [5] 的時候
我們把 int *a 的星號拿掉,成了我們要產生的目標:int,所以我們用 malloc (sizeof(int) * count)。所以換到了雙重指標的時候,int **a 要產生的目標應該是:int *。然後才是 int * 要產生的目標:int。
所以程式碼應該是
int **a = malloc (sizeof(int *) * 5);
for ( int i = 0; i < 5; i++ )
*(a + i) = malloc ( sizeof (int ) * 5 );
當然,如果你真的要這樣寫,到時候要 free 的時候會瘋掉,但也是保險的作法。為什麼?
因為我們把程式合併起來,整個程式碼是:
int **a = malloc (sizeof (int *) * 5 + sizeof (int) * 5 * 5)
請注意,這裡空間雖然分配了,可是你實際在使用的時候,因為要保證所有 int ** 底下的 int * 所指的位置,所以很容易指錯位置,所以上述的方法是比較保險的。
真複雜?沒錯,超級複雜的。
看完有沒有一堆星星在繞呢?
對大多數程式設計師而言,是能不用就不用的東西。其實先進的程式語言,幾乎都會把指標這種東西排除在外。最主要的原因不外乎就是它難以駕馭的問題;只要稍有疏失,就可能導致整個應用程式不穩定。其實今天這篇文章要談的不是該怎麼用指標的,而是使用指標分配二維陣列記憶體的問題。因為這個地方很容易產生一個嚴重的迷思。
相信大家都知道,用單一指標、再分配某個變數實質佔有空間的乘積之後,變成了如同陣列一般的區塊。
好比如說,我們希望有一個 int [5] 的空間,這裡就會用:
int *a = malloc(sizeof(int) * 5) 來宣告。
當然,不要忘記要釋放:free(a);
那,如果我希望有個 int [5][5] 的空間呢?
喔,不就是雙重指標嗎?
所以就是:
int **a = malloc (sizeof(int) * 5 * 5);
簡單嘛!
錯,而且錯很大,錯到你可能 de 不出 bug 在哪邊。
這也是很多人會犯下的錯誤。
我們把動作拆開來看第一項,當我們想要產生 int [5] 的時候
我們把 int *a 的星號拿掉,成了我們要產生的目標:int,所以我們用 malloc (sizeof(int) * count)。所以換到了雙重指標的時候,int **a 要產生的目標應該是:int *。然後才是 int * 要產生的目標:int。
所以程式碼應該是
int **a = malloc (sizeof(int *) * 5);
for ( int i = 0; i < 5; i++ )
*(a + i) = malloc ( sizeof (int ) * 5 );
當然,如果你真的要這樣寫,到時候要 free 的時候會瘋掉,但也是保險的作法。為什麼?
因為我們把程式合併起來,整個程式碼是:
int **a = malloc (sizeof (int *) * 5 + sizeof (int) * 5 * 5)
請注意,這裡空間雖然分配了,可是你實際在使用的時候,因為要保證所有 int ** 底下的 int * 所指的位置,所以很容易指錯位置,所以上述的方法是比較保險的。
真複雜?沒錯,超級複雜的。
看完有沒有一堆星星在繞呢?
Finder 以及音樂檔案 Artwork 的問題
張貼者:
Ehrippura
|
3/13/2012
大獅子,更新之後部分使用者發生 Finder 沒有辦法顯示在 iTunes 設定的音樂圖片的問題。其實這個問題也困擾了我好一陣子。蘋果本身也不斷地推出 iTunes 的更新,卻依然不見這個問題解決。
正當我打算要傳灌之前,我把 iTunes 的資料庫導向另外一個資料夾,讓 iTunes 重建一個新的資料庫,結果,以前本來沒有顯示專輯圖片的檔案圖示突然就這樣正常了!!我再嘗試把轉回原本的資料庫,依然可以正常運作。 (當我這麼想的時候卻不是這樣)
太好了!省下重灌的時間!
How to create new iTunes Library?
Press option key and launch iTunes application than select Create new Library.
修正
結果沒想到卻還是回到 icon 消失的老樣子。不過既然重新產生資料庫可以解決問題,我就先把現有的資料庫輸出,然後移動檔案夾之後,在 Music 下面產生一個同名的 iTunes 資料庫,把檔案移動回去,再匯入資料庫。
看來這次應該是把問題給解決了!
正當我打算要傳灌之前,我把 iTunes 的資料庫導向另外一個資料夾,讓 iTunes 重建一個新的資料庫,結果,以前本來沒有顯示專輯圖片的檔案圖示突然就這樣正常了!!
太好了!省下重灌的時間!
How to create new iTunes Library?
Press option key and launch iTunes application than select Create new Library.
修正
結果沒想到卻還是回到 icon 消失的老樣子。不過既然重新產生資料庫可以解決問題,我就先把現有的資料庫輸出,然後移動檔案夾之後,在 Music 下面產生一個同名的 iTunes 資料庫,把檔案移動回去,再匯入資料庫。
看來這次應該是把問題給解決了!
訂閱:
文章 (Atom)