2012年11月30日 星期五

背景GPS模式提醒

Apple貼心地開放了某些功能,讓App即使進入了不見天日的背景模式,依然可以繼續執行這些功能。但是,如果選擇的是耗電的背景GPS偵測模式,請記得要在App Store上的App介紹提醒使用者,不然可是會讓Apple reject的! 


    

為了不被Apple reject,請記得加入以下文字



   

2012年11月29日 星期四

不再念舊,只保留@2x圖檔的國王新衣陷阱

iPhone就像美麗的model LUCY一樣,不只有內在,同時也有難以抗拒的外在。iPhone外觀的優點,就像LUCY美麗的點,十根手指也數不完。不過如果非要選出代表性的,想當然是高解析度的Retina螢幕當仁不讓地中選。

有了Retina螢幕,App可以呈現更高解析度,更高畫質的圖片。然而美麗是有代價的,一個不小心,可是會開天窗,變成國王的新衣,什麼都看不到! 接下來彼得潘將以LUCY的2張美麗照片為例,說明retina顯示暗藏的致命陷阱。

左邊的圖片為lucy.jpg,右邊為lucy@2x.jpg。聰明的iPhone在顯示圖片時,將根據檔名做判斷,加了@2x的圖片將現身於retina的高解析度螢幕,而少了@2x加持的圖片只有念舊仍然拿著低解析度iPhone的使用者看得到。




因此,當我們執行以下程式碼後,顯示結果如下:


self.imageView.image = [UIImage imageNamed:@"lucy.jpg"];



舊型iPhone (例如iPhone 3GS)



retina糖衣加持的新型iPhone (例如iPhone 5)




雖然念舊是個好習慣,不過有些時候人要向前看,像是為了促進經濟發展買iPhone 5,為了不讓新女友難過忘了舊情人。為了減少App的size,彼得潘決定將lucy.jpg狠心從App刪除,只保留lucy@2x.jpg。如果以剛剛的程式碼在舊型的iPhone再跑一次,結果如下:



iPhone真聰明,自動地將lucy@2x.jpg縮小,顯示於舊解析度的螢幕上。然而條條大路通羅馬,顯示圖片的方法也不只一種,如果採用以下方法,LUCY就像變魔術般,從螢幕上整個消失不見!


NSString *path = [[NSBundle mainBundle] pathForResource:@"lucy.jpg" ofType:nil];
NSLog(@"path %@", path);
self.imageView.image = [[UIImage alloc] initWithContentsOfFile:path];






說明:
線索其實很明顯。印出的Log訊息如下:

    path (null)

剛剛的程式碼,我們先取得圖檔的檔案路徑。然後再以UIImage的initWithContentsOfFile: method,傳入檔案路徑來設定顯示的圖片。但別忘了lucy.jpg早已不存在App裡,只留在彼得潘的記憶深處呀。 因為取得的檔案路徑path是空的,因此UIImageView完全不知道要顯示哪一張圖片,也就只能開天窗,一片空白了。



因此,如果堅持要使用 initWithContentsOfFile:來設定顯示的圖片,請記得要加下@2x,如此美麗的LUCY就可以再度出現在我們的眼前了。

NSString *path = [[NSBundle mainBundle] pathForResource:@"lucy@2x.jpg" ofType:nil];


2012年11月24日 星期六

不能說的秘密,就讓NSNotificationCenter來傳遞吧

利用NSNotificationCenter產生通知,我們可以輕易地讓不同物件跨越空間時間溝通。接下來彼得潘將以電影"不能說的秘密"舉例說明,女主角小雨,男主角彼得潘,男配角葉湘倫之間不能說的秘密,就讓NSNotificationCenter來為他們傳遞吧。

1. 定義Person類別


@interface Person : NSObject

@property (nonatomic, strong) NSString *name;

@end


2. 建立故事的三個主人翁


smallRain = [[Person alloc] init];
smallRain.name = @"小雨";

peterPan = [[Person alloc] init];
peterPan.name = @"彼得潘";

noBody = [[Person alloc] init];
noBody.name = @"葉湘倫";

3.  設計App畫面



畫面上加入按鈕(UIButton),按鈕的圖片上顯示小雨在大雨中對著天空吶喊的問題。


4. 傳送"不能說的秘密"通知

將按鈕的Touch Up Inside event連結至buttonPressed: method,並定義此method。我們已經看到按鈕上小雨詢問的問題了。為了不讓她等太久,我們希望按鈕按下時,馬上回應小雨。因此buttonPressed: 的定義如下:

- (IBAction)buttonPressed:(id)sender {
         [[NSNotificationCenter defaultCenter] postNotificationName:@"不能說的秘密" object:peterPan userInfo:@{@"答案":@"我在這邊,你在那邊,愛像風箏一條線,我經過千山萬水 停在這個定點,帶我的心,到你的世界"}];
}

說明:
利用NSNotificationCenter物件的postNotificationName:object:userInfo: method,我們可以發送通知讓對方知道,此method的定義如下:

- (void)postNotificationName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo;

(1)aName: 通知的名稱。在這裡我們傳入"不能說的秘密"。到時候只有表明想收到"不能說的秘密"通知的物件,才會收到此通知。

(2) anObject: 發送通知的物件。 在這裡我們傳入peterPan,表明peterPan是真心回應小雨的Mr.Right。若是想要匿名也是可以,只要傳入nil,對方即無法知道通知的來源,但如此有可能造成對方收不到通知,等會我們會說明。

(3) aUserInfo: 想讓接收物件知道的額外資訊。由於是NSDictionary型別,所以基本上我們可以傳入任何的資訊。在此我們傳入彼得潘想對小雨說的話( 其實此段話為伍思凱"這邊那邊"的歌詞)。

5. 申請接收"不能說的秘密"通知

 [[NSNotificationCenter defaultCenter] addObserver:smallRain selector:@selector(get:) name:@"不能說的秘密" object:peterPan];

小雨為了要收到彼得潘的回應,她必須先申請接收"不能說的秘密"通知。利用NSNotificationCenter物件的addObserver:selector:name:object: method,小雨可以讓自己收到通知,此method的定義如下:

- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject;

(1) observer: 接收通知的物件,在此我們傳入smallRain,如此小雨即可收到通知。

(2) aSelector: 收到通知後執行的method。 小雨收到通知後,可能大哭,也可能大笑。不過別忘了我們是導演,我們傳入@selector(get:),等會再來定義get:。值得注意的,observer和aSelector是對應的,所以到時候get:將是定義在smallRain Person型別裡的method。

(3) aName: 通知的名稱,在此我們理所當然傳入"不能說的秘密"。

(4) anObject: 指定發送通知的對象。只有當通知是由此對象發送時,observer才會收到通知。在此我們傳入peterPan,所以只有當通知是由彼得潘發出時,小雨才會收到通知,get: method才會被呼叫。如果傳入nil了話,表示observer願意接收任何物件發出的"不能說的秘密"通知。因此如果傳入nil,小雨就可以收到葉湘倫發出的通知。但小雨是個專一的人,她的眼中只看得到彼得潘,看不到葉湘倫,所以我們還是傳入peterPan吧。

6. 定義小雨收到通知後執行的get: method (在Person.m裡)

-(void)get:(NSNotification*)noti
{
    Person *person = noti.object;
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:noti.userInfo[@"答案"] message:nil delegate:self cancelButtonTitle:person.name  otherButtonTitles:nil];
    [alertView show];    
}
說明:
NSNotification物件的object將等同發送通知的物件,也就是彼得潘。而NSNotification物件的userInfo則等於當初彼得潘發送通知時傳入的userInfo,因此從key"答案",我們可以取得彼得潘想說的話。當小雨看到彼得潘的回應時,感動地大聲朗誦出來,因此我們以UIAlertView在畫面上加以呈現。

執行App:

按下按鈕後,彼得潘果真回應了小雨,而小雨也收到了,因此我們在畫面上看到訴說著"我在這裡 ... "的UIAlertView。



如果當初發出通知的是代表葉湘倫的noBody,即便他很深情的以林俊傑"你要的不是我"的歌詞來回應,由於小雨早已指定只接收來自彼得潘的通知,所以小雨永遠也不會收到葉湘倫的訊息。

 [[NSNotificationCenter defaultCenter] postNotificationName:@"不能說的秘密" object:noBody userInfo:@{@"答案":@"你要的不是我,心碎的失去輪廓,曾經給你的感動,只是情緒的波動"}];

執行App:

不管我們按了幾百,幾千次按鈕,小雨都收不到來自葉湘倫的通知,因此永遠也看不到UIAlertView。



不可小看的背景陷阱:

如果當初我們呼叫postNotificationName:object:userInfo:發送通知時處在背景thread,而非main thread,到時候收到通知時所呼叫的method也將會在背景thread執行。以剛剛的例子來說,如果我們不幸在背景thread發送通知,到時候收到通知時,App將壯烈的crash死去。這是因為我們收到通知時會顯示UIAlertView,但此時卻處於背景thread,違反了UI相關程式一定要在main thread執行的規定。






2012年11月23日 星期五

最佳企業App LOCOMO (App Next 2012應用程式大賽 )

Passion Bean的LOCOMO獲選為最佳企業App !




英雄難過美人關,利用美人計啟動Facebook App

彼得潘常常和有著自己FB粉絲團的偶像,藝術家或是朋友合作App,恆久不變的除了我們之間合作的情誼外,另一個就是App的關於頁面了。關於頁面往往包含了相關的FB,Blog和網站連結。

連結至FB很簡單,只要利用UIWebView開啟對應的網址即可。然而針對iPhone特別設計的Facebook App,帶給使用者比純網頁好上100倍的瀏覽體驗。因此更貼心的做法其實是直接透過Facebook App開啟FB的連結。所謂英雄難過美人關,接下來彼得潘將以美女Model Lucy的Facebook粉絲團Love LUCY Love為例,說明如何利用美人計,讓Facebook App如此地英雄好漢聽話地幫我們打開LUCY的粉絲團。

 1. 查詢粉絲團的ID

我們可以指定Facebook App打開某個粉絲團或某個人的塗鴉牆,不過可惜它不識英文,不識中文,只識由數字組成的ID。在Facebook的世界裡,不管是粉絲團還是個人,都有一個獨一無二的識別ID,就好像我們的身份證字號一樣。

問題來了,要怎麼知道粉絲團Love LUCY Love的ID呢? 很簡單,只要以下3個步驟:

(1) 連到Love LUCY Love粉絲團,取得粉絲團的網址。


請先將視線從LUCY身上移開,往上瞧一點,觀察網址列裡的網址。

http://www.facebook.com/Love.Lucy.fans?fref=ts


(2) 取得粉絲團的username。


在網址列裡,在com/後,?之前的Love.Lucy.fans,正是我們夢寐以求的username

(3) 取得粉絲團的ID

有了username後,我們只要輸入以下網址,即可取得ID。(規則為http://graph.facebook.com/ 加 username)

http://graph.facebook.com/Love.Lucy.fans


雖然回報的資料密密麻麻,但都走到這一步了,努力地找一下吧,答案就藏在以下這一行

"id": "151582191520747",沒錯,就是你了,ID 151582191520747。


ps: 其實有些人沒有特別設定過Facebook上的username,他們的FB網址即直接帶有ID資訊,例如以下網址:
http://www.facebook.com/profile.php?id=100000045374040



 2. 啟動Facebook App



NSURL *url = [NSURL URLWithString:@"fb://profile/151582191520747"]; [[UIApplication sharedApplication] openURL:url];

說明:
利用UIApplication物件的openURL: method,我們可以啟動外部的App。至於啟動哪一個,關鍵就在於開頭的字串了。比方tel://會啟動電話App,而Facebook也不怕別人知道,坦蕩蕩地使用它的縮寫fb。所以我們只要以fb://profile/為開頭,然後加入千辛萬苦取得的ID,即可讓Facebook App上勾,墜入情網,心甘情願地為我們開啟LUCY的粉絲團。







LUCY簡介:
粉絲團: Love LUCY Love 
生日:  2月7日 (和彼得潘一樣,好日子)
科系: 輔大心理系 ( 對人心有深入了解) 
星座: 水瓶座 ( 好星座,不是只有天秤座才出帥哥美女呀 )
職業: Model,代言/平面/網拍/廣告/主持/展場/活動
聯絡: lucy.chiayun@gmail.com



2012年11月18日 星期日

消滅status bar怨念產生的黑洞 ~ 以LUCY的美麗魔力 !

iPhone畫面的最上方,有個幾乎無時無刻存在的status bar,顯示著時間,電量,訊號強度等重要資訊。許多遊戲類的App會隱藏status bar,因為它們邪惡地想讓我們沉迷遊戲,忘了時間。而非遊戲類的App一般會顯示status bar,讓我們在操作App時仍然能夠知道電量,時間等重要資訊,而不用離開App查詢。

有沒有兩全其美的方法呢? 當然有,古人有點石成金,彼得潘有點螢幕殺status bar,感謝和彼得潘同月同日生的超人氣Model LUCY的合作,接下來我們將示範如何觸碰螢幕控制status bar的存亡,並且清除status bar怨念產生的黑洞。

一. 在畫面上加入按鈕,顯示"正在聞著新鮮空氣的LUCY"




- (void)viewDidLoad
{
    [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
 
     
    UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 320, [UIScreen mainScreen].bounds.size.height)];
    button.imageView.contentMode = UIViewContentModeScaleAspectFill;
    [button setImage:[UIImage imageNamed:@"lucy.jpg"] forState:UIControlStateNormal];
    [self.view addSubview:button];
    [button addTarget:self action:@selector(buttonPressed:)
                     forControlEvents:UIControlEventTouchUpInside];
 
 
}
說明:
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 320, [UIScreen mainScreen].bounds.size.height)];
設定button的高度為螢幕的高度,換句話說,在iPhone 4s時,是480 points,在iPhone 5時,是568 points。

二. 在按鈕被觸碰時,控制status bar的隱藏和現身

-(void)buttonPressed:(id)sender
{

    if([UIApplication sharedApplication].statusBarHidden)
    {
        [UIApplication sharedApplication].statusBarHidden = NO;
    }
    else
    {
        [UIApplication sharedApplication].statusBarHidden = YES;

    }
}
說明:
當status bar顯示時,點選按鈕叫它滾開,不想再看到它。
當status bar隱藏,而我們又開始思念它時,點選按鈕可以再把它追回來,讓它出現。

執行App:

status bar就像個聽話的女朋友,我們不想看到她時,點一下畫面她乖乖消失。我們想念她時,點一下畫面,她馬上出現。但是當她不在時,卻有個怪異的地方,原本她佔據的空間,變成一長條黑色的區塊(約20 points的高度)。看來一定是她可怕的怨念,留下那破壞畫面美感的黑洞。




三. 黑洞怨念形成的原因

讓我們來查查事情的真相,研究黑洞形成的原因吧。請加入以下的程式碼

-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    
    NSLog(@"view %@", self.view);

}

當我們再一次執行App時,發現Log印出
view <UIView: 0x7125f50; frame = (0 20; 320 548); autoresize = RM+BM; layer = <CALayer: 0x7126530>>
謎底解開了,原來view controller的view一開始的起始y座標就在20,難怪status bar消失後,會留下高度20 points的黑洞。

四. 用LUCY佔滿螢幕的美麗消滅黑洞

還好status bar的怨念不像七夜怪談的貞子那麼可怕,不需要大法師,只要LUCY的美麗就能消滅它。LUCY的這張照片如此漂亮,值得佔滿整個螢幕。我們只要在剛剛的viewDidLoad method裡,將view controller的wantsFullScreenLayout設為YES,即可讓view controller的view佔滿螢幕,換句話說,起始點將是(0, 0),而不是(0, 20)

    self.wantsFullScreenLayout = YES;

執行App:

我們可以清楚看到,這次LUCY是完完全全佔滿螢幕的,所以status bar是重疊地覆蓋在她的上方。





也因為LUCY多了20 points的展示空間,所以這次她的鞋子沒有再不小心被切到了。若是回頭看看Log印出的訊息,可發現此時view controller的view果然從(0, 0)開始。
view <UIView: 0x7435ce0; frame = (0 0; 320 568); autoresize = RM+BM; layer = <CALayer: 0x74362c0>>



LUCY簡介:
粉絲團: Love LUCY Love 
生日:  2月7日 (和彼得潘一樣,好日子)
科系: 輔大心理系 ( 對人心有深入了解) 
星座: 水瓶座 ( 好星座,不是只有天秤座才出帥哥美女呀 )
職業: Model,代言/平面/網拍/廣告/主持/展場/活動
聯絡: lucy.chiayun@gmail.com



2012年11月17日 星期六

彼得潘和mini Hana的Christmas App

彼得潘不會畫畫,但卻很願意幫為了夢想畫畫的插畫家實現夢想。2012年的Christmas,希望彼得潘和mini Hana可以帶給大家洋溢幸福氛圍的Christmas App !



2012年11月6日 星期二

全新的LOCOMO 2.0上架了




全新的LOCOMO 2.0上架了 ! 全新的側滑選單和iPhone 5螢幕支援,帶來不同凡想的視覺體驗 ! 






2012年11月2日 星期五

下載土豆網的"讓我照顧你"

無意間在網路上聽到了孫耀威的經典歌曲"讓我照顧你",可惜只能在土豆網上聆聽,Youtube上竟然尋覓不著。



經過小小的研究後,彼得潘終於找到下載土豆網影片的方法,在這裡和大家分享。

1. 連到以下網站
http://www.flvcd.com

2. 貼上土豆網上"讓我照顧你"影片的網址


3. 點選"開始Go"

4. 終於取得下載連結了,趕緊點選"複製地址"吧


5. 在Safari的網址列貼上剛剛複製的URL,然後再按下Option + Enter,立即啟動下載。


終於,當彼得潘一個人漫步在只有沙路,沒有網路的海邊時,口袋裡的iPhone還是可以持續播放"讓我照顧你"。最後,讓我們好好來聆聽這首好歌吧。






讀檔達人預覽程式 (PC home 2012.11)



飯是用來吃的,茶是用來喝的,那Mac呢,如果只能以一個字來形容,那大概只有一個答案吧,它是用來看的。在Mac上我們會閱讀,瀏覽各式各樣的檔案,而幾乎無所不開,無所不看的預覽程式(Preview),正是我們一定要學會,離不開的百看App。而且隨著時代進步的預覽程式,現在不單單讀,還有著多樣的編輯功能。可以說預覽程式大大省下我們的荷包,斷了其它App生存的活路呀。接下來,就讓彼得潘好好來為各位介紹它的絕妙應用吧。

自動排版的Autosizing (MacToday 2012. 11)




這世界一直在改變,就連始終如一的iPhone也是。iPhone 5的推出,讓我們想要一網打盡,通通支援的螢幕尺寸又多了一種。一個個針對不同尺寸調整App畫面的排版又是何苦呢? 有了Autosizing和Autolayout的幫忙,聰明地自動調整UI元件的大小和位置,再也不是難事。但Autolayout只支援iOS 6,因此接下來彼得潘將先針對 Autosizing,以華仔的經典電影孤男寡女為例,無論畫面怎麼變,我們都要讓華少和Kinki永不分離,完美地呈現在畫面上。