星期四, 四月 22, 2010

Cocoa 手勢支援

在 Macbook Air 推出之後,Apple 就多了手勢操作這項功能,但是這項功能雖然在 10.5 就有了,不過卻直到 10.6 才在 Apple 的 Document 中出現。而要在 10.5 中使用這項功能的話,其實也很簡單,只要實作 10.6 的 Document 裡面出現的幾項 method 即可,也就是下面五個 method:
  • - (void)magnifyWithEvent:(NSEvent *)event;
  • - (void)rotateWithEvent:(NSEvent *)event;
  • - (void)swipeWithEvent:(NSEvent *)event;
  • - (void)beginGestureWithEvent:(NSEvent *)event;
  • - (void)endGestureWithEvent:(NSEvent *)event;
不過除非要自己抓取新的手勢,不然主要只要實作 magnifyWithEvent、rotateWithEvent、swipeWithEvent 這三個即可。

這三個手勢的詳細操作,可以參考 10.6 的 Document,在 10.5 都相容,只有 magnifyWithEvent 要特別處理一下。

magnifyWithEvent 的標準用法如下(Apple Document):
- (void)magnifyWithEvent:(NSEvent *)event {
[resultsField setStringValue:
[NSString stringWithFormat:@"Magnification value is %f", [event magnification]]];
NSSize newSize;
newSize.height = self.frame.size.height * ([event magnification] + 1.0);
newSize.width = self.frame.size.width * ([event magnification] + 1.0);
[self setFrameSize:newSize];
}
但是在 10.5 上,NSEvent 沒有 magnification 這個 method,所以必須自己擴充,code 如下(ref):
#pragma mark defines for 10.6 api not documented in 10.5
#ifndef MAC_OS_X_VERSION_10_6
enum {
/* The following event types are available on some hardware on 10.5.2 and later */
NSEventTypeGesture = 29,
NSEventTypeMagnify = 30,
NSEventTypeSwipe = 31,
NSEventTypeRotate = 18,
NSEventTypeBeginGesture = 19,
NSEventTypeEndGesture = 20
};

@interface NSEvent(GestureEvents)
/* This message is valid for events of type NSEventTypeMagnify, on 10.5.2 or later */
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 - (float)magnification; // change in magnification. #else - (CGFloat)magnification; // change in magnification. #endif @end #endif

這段 code 也把 10.5 中 NSEvent 欠缺的 type id 補齊了,所以如果想要支援手勢操作,最好都把這段 code 貼上來用吧。

標籤: ,

星期三, 五月 27, 2009

更改 Xcode 範本的 __MyCompanyName__ 這個變數

Xcode 產生的原始碼,都會在檔頭加入版權宣告,雖然作者名字會自己抓到,不過用了這麼久,一直沒找到在哪設定 __MyCompanyName__。

前兩天窮極無聊 Google 了一下,原來在 Xcode 裡面不能設定,要用終端機直接改 plist 設定值...

在終端機輸入以下指令:
defaults write com.apple.Xcode PBXCustomTemplateMacroDefinitions -dict ORGANIZATIONNAME "Your_Name_Here“
然後重開 Xcode 就可以了。

標籤: ,

星期日, 五月 24, 2009

用 Objective-C 從二進位檔案(binary file)中讀入數值的 byte order 問題

要從二進位檔案中讀入數值,其中一個會遇到的問題就是 Little-endian 和 Big-endian,這和 CPU 的種類有關。Intel 系列的 x86 CPU 使用的是 Little-endian,而 PowerPC、ARM 等的 CPU 則是採用 Big-endian。endian 不同的問題,在以前 PPC 的時代算是相當重要,後來改用 Intel CPU 之後重要性就下降了許多,不過現在因為 iPhone 採用的 ARM 又是 Big-endian,所以這問題的重要性又大幅提升了,尤其許多新手設計師,之前可能根本沒碰過非 Intel 的平台,根本沒考慮過這問題,於是寫出來的程式就會讀到一堆詭異的數字。

首先我們要先界定 endian 的問題會影響到哪些資料型別。所謂 endian 不同,是因為高低位元在記憶體中表示的方式不同而造成的,Little-endian 將高位元放在記憶體位址較大的地方,Big-endian 則反之。舉例來說,0x00112233 這個 16 進位的數字,在 Little-endian 的機器上,在記憶體中呈現的是 33 22 11 00,而在 Big-endian 的機器上則呈現 00 11 22 33。因此,假如把在 Little-endian 機器上寫入的二進位檔拿給 Big-endian 的機器讀取,讀出來的數字就會出錯。

從這邊我們可以發現,要發生 endian 的問題,首先資料型別必須用超過 2 個 byte 來儲存才有可能,因此只用一個 byte 儲存的型別,例如 char,就沒有 endian 的問題。

至於 int、long 之類的整數型別,可以用 CFSwap[type][Big/Littile/Host]To[Big/Littile/Host] 系列函式來轉換。其中的 type 可能是 Int16、Int32 等等。使用方法如下:
int littleEndian = 1234;
int hostEndian = CFSwapInt16LittleToHost(littleEndian);
那麼 hostEndian 的變數值就是採用目前機器上的 endian 順序的 int。

不過浮點數就沒這麼輕鬆了。我們在前面的例子中還是用 int 來存放 littleEndian,因為就算 byte order 不對了,但它仍然是個 valid 的 integer,不過浮點數的每個 bit 有它不同的意義,因此一旦 byte order 解譯錯誤,它就可能變成 invalid float,導致程式直接當掉。

為了解決這個問題,Objective-C 中用了一個與 byte order 無關的資料結構來儲存這個資料,定義如下:
struct CFSwappedFloat32 {
uint32_t v;
};
typedef struct CFSwappedFloat32 CFSwappedFloat32;
可以看到,這個結構中就只有一個 data,uint32_t,Objective-C 就是用它來儲存這個 float 的資料(當然,此時系統並不會把它當成一個 float)。接下來的處理方式就是,將這個 uint32_t 裡面的 byte 頭尾互換位置,然後將這 32 個 bit(4 個 byte)轉化成 float。而這就是 CFConvertFloat32SwappedToHost 這個函式在作的事。整個的用法可以用以下的例子表示:
CFSwappedFloat32 littleFloat;
long buffer;
float hostFloat;

fread(&buffer, sizeof(long), 1, fp);
littleFloat.v = buffer;
hostFloat = CFConvertFloat32SwappedToHost(littleFloat);
當然,其中的 fread 可以用 memcpy、NSData 的 byte method 等等取代,只要把握住一個原則:「 CFSwappedFloat32 的內部是用 uint32_t 來儲存這個待轉換的 float」即可。

標籤: , , ,

NSNumber 與 NSInteger

在 Mac OSX 10.5 中新增加了 NSInteger 這個東西,但是這下就會跟 NSNumber 搞混,到底要用哪個?

基本上,NSInteger(以及類似的 NSUInteger)是為了解決在 32-bit/64-bit CPU 架構下,int 長度不同的問題,它的定義如下:

#if __LP64__ || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif
也就是說,NSInteger 只是用 typedef 包裝過的 int/long,它是個基本資料型別(data type)。

NSNumber 則是個不折不扣的 Objective-C 類別,因此這兩者的使用時機就很明顯了,當你要把 integer 放到 Obj-C 的集合,例如 NSArray/NSSet 時,請用 NSNumber,不然其他的時候用 NSInteger 就好了。

標籤: , , ,

星期四, 六月 19, 2008

Xcode 與 C99 標準

寫程式時,迴圈是個避免不了的東西,而幾乎每個迴圈都會有個 counter。在大部分的情況下,這個 counter 是用過即丟的,因此我們常常會寫如下的 code:
for(int i=0; i<something; i++) {
some code here...
}
但是在 Xcode 下,這邊會跳出一個 C99 的 Error,原因是 gcc 預設的編譯規則是 C89,而早期的 C 規定所有的變數必須在一開頭宣告,不能在述句中宣告,因此這邊會跳出錯誤。不過對於這種用過即丟的 counter,我覺得事先宣告反而麻煩,因為會造成這個 counter 超出它所應用的 scope,事後反而容易造成問題。解決之道就是讓 gcc 改用 C99 規則。

要在 Xcode 中讓 gcc 改用 C99,請在 Groups & Files 中選取 project 名稱,然後按下 ⌘i 或工作列上的 Info,如下:
在跳出來的視窗右邊的搜尋欄位直接填入 C99,可以找到 C Languang Dialect 這項設定:

然後在 value 的選單中選取 C99 [-std=c99] 就可以了。

標籤: ,

星期一, 三月 03, 2008

iPhone/iPod Touch 更新/降級系統相關的問題與解法

最近幫人破解 iPod Touch,結果要從 1.1.3 降級回 1.1.1 的時候遇到了許多問題,iTunes 一直跳出視窗說回復失敗,發生了未知的錯誤等等,google 了一下找到了這些錯誤代碼的意義和解法,整理如下:
  • 未知的錯誤 (1):這代表 iPod Touch 沒有進入 DFU 模式,必須要進入 DFU 模式才能降級。而要進入 DFU 模式有兩個方式:
      1. 連上 iPhone 跟電腦,打開 iTunes, 確認 iPhone 是開啟的(不是 power off).
      2. 同時按下 Sleep + Home,等到畫面變黑時,但還不是全黑時,放掉 Sleep ,但持續按 Home 鍵(約 10~20秒),直到 iTunes 發現一台 iPhone 在 recovery 狀態.
      3. 已進入 DFU,接下來就照著破解步驟做。
      注意,Sleep 鍵必須要在出現白蘋果前放掉,而在等畫面變黑,又不是全黑的時間點不太好抓,多試幾次應該就會了,大約是同時按下 Sleep+Home 後的6秒。成功的 DFU ,iPhone是沒任何畫面的,切記。
      以上引用自iphone4.tw
    • 另一個方法是利用 ZiPhone,比較方便也比較容易成功。我以 2.5c 版本為例,將 iPod Touch 接上電腦之後,把 iTunes 關掉,然後選擇選單列的 Mode -> Restart in DFU Mode 即可,如右圖所示:
  • 未知的錯誤 (1403):這代表你之前下載的回復檔有問題,請重新下載。要注意的是你可能要先把瀏覽器的 cache 清空,才能確保有重新下載而非從瀏覽器快取又直接複製一份有問題的檔案出來。
  • 未知的錯誤 (1604):請將 iTunes 降級到 7.5,在 Windows 上要把 iTunes、Quicktime 等都移除重新安裝,Mac 上則請參考這裡。不過我雖然有遇到過這個錯誤訊息,但是當我正確的進入 DFU 模式之後,也可以用 iTunes 7.6 正常降級。
  • 未知的錯誤 (1602):這跟 1604 的錯誤一樣,也請改用 iTunes 7.5 再試試看。
另外,我也遇過破解已經完成,但是 iPod Touch 卻一直停留在回復模式,此時一樣利用 ZiPhone 從 Mode -> Restart in Normal Mode,然後等個幾分鐘之後就會以正常模式重新開機。

標籤: ,

星期日, 十月 07, 2007

試著在 Virtual PC 7 中安裝 Linux [1]

因為這學期修了一門 Linux 驅動程式開發,所以想在 VPC 中安裝一套 Linux 來用,沒想到真是困難重重啊...

先說明我的需求:因為只是要在上面練習寫 driver,所以 GUI 就省了,只需要有 ssh server 能夠登入就好。
我的配備則是 PowerBook G4 1.67GHz,記憶體有 2G,使用 Virtual PC 7.03。

首先先用了我最熟悉的 Mandriva。下載了 Mandriva 2007.1 來裝,輕鬆愉快的安裝好,只花了大約半小時多,然後開機,結果一直停在Uncompressing Linux... Ok, booting the kernel.不會動...它就是不會動...

於是我轉向 Mandriva 2007.0,結果相同...它還是不會動。

因此我腦筋動到了最近幾年很紅的 Ubuntu 上,抓來試試,先試了 7.04,沒想到在安裝的時候就遇到問題...看起來是螢幕設定有問題,安裝畫面大概只能看到一半...

我只好摸黑進行,一直到了安裝 base system 的時候,我看到進度列一直停留在 6%,停了起碼有 20 分鐘以上,只好放棄重新啟動。
經過了重複的試驗之後,我發現在 Ubuntu 安裝畫面一開始的地方可以設定 VGA,改成 800x600x16 之後,突然,安裝畫面正常了,我可以看到整個畫面了,也才發現原來進度列雖然停在 6% 但是它還是有在跑的!接下來就是耐心的考驗了....在經過了 2.5 小時的安裝之後,系統終於安裝完畢,但是第一次啟動就看到如下的畫面...Kernel 噴了兩行 CPU 的暫存器內容...掛了...

這樣不行,請出 Google 大神,在網路上翻啊翻的,看到有人說 Windows 版的 Virtual PC 2004 差不多就等於 Mac 版的 VPC 7,安裝的資料可以參考這個網站:What Works and What Doesn't in Microsoft Visual PC 2004。在查閱了裡面的資料之後,我確定了目前應該沒有人安裝成功我試的這幾個 Linux Distro...

退而求其次,我看到目前為止 Ubuntu 可以安裝的最新版本是 Ubuntu 6.06,就決定是你了吧,不過我實在是沒力在等下去,決定把電腦放下載,先去睡了。

標籤: ,

星期五, 五月 18, 2007

系統轉移

最近買了一顆新硬碟裝到我的 PowerBook 上,昨天花了一晚重灌系統,然後利用安裝程式中的轉移功能把舊硬碟中的資料傳送過來。不過慘劇發生,我發現這樣轉移之後系統並沒有更新到 10.4.9,好吧,那就慢慢跑,幸好我之前有先把 10.4.9 combo update 先抓下來。該更新的都更新完之後,我發現寫程式用的 Xcode 沒有轉移過來...本來想直接把整個 /Developer 目錄複製過來,不過零碎檔案太多,而我又有把 Xcode 的安裝檔留著,就想乾脆重裝好了,結果 Java 文件的安裝花了一小時還沒跑完...等待的時間中我啟動 iChat,結果發現帳號資料不見了,只好重新輸入帳號密碼,然後 iChat 就一直停留在等待 .Mac 伺服器回應的階段,又過了十幾分鐘突然整個系統就當掉了....

好吧,就用舊硬碟開機,到 Google 查查看,發現 OIKOS 有個討論串 (只換硬碟,不換內容的方法?) 在講系統轉移的事。看起來最簡單的方式應該是用舊系統開機,然後利用磁碟工具程式裡的重新安裝來進行。要安裝的時候就從左側把舊系統碟拉到來源,要安裝的新硬碟拉到目標,然後選擇下方的清除目標磁碟,最後按下重新安裝就可以了。

事情發展至此,已經是凌晨,眼看複製的速度很慢,我就先去睡了。第二天起來,新系統複製完畢,就用它開機看看。這次效果不錯!看來資料是完整的傳送了過來,而且系統更新也完整的搬移過來,iChat 也正常,看來鑰匙圈的密碼也都成功的轉移了。不過等等...在系統碟最上層怎麼多了幾個替身?包括了 /dev /etc 等等標準的 Unix 目錄,通常這些目錄在 Finder 中是不會出現的,結果現在全部跑了出來。繼續 Google,找到了一個討論串 (DU's Restore in 10.4.3) 在講這個問題。看起來是磁碟工具程式的 bug,在複製檔案的時候沒辦法設定正確的屬性。解決的方法在 Apple 的知識庫有提供:Mac OS X 10.4: Invisible files become visible after NetInstall or restoring from a disk image

主要就是利用安裝光碟中的 SetHidden 工具和一個要隱藏的檔案清單 hidden_MacOS9 來把這些檔案的屬性設定好,這工具可以在此下載。執行之後把 Finder 重開即可。

要避免這個隱藏檔案的問題,可以用安裝光碟開機,然後利用磁碟工具程式照上面的步驟轉移。聽說這樣做的話是 block copy,而不是單純的 copy 檔案,如此就可以把正確的屬性帶到新的系統中,也就不會出現應該要隱藏的檔案卻跑出來的問題。有需要的朋友下次可以試試。

我的硬碟是從 seagate 5400.2 80G 5400rpm 換成 seagate 5400.3 120G 5400rpm,結果電池顯示的使用時間增加了半小時,真棒!

標籤: , ,

星期日, 三月 25, 2007

清除 Finder 選擇應用程式的清單中重複的項目

用 Finder 右鍵選單選擇開啟檔案的應用程式時,有時候會出現重複的項目,例如兩個 QuickTime 之類的,雖然不影響功能,但是把清單拉的很長,有時候不太方便,而且看了礙眼。

前兩天剛好有人在 PTT Mac 版上問到 Finder 的問題,我就搭便車順便問了一下,才知道原來 OIKOS 有人提供過解法了。

只要在終端機下輸入以下的指令清除系統 LaunchServices 的資料就可以了:
/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -kill -domain local -domain system -domain user
執行大約要花個一兩分鐘,我猜和系統裡面有多少應用程式有關,指令完成之後也不用重新開機或重開 Finder 之類的,馬上就可以看到效果。

有此困擾的朋友可以試試。

標籤: ,

星期四, 一月 11, 2007

[Develope] 在 Mac 的終端機(terminal)中使用中文

相信許多像我一樣從 Linux 轉到 Mac 的使用者,即使到了 Mac 上還是喜歡用 terminal 來作些事情,但是也會像我一樣,馬上發現在 Mac 的 terminal 中沒辦法看到中文,也沒辦法輸入中文,不使用內建的終端機.app,換用 iTerm 也無法解決這個問題。

我本來也以為這是個無解的問題,後來無意中 Google 了一下,發現其實是有解的,而且其實只是設定上的問題而已。不過雖說是設定上的問題,但是這些設定卻不是針對終端機程式,而是環境變數。

請在家目錄中新增一個 .profile 檔,內容如下:
alias ls="ls -v"

這樣一來就可以在 ls 的時候看見中文。

然後另外再新增一個 .inputrc 檔,內容如下:
set convert-meta off
set meta-flag on
set output-meta on

這樣就可以順利的輸入中文。

詳細的變數意義,我想有興趣的人就自己 man 或 Google 一下吧,使用 Linux 最應該學到的應該就是自己找資料的本事不是嗎 :)

標籤:

星期三, 十一月 29, 2006

7-11 列印便

上禮拜期中考,雖然老師已經宣佈是開書考,但是我想假如在考試途中把 PB 拿出來放在桌上還是會嚇到他吧 XD,不過家裡又沒有 "可以運作的" 印表機,所以就想到 7-11 去印些資料出來。

照例先在網路上搜尋一下,找到幾篇文章,裡面都提到 7-11 沒有提供 Mac 用的驅動程式,但是有人宣稱把 iBook 插上去就可以直接使用,也有人提到其實 7-11 用的多功能事務機是京瓷 (Kyocera) 的 KM-C830,所以可以直接去京瓷網站上下載驅動程式。看起來一切都很美好,但是要下載驅動程式的時候才發現連結已經失效,因為這些文章都有點時間了...不過幸好,京瓷並沒有把驅動程式拿掉,只是改了位址而已,稍微找一下就可以找到 Kyocera Mita OSX 10.2 and 10.3 installer Version 1.6Kyocera Mita OSX 10.4 installer v 1.6

這個驅動程式裡面有很多款機器,記得安裝的時候只要選 KM-C830 就好,不過裝好之後在系統偏好設定的印表機中還是看不到的,必須等到了 7-11 把 USB 插上電腦才會看到多了一台印表機。

在 7-11 列印還有幾點要注意的,就是 7-11 提供給 Windows 的驅動程式有兩種,一種是黑白,一種是彩色。兩者有何差異呢?首先當然就是黑白印出來是黑白,彩色印出來是彩色,但是最主要的差異是,價錢!A4 黑白一張 2 元,彩色一張 15 元!這為什麼很重要呢?因為黑色也是彩色的一部份,假如你要印的文件本來就是黑白,但是卻選彩色列印,印出來的成品不會有任何差異,但是卻要收你 15 元!在 Windows 上已經一堆人搞錯了,Mac 上就更麻煩了,因為 Mac 上只有原廠的驅動程式,你必須在列印的時候從 "印表機設定" 裡面自己選黑白列印,不然預設可是彩色列印喔!第二個要注意的是只能印 A4 或 A3 的大小,所以一定要在列印選項的 "紙張處理" 裡面確定紙張大小是 A4 或 A3,不然 7-11 的印表機可是會當在那邊沒有回應的喔。至於我為什麼知道...嗯...所謂上一次當學一次乖嘛...也幸好台灣是全世界 7-11 密度最高的地方,我才能直接走到另一家 7-11...

雖然在 7-11 玩印表機還蠻好玩的啦,不過其實對 Mac 使用者來說,另一個 7-11 的服務可能會比較方便,就是 7-11 現在可以直接列印隨身碟中的文件...而且除了必需 (?) 的 doc、ppt 之外,也可以列印 PDF...

所以親愛的 Mac 使用者,以後要去 7-11 列印,請利用系統內建的輸出成 PDF 這個功能,把檔案存到隨身碟中再去印,不用像我一樣呆呆的拿著電腦跑出門...

標籤: ,