0

所有權

| 1/30/2013
物品所有權的問題其實是很微妙的

案例 1.
你今天去買了音樂光碟,會說:我買了周杰倫的新歌。
你今天買了 Windows 光碟,說:我買了 Windows。
問題是:你真的買到了這些東西嗎?
答案是否定的,因為你買到的東西其實是使用權。

案例 2.
二手市場
對廠商而言,二手市場其實是個相當的痛。尤其是音樂、電影、遊戲。廠商在二手市場上面並沒有辦法因為使用者的購買行為取得到利益。許多使用者認為:我今天買了正版的軟體、影音等,是合法使用者

但是廠商不這麼認為!

很多使用者認為,只消我沒有修改這些東西的內容,我把東西拿到二手市場上面去賣有什麼錯誤?因為這個影片光碟是我買的,廠商無權管我!

嗯,聽起來似乎很合理,意思是說,我今天把光碟的內容截取下來,放在網路上面也沒錯了喔?
0

[MyClass alloc]

| 1/29/2013
大家都知道 [MyClass alloc] 這個方法分配了物件的記憶體空間

這陣子看到一個很英勇的用法
我不知道這樣子使用會不會變的比較快,不知道有沒有人想要實驗看看的。


// 先取得 class
Class myclass = objc_getClass("MyClass") ;
// 取得 class 的大小
size_t classSize = class_getInstanceSize(myclass);

// 建立物件指標,並且分配記憶體空間
MyClass *obj = (MyClass *)calloc(1,  classSize);
// 設定 isa
obj->isa = myclass;
// 初始化
[obj init];

這到底是哪招呢?
0

Automatic Reference Counting

| 12/27/2012
我們這裡來考慮一下一個堆疊的程式碼:
@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

0

指標動態產生陣列的兩三事

| 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 * 所指的位置,所以很容易指錯位置,所以上述的方法是比較保險的。

真複雜?沒錯,超級複雜的。
看完有沒有一堆星星在繞呢?

0

Finder 以及音樂檔案 Artwork 的問題

| 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 資料庫,把檔案移動回去,再匯入資料庫。

看來這次應該是把問題給解決了!