2010年8月5日 星期四

DOM-based XML utility For iPhone

在Mac OSX上,分別有NSXMLParser跟NSXMLDocument來處理有關SAX與DOM方式的XML parsing。然而在iOS上的Cocoa Touch,卻只剩下SAX的NSXMLParser的處理方式。相較於DOM來說,SAX的處理方式是較為快速與節省資源的,也或許是這樣才會在iOS上只保留這種方式的parsing。

然而,如果只是簡單格式的XML讀取,用NSXMLParser來parse可能是很快速簡便。但是如果要處理的XML格式眾多或是格式複雜,那就可能不是那麼好過了...而且NSXMLParser也只能處理讀取時的parsing。如果是要將資料輸出成XML格式,那不使用DOM的處理將會變得比較難以處理。

後來在internet上,發現這篇APXML: NSXMLDocument 』substitute' for iPhone/iPod Touch,才知道有這個APXML的DOM-based簡易套件可以使用。說它是簡易套件還真不為過,含Header file在內,全部也才不過6~7個source code files,每個也都不算太大、太複雜。
既然是DOM-based parser,當然除了可以讀取,也可以輸出成為XML。使用上很簡單,只要
#import "APXML.h"
就可以使用到全部的相關類別,不必一一去import個別的class。
Parse XML:
APDocument *doc = [APDocument documentWithXMLString:xmlstring];
取得Root Element:
APElement *rootElem = [doc rootElement];
讀取所有子element:
NSArray *childElements = [rootElem childElements];
讀取element name:
NSString *elementName = elem.name;
讀取element value:
NSString *elementValue = elem.value;
讀取特定名稱之attribute:
NSString *attrValue = [elem valueForAttributeNamed:attributeName];

輸出部分則為
Create Element:
APElement *elem = [APElement elementWithName:elementName];
Set attribute & element value:
[elem addAttributeNamed:attrName withValue:attiValue];
[elem appendValue:elementValue];
Add child element:
[elem addChild: childElem];
Create XML Document:
APDocument *doc = [[APDocument alloc] initWithRootElement: elem];
Output XML string:
NSString *xmlString = [doc xml];

使用語法算是十分簡單、直覺。
其實,要自己實作DOM-based parser也不算太難,但是總是比較費工夫、品質也需要時間來鍛鍊。既然有現成又不錯的lib,當然能善加利用會更好囉~

好用的HTTP lib(for iPhone & Mac OSX)

HTTP API其實在Cocoa裡面是有的,透過NSURL、NSURLRequest、NSURLConnection等類別來達成,也分別支援同步與非同步傳輸。使用上雖然不算是太難,但是仍然有不少繁瑣的手續要做,要處理的delegate method也不算少,讓人感覺還是有點不是那麼方便。

因此,後來在internet上,找到一個叫做ASIHTTPRequest的lib,這個lib是以BSD license的方式open source的。顧名思義,這個lib的主要工作就是提供HTTP protocol的通訊機制,而且用很簡單的方式讓developer可以操作request、response,以及設定POST parameter,甚至是上下傳檔案等等。本身也內建啟用Cookie機制,所以對於一些有session tracking的web services也很方便。當然也提供有同步與非同步的傳輸。
官網位置:http://allseeing-i.com/ASIHTTPRequest/

心得:該Lib除了可以在Mac OSX上使用外,也可以在iOS上使用,而且目前已經與iOS4相容。使用上算是很簡單,也沒碰過啥大問題。如果要說缺點,就是放到project中,會導致project code在compile之後多出不少容量吧XD

2010年8月4日 星期三

動態調整TableVewCell的高度

因為工作需求,原本要使用UITextView來顯示多行文字,但是發現使用了UITextView之後,Cell可以觸發select動作的區域將變得很小(受到UITextView的區域影響)。所以改用別的方式處理。

首先,發現原來UILabel是可以顯示多行文字的,只要把property numberOfLines設為0,就可以支援多行文字,但是必須呼叫[label sizeToFit],來調整UILabel的大小。

而預設的UITableViewCell的textLabel也可以這樣調整,所以就可以顯示多行文字。然而,UITableView還有個問題,就是有cell height的問題。因為cell height似乎是在cell顯示前就會設定好,所以即使在tableView:cellForRowAtIndexPath:這個method裡面去調整cell的高度也是無效。必須透過tableView:heightForRowAtIndexPath:來回傳特定cell的高度。

但是,對於多行文字來說,因為內容行數是不固定的,所以必須在顯示時計算實際行數文字的總高度。幸好在參考iPhone SDK: Resizing a UITableViewCell to Hold Variable Amounts of Text, Part 2 of 2這篇之後,得到解答。就是利用NSString裡面的sizeWithFont:constrainedToSize:lineBreakMode:來根據指定的字型高度跟斷行方式來計算。可以使用Objective-C的Category機制,將此method放置到NSString中。以下是參考上述文章所寫的code:
@implementation NSString (TextHeight)
-(CGFloat) textHeightForSystemFontOfSize:(CGFloat)size {
//Calculate the expected size based on the font and linebreak mode of the label
CGFloat maxWidth = [UIScreen mainScreen].bounds.size.width - 50;
CGFloat maxHeight = 9999;
CGSize maximumLabelSize = CGSizeMake(maxWidth,maxHeight);
CGSize expectedLabelSize = [self sizeWithFont:[UIFont systemFontOfSize:size] constrainedToSize:maximumLabelSize lineBreakMode:UILineBreakModeWordWrap];
return expectedLabelSize.height;
}
@end

透過此method,就可以在tableView:heightForRowAtIndexPath:中回傳正確的文字內容高度了。

2010年5月12日 星期三

DB實作心得---SQL JOIN語法

因為都是用Hibernate,所以好久沒碰這種語法了...老實說以前在學SQL的時候,也一直沒很認真的搞懂。一直到最近為了案子,才又比較認真的去看了...
找了幾篇網友分享的文章,都講得很清楚,所以就不在贅述:
一般來說,我們通常都會儘量用一個SQL statement的方式來完成所需要的查詢。而其中都儘量可以用JOIN的方式來把所需要的資料串出來。不過我也有看到有網友發表心得,表示在MySQL上,進行較複雜的JOIN時,效率會很糟糕,甚至會造成DB table被lock過久的情況。事實上,幾年前我自己也用過MySQL,也是發現它在作較複雜JOIN時,效率真的不好...所以後來我就都改用PostgreSQL。

而在Hibernate中,我所常用的Criteria是一種物件式的查詢方式,它建立跟其他table JOIN的方式是透過createCriteria()或是createAlias()。透過這兩種method,可以把要查詢的root entity跟child entity作JOIN。在建立這種JOIN關係時,Hibernate預設是使用inner join的方式,所以在某些情況會無法正確的找到所要資料,甚至會出現LazyInitializationException。此時,可以試試看在這兩種method的呼叫時,加上Criteria.LEFT_JOIN,這樣Hibernate會以Left outer join的方式處理,也許就可以成功的找到所要的資料了。

我個人認為與其使用一個很複雜的SQL statement來增加查詢效率,未必比使用多個簡單的SQL statement來取出資料再透過自己程式邏輯作處理來的容易跟快速...

Database系統實做心得---SQL調校

做了很久跟DB有關的開發工作,但是其實後來大部分都是靠Hibernate為主。透過它,開發者不再需要傷神有關DB底層的設定與SQL語法的管理與維護。不過也變得比較偷懶,比較不會去在意SQL語法上的調校。
在網路上有許多高手有此道的獨到心得,我只也是從中獲得一點點,這兩偏是個人覺得還蠻不錯的:Database Index 筆記 與 調校 SQL 以徹底改善應用程式效能

其中有些跟DB table schema設計或是SQL語法的技巧,不過在Hibernate中,要使用這些技巧可能就不是那麼容易。Hibernate是允許使用者自行設定這些東西產生的方法,甚至可以自訂SQL statement。不過個人覺得Hibernate自己所產生的schema跟SQL statement已經很不錯了,除非真的很有特殊的需求,不然實在也沒必要自己搞(如果都要自己搞,那就失去用Hibernate的意義了)。

不過兩篇文章都有提到的一個重點:index。在Hibernate中,也有支援產生index的機制,但是只會對primary key跟unique column自動產生。雖然在Hibernate Annotation Extensions中有@index的annotation可以指定對某個property產生db index,但是這功能只有在透過Hibernate作第一次DB schema建立時有效;若是指定的index的table已經存在的話,這機制不會有作用,就必須手動產生。根據上面兩篇文章的內容,產生與刪除index的SQL DML為:
create index index_mytable_mycol on mytable(mycol)
與
drop index index_mytable_mycol

而根據上述兩篇文章的講法,幾乎都認為應該對FK也設定index比較好。當然有些但書,例如在主table資料量有到一定量以上的時候才會比較有效果等等的。

2010年3月26日 星期五

32bits vs 64bits part2, 32bits未必不好

之前就提過有關Snow Leopard的kernel mode的問題了...事實上我一直很困惑為何Apple不把Snow Leopard的kernel預設為64bit的。

當然,後來也去查過很多的文章,發現不管是國內外的一些使用心得或是報告,都是差不多的結論,就是32bit跟64bit的效能差異不大。其實我自己的感受也是一樣。而不管是使用者或是官方的說法都是說32bit kernel的相容性比較高...這點在我上次要透過iPhone來上往時也證實了...目前某些driver或是軟體可能是無法在64bit kernel下運作的。

當然,自己還是很不死心的測試了一下...用XBench...來測試32bit跟64bit的差異...結果...就分數來看兩者差異真的很小...才2~3分左右...事實上還是32bit贏的。而分項成績則是互有優勝,但是差距不大。除了在記憶體方面的項目中的allocation,64bit有大贏之外,其他的其實大部分都是差不多。而32在OpenGL跟一些圖形顯示方面是有些小贏...不管測幾次都一樣。剛好符合一些使用者的講法,目前在顯示driver上,Mac OS的32bit driver的最佳化是比較好的。

官方講法是說64bit kernel在安裝有大量記憶體(32G以上)的情況下才有需要啟動,而其他情況則與32bit無異。

不管怎樣,Snow Leopard的確讓64bit的app更加廣泛的被使用了,數量也變比較多...雖然還是不少32bit third-party app。能以32bit kernel來良好運作64bit app,apple的工程師也是夠厲害...
至於很多人都猜測,在下一版的Mac OS應該就會改變成為64bit kernel...我個人反而不是那麼看待...畢竟目前還是不少driver跟app還是32bit的...轉換為64bit kernel,對Apple來說會有好處還是壞處,還是難講...這也許也是Snow Leopard採用32bit kernel的原因。除非在新一版的Mac OS出現的時候,已經有更多重量級的driver跟軟體都轉換到64bit,否則用32bit kernel來運作應該還是必然的吧

講了一堆屁話,結論就是我又回到32bit kernel了XD

2010年3月21日 星期日

香草輸入法, 新酷音模組 & Snow Leopard

之前一直都是用Yahoo輸入法,是沒太多缺點啦...如果要說的話,就是猜字的準確度不高,而且不方便自己加詞。之前有人一直推薦我使用香草輸入法,但是Google之後,發現目前香草輸入法在0.9a1,看起來不算是很穩定的版本的感覺...而且我又是用64bit kernel,剛好又不在開發團隊有測試過的OS版本內,所以一直很遲疑...
但是,對於新酷音的猜字準確率很難忘,所以今天還是『冒險』一試了...為何說冒險...因為官網上有段話很嚇人:『請注意:輸入法屬於重要系統元件,系統可能因為輸入法軟體的bug而造成不穩或循環crash。如果發生這種情況,請以其他使用者登入後,砍掉輸入法元件檔案』...聽起來就感覺好像穩定度不高的感覺。

不過後來安裝,發現也沒想像中的難跟有問題...跟一般的Mac App安裝沒啥兩樣。不過...安裝玩香草輸入法之後,發現...沒有酷音模組...得另外下載跟安裝... 所幸官網文件還算詳盡。

試用的感覺:從活動管理員看,輸入法本身似乎所耗用的memory要比Yahoo的少蠻多,大概只有一半還不到,不過目前沒有for 64bit的版本(Yahoo的是64bit版本),所以只能用32bit啟動,但是使用上並沒有什麼問題,速度也算是很快。手動加詞的功能可以work,但是似乎只能按住shift之後,再按方向鍵的左鍵選擇詞彙長度,如果從輸入的句子中間開始往右選詞,則會失敗。至於穩定性,目前感覺不出來有啥大問題,可能要多用一陣子吧...

目前香草輸入法的進展感覺好像有點停擺了...目前的版本是2009.8月份的;而新酷音模組則更舊...感覺有點可惜就是...

Updated: 原來Yahoo奇摩輸入法也是有手動加詞功能,而且方法跟香草輸入法是一樣的