highlight.js

星期四, 10月 18, 2012

callback 到底應該怎麼翻?

由於現在越來越多程式語言或是框架 (framework) 強調非同步技術, 使得 callback 躍登熱門詞彙, 不過這個詞倒底要怎麼翻成中文, 可有點傷腦筋。過去有的人不翻, 有的翻為「回呼函數」, 這我個人認為無法達意;我也看過有作者翻成「回撥函數」, 這取材自回撥電話的意思 , 意思是到了, 但是在程式設計的語句中唸起來就是怪怪的。前幾天讀何孟翰先生寫的《超強圖解 前進 App Store!iOS6 SDK 實戰演練》一書, 他譯為「回應函數」, 我覺得真不錯, 既能達意, 夾在文句中唸起來也不會繞口, 趕緊記下來, 往後就用這個說法。

星期五, 10月 12, 2012

IBOutlet 與 IBAction 到底是什麼?

在學習 iOS 開發的時候, 一定會遇到的就是 IBOutlet 與 IBAction, 這兩個其實是定義在 UIKit 的 UINibDeclarations.h 中的 macro, 定義如下:
#ifndef IBOutlet
#define IBOutlet
#endif 
#ifndef IBAction
#define IBAction void
#endif
從定義可以看出來, IBOutlet 與 IBAction 對於程式碼沒有實質的意義, 存在的作用只是像是標籤一樣, 標示了程式碼中的某個屬性可以用來對應到介面上的某個同樣類別的元件, 或是某個方法可以用來回應規格相符的事件。

星期四, 10月 11, 2012

Xcode 4.5 自動產生 IBOutlet 屬性的改變

前天想說編輯的書最後還是應該用 Xcode 4.5 校稿才對, 結果一升級之後今天測試了一下, 發現了一個討厭的問題, 就是在自動產生 IBOutlet 的屬性時, 在對應的成員變數的命名上不一樣了, 這樣一來, 不就得要改書中的內文以及程式了?

以前如果在 Interface Builder 上從一個 UILabel 產生 IBOutlet 屬性, 假設取名為 myLabel, Xcode 會在 ViewController.h 檔中產生以下這行 @property 指令:
@property (weak, nonatomic) IBOutlet UILabel *myLabel;
同時在 ViewController.m 檔中產生對應的 @synthesize 指令:
@synthesize myLabel;
這樣在 ViewController.m 中就可以直接以 myLabel 操作對應的元件。但是在 Xcode 4.5 中, 已經不會產生 @synthesize 指令, 這會導致編譯時由編譯器自動以如下的 @synthesize 敘述幫你合成 getter 與 setter 方法:
@synthesize myLabel = _myLabel;
也就是將對應的成員變數以你指定的屬性名稱加上 "_" 為字首命名, 使得屬性名稱與對應的成員變數名稱變成不一樣了, 因此無法以 myLabel 操作元件, 而必須加上 self  以 self.myLabel 才能操作對應的元件。當然, 也可以直接使用變數, 但這樣除了違背封裝的意圖, 也會使用到程式中沒有出現過得變數。這下子, 書中原本的程式以及解說的內容都得一併修改, 真是麻煩了。

當然, 這樣的變更主要是為了符合良好的程式撰寫習慣, 讓屬性與成員變數能夠明確地區分開來, 不過能不能有個選項讓我可以選擇要不要接受這樣的改變啊?

PS:如果需要, 還是可以自行把 @synthesize myLabel; 加回去, 只是多一道工, 而且對我來說, 變成還要額外解是為什麼要這樣做, 更是麻煩!

星期一, 10月 08, 2012

關掉 Mac 開機的『登』聲音

不知道有沒有人跟我一樣覺得很困擾, 不想要再 Mac 開機時聽到一聲『登』, 尤其是在特定的場合, 『登』一聲實在很尷尬。網路上查了一下, 最簡單的方法就是裝個小工具, 設定開機時不啟用音效, 或是靜音, 我自己試過在 10.7.4 上使用 StartNinja, 可以完美達成任務, 其他有些軟體可能因為 Mac OS 版本的關係, 無法成功。

除了安裝工具軟體外, 也可以參考這一篇問答中 Acid 的回覆, 使用 AppleScript 加上開機與關機的 script, 在關機時設定喇叭靜音, 並在開機完成後設定喇叭恢復原始音量, 這樣就可以在開機時不會聽到『登』的聲音, 但開機後一樣可以聽到正常的聲音了。

星期六, 10月 06, 2012

Objective-C 的協定 (Protocol)

前幾天在看 iOS 開發的翻譯書稿件, 注意到一件奇怪的事。在使用 UIAlertView 的時候, 有些書都沒有強調擔任 UIAlertView 的委派物件必須遵守 (conform) UIAlertViewDelegate 協定。因此, 如果是由 controller 擔負委派物件時, controller 的類別大概會是這樣:
@interface ViewController : UIViewController
    ....
- (void)alertView:(UIAlertView *)alertView
    clickedButtonAtIndex:(NSInteger)buttonIndex {
    .....
}
@end
事實證明, 這樣的確是可以運作, 連個編譯的錯誤訊息都沒有。當使用者點選了 UIAlertView 上的按鈕時, 的確會引發 clickedButtonAtIndex。

但若是使用 UIActionSheet 時, 書中卻又強調委派物件必須遵守 UIActionSheetDelegate 協定。因此, 如果一樣由 controller 擔任委派物件時, controller 類別大概會長這樣:
@interface ViewController :
        UIViewController<UIActionSheetDelegate>
.....
- (void)actionSheet:(UIActionSheet *)actionSheet
        clickedButtonAtIndex:(NSInteger)buttonIndex {
.....
}
@end
實在覺得很奇怪, 兩個元件的 pattern 其實是一樣的, 但為甚麼一個需要明確標示遵守協定, 另一個卻不用?經過 google 找到這一篇 Why do I not need to declare UIAlertViewDelegate in the header?, 看起來原因有兩個:
  1. 在建立 UIAlertView 的  initXXX 方法中, delegate: 的型態是 delegate:(id), 並沒有要求委派物件必須遵守任何協定。但是在建立 UIActionSheet 的 initXXX 方法中, delegate: 的型態卻是 delegate:(id < UIActionSheetDelegate >), 表示委派物件應該要遵守 UIActionSheetDelegate 協定。
  2. 在 Objective-C 中, 協定的角色似乎沒有其他種類物件導向語言中的界面 (Interface) 那樣嚴謹。事實上, 如果擔任 UIActionSheet 的委派物件並沒有遵守 UIActionSheetDelegate 協定,  只要實作有正確的 clickedButtonAtIndex: 方法, 程式一樣可以動, 只是編譯時會有警告訊息而已。而在 framework 的實作中, 看來也都是以透過 respondsToSelector:@selector(delegatedMethod:) 檢查委派物件是否具有指定的方法, 才會實際叫用該方法, 而不是依靠是否遵循特定的協定來判斷。
換句話說, 協定就只是給大家參考的規格書, 而不是像是其他語言中的界面那樣嚴格。 

星期四, 10月 04, 2012

為 Windows 7 中的 XP Mode 虛擬硬碟檔搬家

前幾天因為公司的電腦硬碟不大, 結果 C 碟空間太少, 連想裝個 Visual Stdio 2012 Express for Desktop 測試都不夠, 仔細檢查了 C 碟的空間, 怎麼算都覺得至少還可以多個 6GB 左右, 但是就是找不到這個空間被誰戰掉了。巡視一遍後,終於找到原來是 XP Mode 的虛擬硬碟檔案就佔了 6 GB 多, 直覺認為, 不就把它搬到其他磁碟就搞定了!

不過第一個遇到的問題是 XP Mode 都是以休眠的方式暫停, 而且在開始功能表中只有『登出』沒有『關機』, 不能關機就沒法更動虛擬硬碟檔案。還有 Virtual PC 功能表上有 Ctrl+Alt+Del 功能, 可以讓 XP 顯示『Windows 安全性』交談窗, 就可以把 XP 關機了。

接著第二個遇到的問題是, XP Mode 的硬碟虛擬檔不是單一檔案, 而是由一個基本硬碟虛擬檔延伸而來, 經過 Google 大神幫助, 找到了這一篇 Transferring/Moving a VHD from Windows Virtual PC (Windows XP Mode) to another computer , Virtual PC 本身就提供把分開的兩個硬碟虛擬檔合併的功能, 只要在硬碟設定的地方按『變更』, 就有合併虛擬硬碟的功能, 而且還可以直接將合併的結果儲存到別的位置, 這樣就可以把虛擬硬碟檔搬走了。

就這樣, 我就讓 C 碟空出了許多空間, 又可以亂裝軟體惡搞了。