2010年12月22日 星期三

iPhone 我後悔了~ performSelector 停下來阿

雖然短的跟一行文沒什麼兩樣
但是之前沒記下來,那就開個版面寫一下

Tips:
故事是這樣發生的...
下面的動作是在touch event觸發之後會去執行的
[self performSelector:@selector(myFunc) 

           withObject:nil 

           afterDelay:delay];

但是,在這個延遲的期間又去觸發touch event...
已經下達的performSelector是不會理會的
使用者可能會有UI行為不一致的感覺

因此,在下達performSelector若能把前一次 未執行完的動作給停掉
會是比較理想的作法,cancel 方法如下:
[NSObject cancelPreviousPerformRequestsWithTarget:self

                                       selector:@selector(hideMsg)

                                           object:nil];


參考來源: stackoverflow
                iphonedevsdk

2010年12月13日 星期一

iPhone 更改專案名稱 (update:完整版)

剛起始一個專案的時候
我有個很糟糕的習慣就是取了爛名字
什麼xxxtest阿,xxxdemo等等...
等真的要release的時候不免被人家念一頓

其實要修改 project name也不難
1. 找到專案的info.plist
2. 找到"Bundle display name"的欄位
3. 將原本 ${PRODUCT_NAME} 改成想要的名稱

如果遇到
the program being debugged is not being run
的error message也不要慌,
shift + command + K 把專案給clean重編就好了

參考資料:stackoverflow
              iphonedevsdk

update: 2011/05/10
嗯~原本的作法算是治標不治本
如果精明一點可以發現透過organizer看到的device log都還是舊名稱
雖然之前就有看到網路上有教學
不過好害怕整個project改爛了就很好笑了

anyway,凡是總有第一次,先備份起來總不會失控吧!
更改專案名稱真的沒有這麼恐怖,給我5分鐘就可以搞定的:)

Let's change the project name completely
1. Copy all files under old project directory to a new one.
    拷貝所有舊專案資料夾底下的file到新的資料夾


2. Rename "old_name.xcodeproj" to "new_name.xcodeproj" then open it.
    將舊的xcodeproj檔名改成想要的新名稱,然後用xcode打開


3. Check if project with the new name under Group&Files pane and Target pane
    修改並確定project name及Targets的名稱是新的


4. Clean the project by shift+command+K and quit xcode that's it, 
    don't rename any other file name at this state.
    清除專案,別急著將其他檔案更名,拜託,我在這步失敗過:P


5. Right click on the "new_name.xcodeproj" and choose "show package content",
    open "project.pbxproj" by xcode.
    回到資料夾在xcodeproj檔案上面按右鍵 選顯示套件內容 打開project.pbxproj


6. Replace all "old_name" with "new_name" save and quit
    用new_name取代所有的old_name, 儲存後離開


7. Open the project again, and rename "old_name" to "new_name" in entire project,
    the red lost referenced files should disappear.
    再次開啟xcode將 project中出現的所有"old_name"用"new_name"取代


8. Open "new_nameViewController.xib" and "MainWindow.xib" to correct the class
     identity.
    開啟"new_nameViewController.xib"與"MainWindow.xib"更改delegate, controller的
    class identity欄位


9. 重新編譯,完成!!

我的作法並無使用console,希望對大家有幫助

參考資料:WebObject blog

iPhone POST url遇上跳脫字元的處理方式

寫過網路程式的人都知道
POST url之前最好要將內容encode過
不然decode過程中一定會有判讀錯誤的問題
ex: user=123&abc&pass=qwe=asd
encode後送出 user=123%26abc&pass=qwe%3Dasd
原本以為下面的encoding method用得好好的
沒想到是一個大bug

[unencodedObj stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];


所以請大家改用

(NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
                                 (CFStringRef)unencodedObj,
                                                    NULL,
                             CFStringRef)@"!*'();:@&=+$,/?%#[]",
                                          kCFStringEncodingUTF8 );


參考來源: simonwoodside
                iphonedevsdk

2010年11月23日 星期二

iPhone UIImage的圓角效果及橫向splash screen

原本以為這兩件事情是有難度的,
還好是自己嚇自己~
參考看看囉:)

UIImage圓角效果
1. 找到左側列表的Frameworks,右鍵加入existing frameworks
QuartzCore.framework

2. 記得在.m的檔案也加入
#import

3. 設定圖片來源的同時也設定圓角效果的屬性
imageView.layer.cornerRadius = 5.0;
imageView.layer.masksToBounds = YES;

//And to add a border:
imageView.layer.borderColor = [UIColor lightGrayColor].CGColor;
imageView.layer.borderWidth = 1.0;
imageView.image = [UIImage imageNamed:@"image.png"];

比較一下有無圓角的效果吧~

載入橫向的splash screen
根據網路上的結論是…辦不到!!
ㄜ~程式上是辦不到,不過圖片可以動手腳
iPhone的Default.png請轉90度,變成320x480
iPad的Default.png請轉90度,變成768x1024


資料來源:
           iPhoneSDKPro
           iphonedevsdk

2010年11月8日 星期一

iPhone can't change language of Xcode

寫程式或許會遇到丈二金剛摸不著頭緒的時候
debug可能會嚐到眼花撩亂頭暈目眩的情形
但是當你碰上Xcode的build setting語言改不掉


一開始會很火大…
阿不就系統設定(system preference)裡面
語言與文字選項(language and text)順序調整一下
再不然,狠一點從list上面移除

再來會很無奈
重開Xcode,登出登入,重開機,無濟於事阿!!!

最後會掉入絕望的深淵
只能看著像是外星來的語言
冒著error,warning無情的嘲弄
猜測屬性的設定,這邊試試看,那邊試試看

不是我歧視日文,而是真的完全看不懂阿
不能這樣溫良恭儉讓下去了~
好不容易我找到了大絕招,這樣做就對了!

1. 首先找到Developer -> Application -> Xcode
2. Ctrl + click -> Show Package Contents -> Resource
3. 把那個叫Japanese.lproj 整個砍了吧!!

重新開啟Xocde,迎接清爽的build setting page吧 :)

資料來源: macosx.com

2010年11月3日 星期三

iPhone 自訂navigation bar全攻略 包含按鈕,高度及圖片背景

iPhone的UI真的有很多小細節,我想也累積一些東西了就po上來吧.
自製化的navigation bar到底有多彈性呢?
我想改變navigation bar上面按鈕的樣式,可以!
想改變navigation bar的高度,可以!
想給navigation bar上個圖片,可以!
那..那navigation bar上按鈕的位置呢? 還是可以!!

如果技巧太鼈三就包涵一下啦:P
navigation bar中的按鈕參照UIBarButtonItemStyle所定義項目少了custom這項
不過可以透過initWithCustomView的方式建立自訂的按鈕
詳細作法如下:
1. 先建立一個UIButton,設定其大小位置以及各狀態對應的圖片,最後還要一個action的指向

UIButton * fooButton = [UIButton buttonWithType:UIButtonTypeCustom];

fooButton.bounds = CGRectMake(0, 0, 40.0, 40.0);

[fooButton setImage:[UIImage imageNamed:@"foo.png"] 

   forState:UIControlStateNormal];

[fooButton addTarget:self 

        action:@selector(fooFired:) 

     forControlEvents:UIControlEventTouchUpInside];

2. 接著new一個UIBarButtonItem後,加入navigationItem(這邊以右邊為例)

UIBarButtonItem *fooBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:fooButton];

 self.navigationItem.rightBarButtonItem = fooBarButtonItem;

 [fooBarButtonItem release];

(trick 1) 接下來講講navigation bar的高度怎麼改變,
網路上可以找到一些方法,不過直接改變高度似乎不可行(至少我自己試過不行)
self.navigationController.navigationBar.frame.size.height
另外一個就正常啦,set自己想要的大小位置

[self.navigationController.navigationBar 
setFrame:CGRectMake(0, 0, self.view.width, height)];

(trick 2) 給navigation bar上個圖片也不會太難
1. 首先new一個UIImageView

UIImageView * banner = [[UIImageView alloc]

initWithFrame:CGRectMake(0, 0, width, height)];

2. 指定這個ImageView載入的圖片

banner.image = [UIImage imageNamed:@"banner.png"];

3. 透過addsubview的方式加進navigation bar(這裡額外指定layer在最底層)

[self.navigationController.navigationBar insertSubview:banner atIndex:0];

 self.navigationController.titleView = banner;  上面這個作法會讓titleView蓋過title的字 (very important)

咳~醜媳婦終究還是要見公婆
改變navigation bar按鈕位置的方法有點投機
如果想要達到下圖的樣子要善用trick1跟trick2

首先在我們改變navigation bar高度的過程中
一定會發現按鈕的位置都偏下,就像下面的圖

沒關係,我們在navigation bar上面放一個高度較高,size較大的圖片蓋過去
如此一來navigation bar上面的按鈕怎麼看都會在中間啦!

順帶一提:
自訂的navigation bar剛開始跑起來都還好端端的,
但是隱藏過後又要顯示時,
按鈕設定全跑了,navigation bar高度也會回復預設值.
後來解決的方法還滿暴力的,
就是要再度顯示之前,再設定一次navigation bar的frame size

[self.navigationController.navigationBar 
setFrame:CGRectMake(0, 0, width, height)];
[self.navigationController setNavigationBarHidden:NO 
                                       animated:NO];

Update:
如果rotate會導致navigation bar上面的button位置跑掉,
表示其高度被設定回預設值,
解決的方法也是在rotate完成後,再設定一次navigation bar的frame size

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {

  //set your frame size here

}

             stackoverflow - BarButtonItem

2010年10月13日 星期三

iPhone/iPad start apps with specific orientation and device detection

好久沒po筆記了,只能說俺的惰性實在是太容易復發了
一般來說iPhone跟iPad一執行程式起來都是直立狀態
(PortraitOrientation)

如果想指定啟動後就是橫著的方向,設定的方式如下:
1. 因為是app一開始執行就要做的動作,
   所以設定也是在一開始的ViewController裡面
    {ProjectName}ViewController.m  -->
    - (BOOL)shouldAutorotateToInterfaceOrientation:
            (UIInterfaceOrientation)interfaceOrientation

2. 修改並指定interfaceOrientation朝左或右
   return YES;
   return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
   or
   return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);

   補充說明一下 return YES的作法:
   device會參考plist中的Supported interface orientations欄位,
   有指定到的方向device會自己做旋轉動作.

   另外,UIInterfaceOrientationLandscape與UIDeviceOrientationLandscape
   的方向是剛好相反的(這特性可以被作為一些判斷依據)

3. 在參考資料的過程中,有這樣的需求是程式在iPhone跟iPad起始的方向要不同
   一樣是在原處動手腳,加上一些判斷式就能夠分辨device種類了.
   BOOL iPad = NO;
#ifdef UI_USER_INTERFACE_IDIOM
   iPad = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
#endif
   if (iPad) {
      // 條件成立表示device為iPad,執行環境iOS3.2以上
   } else {
      // 條件不成立有兩種可能1.device是iPhone或iPod
      // 2.執行環境iOS3.2以前版本不支援UI_USER_INTERFACE_IDIOM
   }

有興趣可以看一下UI_USER_INTERFACE_IDIOM在UIDevice.h的定義
目前我執行起來沒有什麼問題~
網路上有很多討論,如果是universal apps又是another story了:)

很開心在網路上開始看到有人site我的文章了耶~
但是可以請好心的註明一下出處嗎?

參考資料: JEFF LAMARCHE's blogger
               UIDevice Class Reference
               Ole Begemann's blogger
               Sangraal at Programbles
               BillyGiggles at iphonedevsdk


2011/01/03 補充:
iOS version detection

既然有偵測device 型號的方法
iOS版本的偵測當然也不能缺席

#ifdef __IPHONE_3_0
// works on >= iOS 3.0
#else
// works on < iOS 3.0
#end

或

float ver = [[[UIDevice currentDevice] systemVersion] floatValue];
if (ver >= 3.0) {
    // Only executes on version 3 or above.
}
資料來源:stackoverflow

內容回應