顯示具有 iPhone 標籤的文章。 顯示所有文章
顯示具有 iPhone 標籤的文章。 顯示所有文章

2010年10月8日 星期五

View Transition Tutorial

在 iPhone App 上 View 和 View 之間的轉換非常常見, 這邊提供一個簡單範例教導如何在 View 之間做不同效果的轉換.

開始此範例之前, 必須先準備兩個不同的 view (這部份就不額外說明), 以筆者的例子而言, 有兩個 View, 一個是 OneView, 另一個則是 AnotherView, 在這兩個 View 裡面都包含了單一個 Button, 當點擊之後就可以在這兩個 View  之間做轉換.

真正要寫 Transition 的 code 其實很簡單, 以筆者的例子而言, 有兩種轉換方式, 其程式碼如下


-(void)FlipAnotherFromOne{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:1.0];
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:window cache:YES];
    [oneController.view removeFromSuperview];
    [window addSubview:anotherController.view];
    [UIView commitAnimations];        
}

-(void)FlipOneFromAnother{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:1.0];
    [UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:window cache:YES];
    [anotherController.view removeFromSuperview];
    [window addSubview:oneController.view];
    [UIView commitAnimations];        
}

上面程式碼中的 setAnimationTransition 在 iPhone 裡面定義如下:

typedef enum {
    UIViewAnimationTransitionNone,
    UIViewAnimationTransitionFlipFromLeft,
    UIViewAnimationTransitionFlipFromRight,
    UIViewAnimationTransitionCurlUp,
    UIViewAnimationTransitionCurlDown,
} UIViewAnimationTransition;


所以若需要不同的效果只要填上自己所需要的參數即可.

需要完整的範例可到 這裡 下載

2010年10月7日 星期四

Interface Builder Tutorial - 1

一般開發者在開發界面程式時, 都會需要借助視覺化的工具來縮短開發時間, 例如最常看到的如 Borland C++ Builder (BCB). 這類工具主要概念是"所見即所得" , 簡單的說就是一些常看到的使用者介面如 button, label, textfield, ....等,  都可以透過 BCB 等這類工具讓開發者直接用拖曳元件的方式來快速達成開發目標, 當然這些工具都是屬於 windows 的, 那究竟在 iPhone Programming 的領域中是否也有這類工具呢? 不怎麼貼心的 Apple 當然也提供了視覺化開發工具 "Interface Builder".
在筆者使用的這段時間內, 發現到雖然 Interface Builder 可以快速縮短開發時間, 這點的確是不容置疑的, 但在使用上卻發現許多不直覺的地方 (相對於 windows 上的視覺化開發工具而言), 不過整體來說是還可以接受的範圍.
要開始使用 Interface Builder 之前, 你可以先用 Xcode 新建一新的 iPhone Project, 建立之後會在左側 Project tree 裡看到一個屬於 Interface Builder 的檔案"MainWindow.xib"


 直接點擊此檔案開啓 Interface Builder, 在裡面會看到幾個基本的元件 .xib window,



Inspector



Libaray,


我們要做的第一步驟就是直接編輯  window 視窗, 首先直接點擊 .xib 裡的 window, 且在右方 Library 裡找到 "Label" 和 "Round Rect Button", 並直接將她們拖曳到 window 畫面中, 分別編輯上面的顯示字串, 完成時大概會有類似下面的圖示

完成之後, 接下來就是要開始編寫 button & label 相關的 code 了, 在 AppDelegate.h 裡加入 class member & function


IBOutlet UILabel *text;


-(void) BtnAction:(id) sender;


並且在 AppDelegate.m 裡面實作 BtnAction, 我們在裡面實作了一個非常簡單的功能, 就是當點擊時, 會去更改 Label 的顯示字串


-(void) BtnAction:(id) sender{
    [text setText:@"sYou Pressed!"];
}

當完成上述動作之後, 最後我們要做的就是將 UI 和 code 之間做個"關連", 這步驟就是和一般 window 最大不同的地方, 一般若漏掉"關連"這動作, 你所寫的 code 就不會反應到畫面上, 而"關連"的方式很簡單, 我們再次打開 MainWindow.xib, 然後在 MainWindow.xib 視窗裡選擇 xxxx_AppDelegate,此時就會在 Connection Inspector 裡看到剛剛所新增的 text & BtnAction


"關連" 這動作只要你按住 text 右方的圈圈, 並拖拉至剛剛所產生的 Label 即可, 而 BtnAction 也是一樣, 拖拉到 Button 的位置上, 但是因為觸發 Button 的方式有很多種, 所以當你拖曳過去之後, Interface Builder 會要你選擇觸發方式, 我們此時選 "Touch Up Inside"


完成之後, 儲存, 編譯, 執行, 應該就可以看到此次練習的成果了.

完整範例可以到 這裡 下載

2010年10月4日 星期一

ipa 上傳失敗問題

今天為了更新一些東西需要上傳 binary 到 apple, 但是不知道為什麼又出現


Application failed codesign verification

看到的時後差點沒吐血!!!! 明明昨天就好好的, 上個班回來又變這樣!!!
研究了好久發現一個可以正常 sign app 的方式了, 不過這方是是基於憑證都設定正確的情況下才有用(一定會有人問, 為什麼憑證都設定正確卻還不過, 老實說, 我也不知道, 我只知到心中一百個 OOXX)
1. 第一次直接編譯產生 .ipa
2. 將 Entitlements.plist 砍掉
3. 再次新增 Entitlements.plist
4. 重新編譯, 重點來了!! 要編譯第二次時, 不能 clean project, 只需要把第一次產生的.ipa 砍掉就好(別問我為什麼, 我也不知道)
依照上面步驟編譯完成時, 應該可以在 build log 看到如下訊息

/Users/tixlo/Data/iPhone/GameDev/HealthyDiet/build/Distribution-iphoneos/HealthyDiet.app: replacing existing signature

此時的 .ipa 就可以正常上傳了

以上就筆者個人開發環境而言是可以正常運作的, 若你真的對這錯誤走投無路的話, 不訪試試看這方是

2010年10月2日 星期六

Apploader 上傳 ipa 問題

原本上載 ipa 檔已經都搞定, 但是昨天晚上要再次上傳時又發生
application failed codesign verification ....... submission certification
完全不知道為什麼, 照著之前的解決步驟也無法順利上傳, 又試了整個晚上到今天忽然又可以完整的上傳, 過程中嘗試很多方式, 也不知道到底是哪個步驟完整解決此問題, 所以乾脆就直接把有嘗試過的方法都列出來, 以後再遇到的時候再一個一個測試 Orz
1. 將 Entitlements.plist 刪除並重新新增至 Project 根目錄
2. 修改 Project .pbxproj 檔案, 內容如下:


3. 將之前安裝的 certification & key 全部刪除,  把整個 key 的產生, certification 的上傳, Profile 設定步驟全部砍掉重練(keychain & iPhone Provision 都砍掉), 照著步驟重新安裝 certification / provision

依筆者的情況, 依照上面這些步驟"亂試" 結果試可以正常運作的, 不確定其他人是否也可以依此方式解決問題 Orz.., 弄到目前只有一個想法
"Apple 阿 Apple 阿, 我真是不懂你阿!!!"

2010年10月1日 星期五

[iPhone] HealthyDiet


Description
在現今食物熱量普遍都偏高的情況下,導致體重的控制變成是一件非常不容易的事情,要如何有效且健康的維持體重,幾乎變成了全民都需要留意的事情,HealthyDiet 提供了一個科學化的紀錄方式,讓每個使用者都可以精準的控制每天吃進肚子的熱量,根據統計少/多攝取 7700 大卡就平均會瘦/胖 1 kg,有鑒於此,對於每日熱量的控管就變的相當重要,HealthyDiet 可以協助你達上熱量控管的目的,而她所提供的功能有
自動計算個人每天所需要的熱量,理想體重以及BMI可以自行設定所要達到的目標體重,不管是增重還是減肥,HealthyDiet 會根據你所設定的目標(包含目標體重,預計多久達成,本身活動系數),來計算每日應當攝取的熱量內建多達2千多種食物熱量表分類多達 23 種,其中包含大家最長看到的麥當勞,吉野家,肯德基,爭鮮壽司,麵包類,五穀類,飲料,和各個便利商店因為中國人食物樣式太多樣話,所以也提供讓你自建食譜每個月會有熱量曲線圖,能夠讓你更精準的瞭解每個月的熱量攝取情形








Lite 免費版本已經上架, HealthyDietLite

2010年9月21日 星期二

How to convert .app to .ipa

使用 Xcode 所編譯出來的都是 .app 檔案, 但是大部份情況來說, 使用 .ipa 比 .app 方便多了
因為 .ipa 可以簡單的透過 iTunes 安裝並同步到 iPhone. 既然 ipa 比較方面, 那究竟要如何
達成此幕目的呢? 做法很簡單, 只需要幾個步驟就可以完美產生 .ipa

開啓你的 Xcode 專案, 依照下圖新增一 Build Phase


將下述內容直接複製到 script 欄位中即可


payload_dir="$CONFIGURATION_BUILD_DIR/Payload"
app_bundle_dir="$CONFIGURATION_BUILD_DIR/${PROJECT_NAME}.app"

/bin/rm -rf "$payload_dir"
/bin/mkdir "$payload_dir"
/bin/cp -R "$app_bundle_dir" "$payload_dir"
/bin/cp iTunesArtwork "$CONFIGURATION_BUILD_DIR/iTunesArtwork"
cd "$CONFIGURATION_BUILD_DIR"

/usr/bin/zip -y -r "${PROJECT_NAME}.ipa" Payload iTunesArtwork
rm -rf "$payload_dir" iTunesArtwork


新增 Build Phase 之後, 可以在專案列中看到如下圖般的 "Run Script" 選項


當完成上述步驟時, 只要編譯你的專案 .ipa 就會自動產生 (當然前提是要編譯要成功)
在 build messages 裡面可以看到類似下面的訊息


一切都完成時, 此時就可以看到我們所產生的 .ipa 檔了


Questions for uploading .ipa binary to apple

case 1:
"The CodeResources file must be a symbolic link to _CodeSignature/CodeResources"


If you're using command-line "zip", you need to use zip -y -r to preserve the symlink.
reference


case 2:
Application failed codesign verification.  The signature was invalid, or it was not signed with an Apple submission certificate.


用文字編輯器開啓 .pbxproj , 搜尋 CODE_SIGN_IDENTITY 應該會看到類似下面的話面



以筆者的例子而言, 要找的是 Distrubution , 除了 Distribution 以外, 要留意的有幾個要確定的地方
確認在 buildSettings 裡的 CODE_SIGN_IDENTITY , PROVISIONING_PROFILE (有兩組)
是否為所需要的. 問題就來了, 要怎樣才能知道我們所要的資訊是什麼呢?
針對 CODE_SIGN_IDENTITY , 我們需要開起 Mac 裡的 Keychain Access , 並選擇左下方的“憑證”欄位



 打開所需要的憑證



觀看其內容會發現有一個欄位寫著憑證名稱, 此名稱就是要填入到上述 CODE_SIGN_IDENTITY 的值
置於另一個 PROVISIONING_PROFILE 呢? 此時請打開 Xcode | Windows | Organizer


    
上述的 Profile Identifier 所顯示的值就是我們需要填入 PROVISIONING_PROFILE 的.
上述兩組值需要根據你所申請的 Certification/Provision 的實際情況來填寫
reference



2010年9月17日 星期五

How to implement customized keyboard on iOS4

在 iPhone 上面開發應用程式時, 在使用輸入鍵盤時, 或多或少都會遇到客制化鍵盤的問題, 這邊筆者以
簡單的數字鍵盤來示範客制化的動作. 這部份我想網路上已經有不少 sample code , 但大部份基本上都是
以 SDK 3.x 的版本去實作, 以"特定寫法"來實作客制化在 iOS4 會有問題, 這部份稍候會提到兩版本的差異.


上述看到的例子是 UIKeyboardTypeNumberPad 搭配 "Done" 的圖示所組合而成的. 在開
始介紹如何實作之前, 先稍微提一下網路上查到的一些範例寫法. 因為 SDK 升版之
後在架構上有做了些修改, 所以導致行為上的不正確. 以下面這例子為例, 它可以正
常的在 iOS4 之前的版本運行, 但在 iOS4 上卻會有看不到上面 "Done" 圖示的問題.

- (void)loadView{
    ...
    textFieldContent.delegate = self;
    textFieldContent.placeholder = @"press me";
    textFieldContent.keyboardType = UIKeyboardTypeNumberPad;
    textFieldContent.returnKeyType = UIReturnKeyDone;
    [self.view addSubview:textFieldContent];
    [textFieldContent release];
    
    [[NSNotificationCenter defaultCenteraddObserver:self 
                                    selector:@selector(keyboardWillShow:) 
                                        name:UIKeyboardWillShowNotification 
                                      object:nil];
    
}

- (void)keyboardWillShowOnDelay:(NSNotification *)notification{
    UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
    doneButton.frame = CGRectMake(0, 163, 106, 53);
    doneButton.adjustsImageWhenHighlighted = NO;
    [doneButton setImage:[UIImage imageNamed:@"DoneUp.png"] forState:UIControlStateNormal];
    [doneButton setImage:[UIImage imageNamed:@"DoneDown.png"] forState:UIControlStateHighlighted];
    [doneButton addTarget:self action:@selector(doneButton:) forControlEvents:UIControlEventTouchUpInside];
    
    UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
    UIView* keyboard;
    for(int i=0; i<[tempWindow.subviews count]; i++) {
        keyboard = [tempWindow.subviews objectAtIndex:i];
        if([[keyboard description] hasPrefix:@"<UIKeyboard"] == YES)
            [keyboard addSubview:doneButton];
    }
}

上述這段代碼主要原理是透過跟 OS 註冊 keyboard 相關的 notification, 並在顯示
keyboard 時, 在 keyboard view 上添加所需要的特定 UIView, 簡單流程大致如下
1. 註冊 UIKeyboardWillShowNotification : 當 keyboard 要秀時, OS 就會呼叫
    keyboardWillShow
2.  當被 keyboardWillShow 叫用時, 搜尋屬於 keyboard 的 view
   if([[keyboard descriptionhasPrefix:@"<UIKeyboard"] == YES)
3. 當找到所需要的 view 時, 再將需要的 view 加入即可
   [keyboard addSubview:doneButton];
上面就是一個 customized keyboard 的簡單實作流程. 但是為什麼這段 code 會無法
在 iOS4 上正確執行呢? 問題點主要出在上述的第 2 個步驟.
在舊的 SDK 中, 當 UIKeyboardWillShowNotification 事件發生且叫用 keyboardWillShow 
時, 此時的 keyboard view 已經被添加到 windows 裡了, 但是在 iOS4 的世界中, 相同
情況發生時, keyboard view 卻會在下個 event loop 裡才會被添加到 windows 中, 也
就是因為如此, 所以上述
[[[UIApplication sharedApplicationwindowsobjectAtIndex:1];
會找不到 keyboard view. 除了這原因以外, 還有另一個重要的差異性, 第 2 步驟所比
對的 @"<UIKeyboard" 字串在 iOS4 中也被修正過, 它被藏在 @"<UIPeripheralHostView"
裡.
針對這兩點, 所以將只要將之修正即可正常的在 iOS4 上執行
1. keyboard view
   既然知道是 keyboard view 會在下個 event loop 才會被放到 windows 裡, 所以我們
   可以透過下面方式將 keyboardWillShow 延遲叫用
   [self performSelector:@selector(keyboardWillShow:) withObject:nil afterDelay:0];
2. 修正比對 @"<UIKeyboard" 的方式

   if ([[possibleKeyboard description] hasPrefix:@"<UIPeripheralHostView"]) 
       possibleKeyboard = [[possibleKeyboard subviews] objectAtIndex:0];

   if ([[possibleKeyboard description] hasPrefix:@"<UIKeyboard"])  
   {
       foundKeyboard = possibleKeyboard;
       break;
   }                
經過上述兩個修正之後的 code 大概會如下 :
    [[NSNotificationCenter defaultCenter] addObserver:self 
                    selector:@selector(keyboardWillShowOnDelay:) 
                        name:UIKeyboardWillShowNotification 
                      object:nil];

- (void)keyboardWillShowOnDelay:(NSNotification *)notification
{
    [self performSelector:@selector(keyboardWillShow:) withObject:nil afterDelay:0]; 
}

- (void)keyboardWillShow:(NSNotification *)notification
{    
    UIView *foundKeyboard = nil;
    
    UIWindow *keyboardWindow = nil;
    for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) 
    {
        if (![[testWindow class] isEqual:[UIWindow class]]) 
        {
            keyboardWindow = testWindow;
            break;
        }
    }
    if (!keyboardWindow) return;
    
    for (UIView *possibleKeyboard in [keyboardWindow subviews]) 
    {            
        //iOS3
        if ([[possibleKeyboard description] hasPrefix:@"<UIKeyboard"]) 
        {
            foundKeyboard = possibleKeyboard;
            break;
        }
        else
        {
            // iOS 4 sticks the UIKeyboard inside a UIPeripheralHostView.
            if ([[possibleKeyboard description] hasPrefix:@"<UIPeripheralHostView"]) 
            {
                possibleKeyboard = [[possibleKeyboard subviews] objectAtIndex:0];
            }                                                                                
            
            if ([[possibleKeyboard description] hasPrefix:@"<UIKeyboard"]) 
            {
                foundKeyboard = possibleKeyboard;
                break;
            }                
        }            
    }
    
    if (foundKeyboard) 
    {
        // create custom button
        UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
        doneButton.frame = CGRectMake(0, 163, 106, 53);
        doneButton.adjustsImageWhenHighlighted = NO;
        [doneButton setImage:[UIImage imageNamed:@"DoneUp.png"] forState:UIControlStateNormal];
        [doneButton setImage:[UIImage imageNamed:@"DoneDown.png"] forState:UIControlStateHighlighted];
        [doneButton addTarget:self action:@selector(doneButton:) forControlEvents:UIControlEventTouchUpInside];
        
        [foundKeyboard addSubview:doneButton];
    }
}
這邊要注意到的是, 因為同一個 app 有可能會在新舊版本的 OS 上執行, 所以若只有
針對 iOS4 而做修改, 就有可能會造成舊 iPhone 無法正常值行, 有鑒於此, 上述這段
 code 針對比對字串做了點小技巧, 讓此 code 可以符合新舊版本.
完整的範例可以到 這裡 下載

2010年9月12日 星期日

How to develop a multi-language app

目前 iPhone 的普及應該已經算是接近國民機的等級了, 在世界各地 iPhone 依然都還
是最搶手的手機之一, 若有想要在 iPhone 上面開發應用程式, 操作的使用界面就不能
單單只用自己國家的語言顯示, 若是企圖想要將自己的 app 發佈到其他國家, 多國語
系的支持就會是必要的.  至於要如何在 iPhone 上面開發多國語系的 app 呢?其實步驟
相當簡單, 首先你先新建一個 windows-base 的新專案, 並如下圖般的新增檔案(New File)


選擇 "Resource" 裡的 "Strings File" 選項

此新增的檔案名稱命名為 "Localizable.strings", 接著依照下圖點選 "Get Info"

開啓 Info 視窗之後, 點擊左下角的 "Make File Localizable" 並選到 "General" tag
此時在你會看到可以新增語系的選項"Add Localization", 若要新增繁體中文則輸入
zh_TW, 而簡體中文則輸入 zh_CN, 在下圖的語系中, 支援了三種



當完成之後會在專案檔案列表中看到 "Localizable.strings" 底下會產生語系字串檔
以筆者的例子而言, 會有三個檔案 "English" , "zh_TW", "zh_CN"


分別在此三個檔案裡面分別輸入不同語系字串內容
English :

"MultiString"="English Version";

zh_TW :
"MultiString"="繁體版本";

zh_CN :
"MultiString"="简体版本";




到目前為止, 已經完成了多國語系開發所需要的準備工作, 接下來就是示範如何
將他們呈現在 iPhone 畫面上.
開啓專案裡的 MultiLanguageAppDelegate.m, 並在 didFinishLaunchingWithOptions
裡面增加如下內容:


    CGRect frame = CGRectMake(10.0, 100.0, 200.0, 40.0);
    UITextView *text = [[UITextView alloc]initWithFrame:frame];
    [text setTextColor:[UIColor blackColor]];
    [text setFont:[UIFont systemFontOfSize:24]];
    [text setText:NSLocalizedString(@"MultiString",nil)];
    [window addSubview:text];
    [text release];
    

此時只要編譯並直接執行 iPhone , 然後在 Simulator 裡切換不同語系, 就會看到不同
的顯示字串

完整的 MultiLanguage 範例可以到 這裡 下載