2012年9月18日 星期二

Android開發環境準備

1. 安裝Eclipse

http://www.eclipse.org/downloads/

下載並安裝Eclipse for Mobile Developers



2. 啟動Eclipse

3. 點選Help -> Install New Software


4. 點選右邊的Add按鈕。



5. 輸入ADT的名稱和下載位置

Name : ADT Plugin
Location: https://dl-ssl.google.com/android/eclipse/


6. 在安裝的清單裡,勾選Developer Tools,然後再點選Next。

只是要開發App了話,不需要NDK Plugins來湊熱鬧。




7. 點選Next。


8. 勾選同意License後,點選Finish,開始安裝。


過程中若出現Security Warning,請不要害怕,勇敢地按下Ok吧。


9. 完成安裝,按下Yes重啟Eclipse。



10. 重啟後將看到SDK安裝的視窗。

請同時勾選Install latest SDK和目前仍然很多人使用的舊版2.2 SDK。



勾選是否同意回傳報告給Google。



勾選Accept All,全部安裝吧。



11. 設定PATH

export PATH=/usr/local/bin:$PATH:/Users/peterpan/android-sdks/tools:/Users/peterpan/android-sdks/platform-tools



2012年9月17日 星期一

只要有iPhone,人人都可以是攝影大師 - iOS 6的全景拍照

iOS 6支援全景拍照,而且不只iPhone 5獨享唷,連iPhone 4S也擁有此非凡能力。接下來,就讓彼得潘手上的iPhone 4S,為各位示範拍攝愛車的全景照片吧。不過可惜彼得潘不是有錢的蝙蝠俠布魯斯韋恩,所以拍攝的不是高級跑車,只是小小的單車啦。

1. 打開相機App,點選"選項"按鈕,再選擇"全景模式"


2. 進入傻瓜全景拍照模式。只要持續移動iPhone,即可完成全景照片。



3.  大功告成 ! 只要有iPhone,人人都可以是攝影大師 。





2012年9月16日 星期日

致命的Autolayout

當我們興高采烈地採用最新的Xcode 4.5,搭配最新的iOS 6 SDK,建立新專案開始開發時,一旦在iOS 5的機器上執行,卻馬上crash,死前遺言如下:




從遺言我們得知問題出在NSLayoutConstraint上,這是因為它是在iOS 6才冒出的類別 

NS_CLASS_AVAILABLE_IOS(6_0)
@interface NSLayoutConstraint : NSObject


讓我們回頭看看專案的storyboard,我們可發現在View下多了很多設定排版的Constraint。




切換到storyboard的File Inspector頁面,我們可發現Use Autolayout被勾選。

 
Autolayout是iOS 6才加入的排版機制,利用剛剛畫面上看到的Constraint,排列畫面上的元件。 為了能相容iOS 5以下的版本,我們只要取消此勾選,移除Autolayout,即可解決App crash的問題。







2012年9月12日 星期三

找不到Xcode的xcrun

在將Storyboard做Localization時,我們需要於Terminal輸入以下指令,將精心翻譯的語系版本文字輸入到Storyboard的畫面上。


ibtool --strings-file MainStoryboard.strings --write MainStoryboard.storyboard ../en.lproj/MainStoryboa.storyboard


此指令將用到xcrun,而xcrun必須找到一個存在的Xcode路徑。當我們進行多次Xcode的安裝,移除動作後,可能發生xcrun找不到Xcode的問題,出現以下錯誤訊息

xcrun: Error: could not stat active Xcode path '/Applications/Xcode45-DP4.app/Contents/Developer'. (No such file or directory)

這是因為xcrum找尋的Xcode45-DP4.app已經不存在,那是舊的路徑。假設目前Xcode位在/Applications/Xcode.app,只要輸入以下指令,即可解決問題

sudo xcode-select -switch /Applications/Xcode.app



2012年9月7日 星期五

不斷進化的Objective-C (MacToday 2012.9)



隨著Xcode 4.4的推出, Objective-C也有了大幅的進步。其實偷懶是人類的天性,科技的進步正是朝著偷懶的目標前進。接下來彼得潘將介紹的Objective-C三大新功能,完全實現了彼得潘不為人知的偷懶欲望,我們可以打愈少的字,犯更少的錯,開發更多的App,賺更多的錢,環遊世界玩更多的國家!

一.  自動補上@synthesize

@property和@synthesize的發明大大減輕了我們手指打字的疼痛程度,讓我們不用再千辛萬苦打下落落長存取物件member的setter和getter。然而所謂懶還要更懶,可以開車就不想走路,可以坐車就不想開車。不斷地打下member相對應的@property和@synthesize,也是很辛苦的。讓我們看看以下這個例子。


假設我們自訂一個蝙蝠俠類別,BatMan。舊時代的寫法如下:

BatMan的宣告 (BatMan.h) :  

#import <Foundation/Foundation.h>

@interface BatMan : NSObject
{
    NSString *name;
    NSString *gender;
}

@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) NSString *gender;


@end

BatMan的定義 (BatMan.m) :  

#import "BatMan.h"

@implementation BatMan

@synthesize name;
@synthesize gender;

@end


今天幸好BatMan只有名字和性別兩種屬性,若是我們連它的眼睛顏色,是否禿頭等各式小細節都想設定,當屬性愈多,我們需要耐下性子輸入的@synthesize也愈多。以剛剛的例子為例,name短短4個英文字組成的單字,仿佛怕我們遺忘它般一連出現三次,一次在member的宣告,一次在@property,一次在@synthesize。如果有一天,我們不用同樣的單字輸入三次,省下三分之二的時間去約會,該有多好! 如果不再是如果,讓我們看看以下這個超簡單Bat Man偷懶版。

BatMan的宣告 (BatMan.h) :  

#import <Foundation/Foundation.h>

@interface BatMan : NSObject

@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) NSString *gender;
@end

BatMan的定義 (BatMan.m) :  

#import "BatMan.h"

@implementation BatMan

@end

不用在類別裡宣告member,也不用再補上@synthesize,只要@property,聰明的Xcode馬上知道我們在想什麼,幫我們將剩餘的部分補上。雖然我們肉眼看不到,但它們確實存在,程式碼也實實在在地編譯成功了!  不過我們還是來解密一下,了解Xcode到底幫我們加上了什麼。

@synthesize name = _name;
@synthesize gender = _gender;

Xcode幫我們加了以上兩行程式碼,如此不只補齊了@synthesize,連member也自動幫我們生成。而member的名稱,正是 = 符號右手邊加了底線的名稱,_name和_gender。假設BatMan有一項飛翔的獨門絕技,有一個fly method,接下來我們讓BatMan一邊飛,一邊取名字。

-(void)fly
{
    _name = @"彼得潘";
}

在fly method裡,我們將BatMan的名稱取名彼得潘。利用偷偷產生的_name member來設定。

二.  神奇的@

Objective-C的物件讓人又愛又恨。因為物件,讓我們可以輕易設計許多天馬行空的App。但也因為物件,讓我們在使用某些常用型別,比方int, Array, Dictionary時,需要寫許多令人心煩的程式碼。現在有了神奇的@,一切都簡單多了。



(1) NSNumber

1.  一拍即合型
如果對象是數字,它和@完全是一拍即合,可以直接結合。

沒有@的世界末日

    NSNumber * endOfTheWorld = [NSNumber numberWithInt: 2012];

神奇@的世界末日
  
NSNumber *endOfTheWorld = @2012;


2.  月下老人 ( ) 牽線型

如果不是數字,還是可以結合,只不過需要 ( ) 的幫忙撮合。比方method getEndOfTheWorld回傳數字,讓我們看看它如何結合@。

-(int)getEndOfTheWorld
{
    return 2012;
}

沒有@的世界末日

    NSNumber * endOfTheWorld = [NSNumber numberWithInt: [self getEndOfTheWorld]];

神奇@的世界末日

    NSNumber *endOfTheWorld = @([self getEndOfTheWorld]);


(2) NSArray

結合@ 和 [ ] ,我們可以輕易創造NSArray。接下來我們以彼得潘看了2次的蝙蝠俠三部曲為例說明。

沒有@的蝙蝠俠三部曲

    NSArray *batmanMovies = [NSArray arrayWithObjects:@"開戰時刻", @"黑暗騎士", @"黎明升起", nil];

神奇@的蝙蝠俠三部曲

    NSArray *batmanMovies = @[@"開戰時刻", @"黑暗騎士", @"黎明升起"];

利用神奇@來創造array,不只程式碼更加精簡,最重要的我們終於甩掉沒路用的nil了。從前利用arrayWithObjects:生成array,必須以nil做訊號表示已經來到array的盡頭,後頭無一物了。現在神奇@聰明多了,只要將array裡的物件一一交給它,它就懂了。

蝙蝠俠是如此地賣座,不管是電影公司或影迷,都願意為了第4集再砸錢吧。不過要拍第4集可沒那麼簡單,利用@建立的array是不可變的NSArray。現在該是向變形金剛學習的時刻了。讓我們將@生成的NSArray變型為NSMutableArray。

  NSMutableArray *batmanMovies = [@[@"開戰時刻", @"黑暗騎士", 
      @"黎明升起"] mutableCopy];
 [batmanMovies addObject:@"當蝙蝠俠遇上彼得潘"];


(3) NSDictionary

結合@ 和 { },我們可以輕易創造NSDictionary。接下來彼得潘以最近推出新專輯的蔡淳佳新專輯曲目來說明。

沒有@的蔡淳佳新專輯主打歌

    NSDictionary *joiNewAlbum = [NSDictionary dictionaryWithObjectsAndKeys:@"Love You", @"song1", @"不透光", @"song2", nil];


神奇@的蔡淳佳新專輯主打歌

    NSDictionary *joiNewAlbum = @{ @"song1" : @"Love You", @"song2": @"不透光" };


三.  更方便的存取集合裡的元素 (Object Subscripting) 

透過全新的Object Subscripting語法,我們能夠以更簡潔利落的程式碼存取集合裡的元素。所謂集合,最具代表性的莫過於NSArray和NSDictionary了。讓我們繼續以剛剛的batmanMovies和joiNewAlbum為例,並配合實際的UI畫面demo說明。

(1) 畫面設計


說明:
待會我們將利用movieLabel和songLabel填入電影名和歌曲名。

(2) 程式設計

沒有Object  Subscripting的舊時代寫法:


- (void)viewDidLoad
{
    [super viewDidLoad];

    
    NSMutableArray *batmanMovies = [@[@"開戰時刻", @"黑暗騎士", @"黎明
                  升起"]
                                    mutableCopy];
    [batmanMovies addObject:@"當蝙蝠俠遇上彼得潘"];
    NSDictionary *joiNewAlbum = @{ @"song1" : @"Love You", 
        @"song2": @"不透光" };

    movieLabel.text = [batmanMovies objectAtIndex:3];
    songLabel.text = [joiNewAlbum objectForKey:@"song2"];
}

執行結果:



Object  Subscripting的新時代寫法:

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    NSMutableArray *batmanMovies = [@[@"開戰時刻", @"黑暗騎士", @"黎明
                    升起"]
                                    mutableCopy];
    [batmanMovies addObject:@"當蝙蝠俠遇上彼得潘"];
    NSDictionary *joiNewAlbum = @{ @"song1" : @"Love You", 
        @"song2": @"不透光" };

    movieLabel.text = batmanMovies[3];
    songLabel.text = joiNewAlbum[@"song2"];
}
說明:
利用[ ] 內指定數字存取array裡的物件( 第一個物件的index為0),指定key則可存取dictionary裡的物件。

想要具有Object Subscripting的神奇魔力,其實很簡單,想要像NSArray一樣透過index存取,需要定義以下2兩個method:

- (id)objectAtIndexedSubscript:(NSUInteger);
- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx;

想要像NSDictionary一樣透過key存取,需要定義以下2兩個method:

- (id)objectForKeyedSubscript:(id)key;
- (void)setObject:(id)object forKeyedSubscript:(id)key;


接下來彼得潘就以Peter Pan的自我介紹為例,說明如何讓自訂類別具有Object Subscripting的神奇魔力吧。

(1). PeterPan類別的宣告 
#import <Foundation/Foundation.h>

@interface PeterPan : NSObject
{
    NSString *lover;
    NSString *enemy;
    
}

- (id)objectForKeyedSubscript:(id)key;
- (void)setObject:(id)object forKeyedSubscript:(id)key;

@end

(2). PeterPan類別的定義,定義實現Object Subscripting的必要method objectForKeyedSubscript:和setObject:forKeyedSubscript:。
- (id)objectForKeyedSubscript:(id)key
{
    if([key isEqualToString:@"最愛"])
    {
        return lover;
    }
    else if([key isEqualToString:@"死對頭"])
    {
        return enemy;
    }
    else
    {
        return nil;
    }
}


- (void)setObject:(id)object forKeyedSubscript:(id)key
{
    if([key isEqualToString:@"最愛"])
    {
        [self setValue:object forKey:@"lover"];
        
    }
    else if([key isEqualToString:@"死對頭"])
    {
        [self setValue:object forKey:@"enemy"];
        
    }
}

測試程式

- (void)viewDidLoad
{
    [super viewDidLoad];
    PeterPan *peterPan = [[PeterPan alloc] init];
    peterPan[@"最愛"] = @"温蒂";
    peterPan[@"死對頭"] = @"虎克船長";
    self.loverLabel.text = peterPan[@"最愛"];
    self.enemyLabel.text = peterPan[@"死對頭"];
}
說明:
由於peterPan物件學會了Object Subscripting,因此我們可以透過[ ] ,傳入@”最愛”和@”死對頭”做為key來存取。q


執行結果:




2012年9月3日 星期一