Use delegate methods, Luke.

有時候看一些討論區裡頭的內容,實在讓人不禁眉頭一皺。比方說,你看到有人問了這樣一個問題-

如果我有一個NSArray存放不固定數量的CGPoin,這些Point在drawRect中都被用來當作是draw的data,但其實這些點也要被某個我的Controller class來增減或改變。

請問這些data object(NSArray contain CGPoint),是放在View的class底下比較好, 還是放Controller的class底下,比較好ㄋ?

然後馬上出現的回應是:

其實你高興就好, MVC 不是強制的, 也有很多灰色地帶
是我的話這類東西通常放在 view, 不過那是我

是啦,雖然不是說不照某種方法設計,程式就會動不了,但是在直接跳到「MVC不是強制的」這種意見之前,是不是忽略了幾個討論-如果是用 MVC 的設計,應該要怎麼做,這種需求難道用 MVC 的方法沒有辦法解決嗎?蘋果自己是怎麼處理這樣的狀況?

另外一個很大的問題是-你是使用者的話,你會敢用抱持著「高興就好」的開發者寫出來的東西嗎?…

Continue reading

Cocoa/iPhone App 的 Debug

什麼程式都會有問題,而在寫 Cocoa/iPhone 程式的時候要 debug,最好還是先看一下蘋果的Xcode Debugging Guide這篇文件,這裡就只就一些最常見問題簡單寫一寫。

在開發 Cocoa/iPhone 應用程式的時候,如果你的程式 crash,QA Team 的成員很高興地把問題列成p1 bug 的時候,就個人遇到的狀況來說,有高達八成的機率(台灣電視記者的口氣),Xcode 會告訴你是以下三種問題-Out of Bound、Bad Access、Unsupported Selector。說起來都是很基本的錯誤,但是基本的錯誤並不代表是不會犯、或不常犯的錯誤,而且機率有高達八成之多。

Cocoa 應用程式有的時候就只會告訴你程式有 exception,接下來的 code 頂多就是不跑,至於 iPhone 上面就是直接炸掉給你看。而在這八成之外的另外兩成,則是各種稀奇古怪的問題了。

Continue reading

ASCII Art 產生器(Mac OS X 用)

前兩天心血來潮寫了一個小東西-ASCII Art 產生器(下載)。顧名思義,這個小東西就只有那麼一個功能-把圖片檔案轉換成以文字構成的 ASCII Art。

照理說應該 10.4 以上的麥金塔電腦就可以用(不過我現在手邊沒有安裝 10.4 的機器,所以我只能保證在 10.5 與 10.6 可以用);程式碼都在 Github 上,如果想要自行編譯,您需要安裝 Xcode 3.0 以上版本(不過我現在用的不是 3.0,用的是 3.1.4…反正去找最新的 Xcode 來用就對了。)

WebKit 對於開啟新視窗事件的處理

如果想要在網頁中插入開啟新的瀏覽器視窗的語法,有兩種簡單的作法,一種是直接在連結語法中加入 target=”_blank”,例如 <a href="http://zonble.net/" target="_blank">,另外一種方法則是呼叫 Javascript 的 window.open() 函式。

而雖然這兩者的目的是開啟新的瀏覽器視窗,但是在當你在寫一個使用了 WebKit 的 Cocoa 應用程式的時候,對於這兩個事件,則需要分別給予不同的實作-在 WebView 物件中觸發前者時,WebView 會去呼叫 Policy DelegatewebView:decidePolicyForNewWindowAction:request:newFrameName:decisionListener: 這個 Method,但是後者-Javascript 的 window.open()-則會跳過 Policy Delegate,直接向 UI Delegate 呼叫 webView:createWebViewWithRequest:

意思就是,在使用者在你的應用程式中的 WebView 中,點選了一個包含 target=”_black” 的連結的時候,WebView 首先會詢問你所指定的 Delegate Object,然後你可以根據狀況判斷,而做出對應的處理-應該開新視窗、開新的瀏覽器分頁(如果你寫的是一套具備分頁功能的瀏覽器應用程式)、或是使用系統預設的瀏覽器開啟。

但是遇到 window.open() 則不然,這個狀況是-事件發生的 WebView 已經決定要因此產生新的 WebView 物件,你需要在 webView:createWebViewWithRequest: 的實作中,回傳一個 WebView 物件,而這個 WebView 物件就會開始載入 window.open() 所傳入的、那個要開啟的 URL。而我們會在這個地方遇到一個問題-基本上我覺得應該算是蘋果的 Bug-在 webView:createWebViewWithRequest: method 中所傳入的那個 NSURLRequest 物件,居然是 NULL!

Continue reading

Bunt

一年多前我寫了一個小工具,叫做 colorBy.colorPicker,這個工具的目的在於解決在開發 Cocoa 應用程式的時候,撰寫跟色彩有關的程式的麻煩-比方說,當你需要一個 NSColor 物件的時候,你都必須要花點時間,把你看到的一組顏色,換算成對應到 HSBA 或 RGBA 的小數。不過,今天回頭看這個程式,在設計上有幾個問題-

一、在這個程式寫出來到現在,這段時間裡,Mac Developer 又多了一種跟色彩有關的物件要處理,叫做 UIColor,因為 UIKit 出來了嘛…。

二、原本的程式是寫成 Mac OS X 的系統 Color Picker,之所以寫成 Color Picker,原本是以為這樣就可以在各種文書編輯軟體裡頭-BBEdit 啦、TextMate 啦還是 SubEthaEdit,都可以叫出這個工具,因為大概只有 Color Picker 與輸入法可以算是平台上所有應用程式都可以用的外掛工具(plugin)。

但經過一年多再回來看,這種考量其實完全沒有必要,所有的開發工作往往都是在 Xcode 完成,而麻煩的地方就在,Xcode 裡頭實在找不到什麼地方可以把系統 Color Picker 叫出來。

因為這兩個原因,前兩天決定把這個工具整個重寫一次。新版的名稱叫做 Bunt,專案放在 GitHub 上:http://wiki.github.com/zonble/bunt,您可以直接取得程式碼自行編譯。簡單來說,差別在於-

一、Bunt 現在是獨立的 Cocoa 應用程式,而不再是系統 Color Picker,在啟動之後,就會出現在畫面右上角,需要的時候,用切換應用程式的方式切換過去就可以了。

二、除了原本就支援的 NSColor、Quartz Drawing 的 ColorRef 外,加入了產生 UIColor 與 OpenGL 的顏色的功能。

歡迎取用。

怎樣限制 Mac OS X 表格中編輯區中的輸入字數

這篇文字來自 22 日晚間我在台北 Cocoaheads 活動中所分享的一個題目。

在講完之後,有些朋友覺得講得速度似乎有點快,而我回來之後看了一下自己的投影片,總感覺如果只是將投影片放在網路上,可能根本不知道我在說什麼,而更大的問題是,回來之後又做了一點小研究,發現有個地方講錯。看來,要在網路上分享這則故事,還是要換成比較詳盡的文字。

楔子

故事是這樣的。

一兩個月前,公司正在承接製作國內某知名輸入法廠商的 Mac OS X 版本的工作,專案的其中一環,是要製作一個使用表格輸入介面的自定字詞編輯工具-基本上就是在主視窗當中有一個表格,第一欄是自定詞的拆碼(或字根),第二欄則是這組拆碼所對應到的字詞。-當你在使用 Cocoa Framework 開發的時候,要使用表格介面,你當然會毫不猶疑的使用 NSTableView 物件。

因為這套輸入法的規則是,所有文字的打法最大只會有五碼,所以,在輸入或修改拆碼這個欄位的時候,如果使用者已經打了五個字元,就不應該繼續輸入。這件事情在 Windows 上面很簡單-如果你是寫一個 .Net 程式,你只要寫上一行,設上 DataGridViewTextBoxColumn.MaxInputLength (MSDN 文件)就好了,還可以在 IDE 中直接使用 GUI 設定;但是,在 NSTableView 的文件中,則是完全找不到對應的設定。

另外,客戶也要求,在按下 Enter 的時候要寫入資料,按下 ESC 按鍵的時候,則是要取消編輯狀態。如果是在 Mac OS X 10.5 上面,用 Interface Builder 拉好了一個 NSTableView,基本上這個 table view 在編輯狀態時,按下 Enter 就會完成編輯,這是我們要的,然而,如果按下 ESC 按鍵,預設卻是出現 Auto-complete 選單,幫你做些英文拼寫檢查之類的;至於在 10.4 上面,則是無論按下 Enter 或是 ESC,都不會理你…。

顯然在這個部分,也需要對 NSTableView 做一定的客製。

Continue reading