2009年10月31日 星期六

2009年10月30日 星期五

2009年10月29日 星期四

Leopard 捷徑

要在 Leopard 建立捷徑,只要在圖示上按右鍵,再選擇 Alias 即可。

2009年10月22日 星期四

XCode 小秘技(三)

在 XCode 裡有一個名叫 Guard Malloc 的功能。它主要在程序運行時,檢查有沒有使用到非法的記憶體空間。經過試驗之後,發覺非常好用;唯一的問題是執行效率下降了不少,使得整個過程都慢起來。所以,我只會在有需要時才打開它。

2009年10月20日 星期二

XCode 小秘技(二)

一直以來,我都有把 iPhone 專案內使用到的檔案以 Group 的方式分門別類;主要是方便管理及使用。但在編譯成為 IPA 後,原本按 Group 整整齊齊分類的檔案都會變得散亂地放在 IPA 內應用程式的根目錄。我一直都想解決這個問題!

現在由我開發的角色扮演遊戲,已經包含上 2500 張圖片及資料檔案,更需要清清楚楚地分門別類。我嘗試了很多次都無法成功,也找不到類似的功能;最後發現,原來先在 Finder 建立起資料夾,把相應的檔案放進去,並把資料夾拖拉到 XCode 左方檔案清單的 Resources 內;這時會有一個視窗彈出,選擇 Create Folder References for any added folders 即可。而該資料夾的圖示亦會由正常 Group 分類的黃色,變成藍色。這樣編譯出來的 IPA 便會出現該資料夾及檔案。

2009年10月19日 星期一

XCode 小秘技

在開發大型軟件時,為了在最快的時間內創造出一點成果,很多時都會先建立程序框架及其部份內容;而較為複雜細微的部份會在較後的時間去實現。我習慣在相關部份加入 TODO: 註解。在 IDE 的上方會有一個快速函數跳轉功能,原來 XCode 對於「TODO:」會有特別處理。在這個快速函數跳轉功能內也會顯示「TODO:」的內容,而且還以粗體顯示,十分方便。

2009年10月16日 星期五

替 Function 換名

對於日漸壯大的代碼,有時會想到把某些功能函數換過一個更合適的名字,但考慮到在現時千絲萬縷的連結下,若利用 Search & Replace 的話,錯誤的風險會很高。

原來在 XCode 下有著一個名為 Refactor 的功能,可以有效地處理以上問題。只要在功能函數上點選滑鼠右鍵,便會彈出如左圖般的選單。點選 Refactor 後輸入新的函數名稱,切記要輸入冒號!按 Preview 後會出現將要修改的地方,同時 Preview 按鈕也會變成 Apply 按鈕。其中 Snapshot 是打勾了,這個是備份功能,方便還原之用;但會把整個 Refactor 進程拖得很慢,我通常都會把它關掉!反正 Refactor 之後的代碼不會立即儲存。最後就是按 Apply 啦!

2009年10月15日 星期四

Shadow warnings!


今日花了半天時間找 Bug,到最後原來是因為使用了一個跟 Class member 同名的 Variable 而導致!這個錯誤已經是連續第二天犯下,為免再重蹈覆徹,決定要有效地找出相同的 Variable 名稱。做法很簡單!在 XCode 內 Build Configuration 內的 Other Warning Flags 加入 -Wshadow,代碼在編譯時會找出定義了相同 Variable 名稱的地方,給編程人員一個警告。

2009年10月9日 星期五

AppleScripts 處女作



最近工作上的關係,很想在 Leopard 上把大批大批的檔案改名。這個在 Windows 上很簡單的一個指令(ren *.m *.x),卻在 Leopard 上成為難題。雖然我可以用 Windows 來處理這個工作;但在 Leopard 下進行開發,始終想找個解決方法。原來網上也有很多朋友遇到相同的情況!他們多會改用軟件處理(居然連改名都會出一個專用軟件),而我不想下載及安裝,便決定改為使用 AppleScripts 來代替。它是內建在 Leopard 之內,所以不用安裝,而且是免費!我是第一次接觸 AppleScripts。發現它很像英語,單憑指令語句來學習,真是一頭霧水!花了兩個小時,我最後都能編寫出批次修改副檔名的 AppleScripts 了!
 
------------------------------------------------------------------------------
-- Rename File Extension script
-- Program by Pacess HO
-- 2009-Oct-09 22:30
------------------------------------------------------------------------------
try
-- Set focus to the top folder window
-- And put the path to "sourceFolder"
tell application "Finder" to set the sourceFolder to (folder of the front window) as alias

on error
-- In case no open folder windows, show an error message
display dialog "Please select a folder first and then run script again." with icon caution buttons {"Finish"}
beep 2
return
end try

-- Enter the existing file extension
repeat
display dialog "Enter the extension want to be replaced" default answer "m" buttons {"Cancel", "OK"} default button 2
set the oldExtension to the text returned of the result
if the oldExtension is not "" then exit repeat
end repeat

-- Enter the new file extension
repeat
display dialog "Enter the NEW extension" default answer "x" buttons {"Cancel", "OK"} default button 2
set the newExtension to the text returned of the result
if the newExtension is not "" then exit repeat
end repeat

-- Put files in "sourceFolder" to "fileList"
set the fileList to list folder sourceFolder without invisibles
set sourceFolder to sourceFolder as string

-- Process each file
repeat with i from 1 to number of items in the fileList
set thisFileAndPath to item i of the fileList
set thisFileAndPath to (sourceFolder & thisFileAndPath) as alias
set thisFileInfo to info for thisFileAndPath

-- Remove the path and remain filename with extension
set the thisFileName to the name of thisFileInfo

-- Just process the file which is not a folder or alias
if folder of thisFileInfo is false and alias of thisFileInfo is false then

-- Is it end of old extension?
if the thisFileName ends with the oldExtension then

-- Get the length of old extension
set the nameLength to the number of characters of the oldExtension

-- Remove the old extension
set the newFileName to (characters 1 thru -(the nameLength + 2) of the thisFileName) as string

-- Add the new extension
set the newFileName to the (the newFileName & the "." & the newExtension) as string

-- Rename
tell application "Finder"
try
set the name of thisFileAndPath to the newFileName
end try
end tell

end if
end if
end repeat
beep 2

2009年10月7日 星期三

靈活調動 UITableView 項目的方法

由於 Unit Test 的項目漸漸增加,而某些項目的使用頻率增加了;為了方便起見,我需要能靈活調動項目的次序,以及其相對應的 viewController。

首先在 loadView 內定義好一個 NSArray,內裡包含了項目名稱及其 viewController 的類:

// Prepare menu items
menuList = [[NSArray alloc] initWithObjects:
@"Test 1", [Test01Controller class],
@"Test 2", [Test02Controller class],
@"Test 3", [Test03Controller class],
@"Test 4", [Test04Controller class],
@"Test 5", [Test05Controller class],
@"Test 6", [Test06Controller class],
@"Test 7", [Test07Controller class],
nil];
之後在 didSelectRowAtIndexPath 中加入以下指令:

//-------------------------------------------------------------------------------
// Respond to user selection
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)newIndexPath {
UIViewController *viewController;

int itemSelected = [newIndexPath row];
int index = (itemSelected<<1)+1;
Class thisClass = [menuList objectAtIndex:index];
viewController = [[thisClass alloc] init];
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];
}
這樣,日後要更改項目的次序時,只要修改 menuList 中的排位即可;要新增項目時,在 menuList 中加入即可。

2009年10月6日 星期二

搜尋應用程式目錄下的檔案

今天我為 Unit Test 的 Java UTF Text 測試進行了更新;把原本放在 UIPickerView 的固定地圖檔名改為即時在應用程式目錄下搜尋出來。

// Search png file names
NSString *resourcePath = [[NSBundle mainBundle] resourcePath];
mapFileList = [[[[NSFileManager defaultManager] directoryContentsAtPath:resourcePath] pathsMatchingExtensions:[NSArray arrayWithObject:@"png"]] copy];
搜尋出來的檔名會包含了檔案類別名稱,在使用到 pathForResource 時便要把它刪除,可使用以下指令:

// Remove file extension .png
NSString *fileName = [pngFileName stringByDeletingPathExtension];
NSString *filePath = [[NSBundle mainBundle] pathForResource:fileName ofType:@"png"];
if (filePath == nil) {return @"Error";}

2009年10月5日 星期一

設定公司名稱的方法

在 XCode 內新增新代碼檔案時,在頂方都會出現 __Company_Name__ 字眼,一直都想更正這個問題,今日給我找到了答案。其中一個方法是在 Terminal 輸入
defaults write com.apple.Xcode PBXCustomTemplateMacroDefinitions '{ORGANIZATIONNAME="CompanyNameHere";}' 
即可。