2012年3月28日 星期三

懶人import header法

若是某個header檔的定義很多地方都會用到, 我們往往需要在每個用到的地方import header。 然而, 其實有一招偷懶的訣竅。 只要於pch檔import此header, 即可到處都存取到此header裡的定義。

2012年3月24日 星期六

HPX Life 5 講座 – 彼得潘的App逐夢之旅

http://www.hpx-party.com/blog/archives/4772


管理controller的超級controller - container view controller - 發生在南天宮和劍潭捷運的Kiss

一般的view controller,管理的是畫面上的view。
然而,在iOS的世界裡,
view controller也有著強弱之分。
超級controller管理的是controller,而不是單單的view。
比方我們常見的tab bar controller,
正是超級controller的代表。
當畫面上有4個tab時,
每個tab顯示的畫面分別由對應的view controller控制。
但tab bar controller控制著這些tab對應的controller,
控制著哪個tab的畫面能夠亮相。
因此最後畫面呈現內容的決定權,
其實掌控在超級controller tab bar controller手上。

在iOS 5,
除了內建的超級controller
我們終於可以創建自己的超級controller。
由於超級controller管理的對象為controller,
所以又被稱為container view controller。

接下來彼得潘將以百吻巴黎楊雅晴的美麗圖片,
為各位示範container view controller的應用。

1.  布置超級controller ContainerViewControllerViewController的畫面。

     此controller的view也將是App的主畫面。
      



     container view controller雖然特別之處在於控制其它controller,
     但它依然是不折不扣的view controller,
     因此它也控制著自己view上的畫面內容。     
     如上圖所示,
     我們於它的view上添加兩個button,
     "台中南天宮"和"劍潭捷運站",
     只要點選button,
     即可看到發生於其中的浪漫Kiss照片。


  
   
      於畫面上我們另外加入一片浪漫的粉紅色背景,
      將來甜美的Kiss照片,
      將呈現於其中。
      而負責呈現圖片的,
      將是我們待會要創建,
      被ContainerViewControllerViewController管理的controller。 

2.   定義繼承自UIViewController的LeftViewController和RightViewController
    
       他們分別負責"台中南天宮"和"劍潭捷運站"Kiss圖片的呈現。

       說明:
       (1)     self.view.frame = CGRectMake(0, 0, 320, 320);
       
       我們必須設定view的大小和位置,
       此影響到時候Kiss圖片出現的位置和大小。
     
       我們稱ContainerViewControllerViewController為parent view controller,
       而其控制的LeftViewController和RightViewController為child view controller,
       child view controller畫面佔據的位置和大小,
       由其view的frame決定。
       這是因為到時候child view controller的view將被加到parent view controller掌控的view上,
       (parent view controller掌控的view可以是其掌控的任何一個view,
        比方view A的subview,view B。 )

3.   指定ContainerViewControllerViewController管理的controler。

      說明:
      (1).     [self addChildViewController:leftController];
         
           利用addChildViewController: method,將leftController交由ContainerViewControllerViewController物件管理。

     (2).    [contentView addSubview:leftController.view];
   
           child view controller的畫面,能夠出現在parent view controller的畫面。
           其實道理很簡單,
           正是我們最熟悉不過的addSubview:。
           我們將它加在containerView上 (前面建立的紫色畫面)
           將Kiss圖片限制於此區塊內神聖地保護著。

4.  切換顯示的kiss圖片 

    切換顯示的kiss圖片,
    其實也就是切換顯示圖片的child view controller。

    說明:
    (1) RightViewController *leftController = [self.childViewControllers objectAtIndex:0];
          LeftViewController *rightController = [self.childViewControllers objectAtIndex:1];

          利用childViewControllers property,取得管理的child view controller。

    (2)  [self transitionFromViewController:rightController toViewController:leftController duration:2.0 options:UIViewAnimationOptionTransitionFlipFromLeft animations:nil completion:nil];

          此method的定義如下

          fromViewController: fromViewController的view將被移除,
          toViewController: toViewController的view將被加入。
          duration: 動畫的時間。
          options: 定義動畫效果
          animations: 定義動畫效果
         completion: 定義切換成功後,執行的程式碼。

         有關動畫部分,
          請記得影響的範圍將是child view controller的view的parent view。
          因此當UIViewAnimationOptionTransitionFlipFromLeft動畫進行時,
          將只在前面建立的contentView內翻轉。


執行結果:






2012年3月20日 星期二

macports

problem:
Warning: xcodebuild exists but failed to execute Warning: Xcode appears to be installed but xcodebuild is unusable


solution:
sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer 

2012年3月19日 星期一

不愛ARC的舊時代檔案

很多時候,
我們會遇到前人寫的程式碼,
他們於沒有ARC的艱困環境,
費盡千辛萬苦完成。
當我們將這些檔案加入ARC專案時,
若想保險起見,
完全不更動這些舊檔案。
只要於target的Build Phases頁面,
於Compile Sources區塊,
將不支援ARC檔案的Compiler Flags設為
-fno-objc-arc。




2012年3月17日 星期六

ARC下不可不慎的method取名



ARC做事有它自己的原則,
其中的關鍵在於method的取名。

以上圖為例,
當method名稱為getArtist時,
ARC認為此method回傳的物件有點髒亂,
需要被丟到autorelease pool好好清洗一番。
因此雖然接收的變數artist宣告為__weak,
但此物件還可以繼續存活,
直到autorelease pool將pool裡的物件release。

但當method名稱以alloc, copy,  new, init, mutalbeCopy開頭時,
回傳物件的生死將由接收的變數決定。
由於接收的artiest2宣告為__weak,
表明了對回傳的物件沒有興趣。
所以此物件將馬上被release,
結束它短暫又平凡的一生。

神奇的KVC ( key-value coding)

2012年3月13日 星期二

git submodule的使用

在UseShareLibraryProject1 project裡加入ShareLibrary project


1. git submodule add git@github.com:deeplovepan/ShareLibrary.git
   將ShareLibrary抓下來

2. git commit
    commit ShareLibrary和.gitmodules
 
3. git submodule init
   更新.git/config
  ->
  多了
  [submodule "ShareLibrary"]
   url = git@github.com:deeplovepan/ShareLibrary.git

在UseShareLibraryProject1裡修改submodule ShareLibrary

1. cd ShareLibrary/ShareLibrary, modify ShareLibraryAppDelegate.m

2. git add ShareLibrary/ShareLibraryAppDelegate.m

3. git commit

4. git push
   從push只修改到github上的ShareLibrary project

5. 回到UseShareLibraryProject1根目錄, 從根目錄commit和push,
   如果才會更新UseShareLibraryProject1採用的submodule版本

6. git add ShareLibrary

7. git commit

8. git push


其它人抓取UseShareLibraryProject1

1. git clone git@github.com:deeplovepan/UseShareLibraryProject1.git

2. git submodule init
    更新.git/config,多了submodule的資訊

3. git submodule update
    抓取submodule內容


其它人更新UseShareLibraryProject1

1. git pull
   更新紀錄的submodule資訊,此時打git submoule,
   若開頭有+,表示submodule內容有修改,需更新
   ex:
   +be295206e07a1eeb6243fa5ee2466c1f6e990e94 ShareLibrary
 
2. git submodule update
   若submodule有更新,抓取submodule內容



只針對UseShareLibraryProject1下的ShareLibrary更新,因為github上的ShareLibrary project有修改



1. 切換至UseShareLibraryProject1下的ShareLibrary

2. git pull origin master

3. 回到UseShareLibraryProject1根目錄
   此時打git submodule將出現以下訊息
   +27c6861c06fdb3a9c82d9b70d41f6287bc068961 ShareLibrary (remotes/origin/HEAD)
   開頭的+表示submodule被更動了
 
4. git add ShareLibrary

5. git commit
   此時再打git submodule,開頭的+不見了
   27c6861c06fdb3a9c82d9b70d41f6287bc068961 ShareLibrary
 
6. git push





2012年3月9日 星期五

在Newsstand上架

一般的App會出現在home畫面,
然而像雜誌,報紙這類的App,
若是能出現在Newsstand裡,
其實會更方便讀者閱讀,
而且還能享有於背景下載的好處。

只要以下3個步驟,
即可讓彼得潘的新書"App程式設計入門"變身為充滿文藝氣息,
靜悄悄於背景下載最新一期內容的電子書:

1. 加入NewsstandKit.framework。

2. 於target的info頁面,新增欄位Application presents content in  Newsstand,並將其設為YES。


      原來它就是那道光,那道讓App出現於Newsstand App裡的關鍵角色。

3. 於target的info頁面,新增欄位Required background modes,並將其設為newsstand-content。



       只有設為newsstand-content,才能觸發背景下載的魔力。

執行結果:





設定螢幕截圖的檔案格式

身為抱著Apple作夢的作家,
拍下螢幕截圖(screenshot)是少不了的工作。
不需另外安裝軟體,
只要  Shift + Command + 4,
即可切換至截圖模式,
以觸控版拉出截取的框框大小。

然而,
出版社要求tiff格式,
blog要求png格式。
因此常常需要不斷地切換截圖的檔案格式。

只要在Terminal輸入以下兩行指令,
即可輕鬆設定圖片格式。

設定格式為jpg

defaults write com.apple.screencapture type jpg
killall SystemUIServer

以下即為彼得潘截取PunApp專欄於Yahoo的圖片



github和Xcode的結合

1. 在Mac上從Xcode 建立新專案PeterPanCocoaLib

從organizer視窗的Repositories分頁找到PeterPanCocoaLib,此時可看到已經有了第一次的Initial Commit。



2. 在github上建立專案PeterPanCocoaLib,取得SSH連結



3. 在organizer視窗的Repositories分頁找到PeterPanCocoaLib

點選Remotes -> Add Remote



4. 輸入remote資訊
name:   origin
Location:  SSH連結




5. 將Mac上的專案PeterPanCocoaLib push到remote







2012年3月7日 星期三

NSNotificationCenter

- (id)addObserverForName:(NSString *)name object:(id)obj queue:(NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block

只接收obj發出的notification


- (void)postNotificationName:(NSString *)notificationName object:(id)notificationSender

notificationSender: 發出notification的sender

非同步網路探究

NSURLConnection:
+ (void)sendAsynchronousRequest:(NSURLRequest *)request
                          queue:(NSOperationQueue*) queue
              completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*)) handler
->
When the request has completed or failed, the block will be executed from the context of the
specified NSOperationQueue

ex:
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue 
                           completionHandler:^(NSURLResponse *response,    
                                    NSData *data, NSError *error) 
 {
         NSLog(@"thread %p %p", [NSThread currentThread], [NSThread mainThread]);
}];
->   currentThread != mainThread

NSOperationQueue *queue = [NSOperationQueue currentQueue];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue 
                           completionHandler:^(NSURLResponse *response,    
                                    NSData *data, NSError *error) 
 {
         NSLog(@"thread %p %p", [NSThread currentThread], [NSThread mainThread]);
}];
->   currentThread == mainThread

block和物件生命的關係:


假設呼叫以下method


 [NSURLConnection sendAsynchronousRequest:req queue:[NSOperationQueue currentQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {

}];
如果block裡帶有某個物件,則此物件將維持生命直到block執行完。











2012年3月6日 星期二

為太空飛鼠建立static library

感謝蘇森力畫了可愛的太空飛鼠,


今天彼得潘將為各位介紹如何建立static library (.a檔)
讓所有喜歡牠的人,
都能輕易將牠加入自己開發的App。

1.  新增target
     static library也是target的一種。

2. 選擇Cocoa Touch Static Library


3. 將static library,也就是target的名稱命名為CuteMouse


4. 新生的target, CuteMouse。
 
5. 將欲編譯成libCuteMouse.a的source code加入
 
     比方CuteMouse.m想加入,那麼我們必須在其Target Membership的設定裡將CuteMouse勾選

  
6. 編譯libCuteMouse.a

    請針對device和simulator分別編譯,產生對應的CuteMouse.a。因為到時候別人在使用.a時,
    必須依據編譯的平台選擇合適的.a。



7. 在新的專案使用libCuteMouse.a

    (1) 將libCuteMouse.a加入專案

    (2) 將libCuteMouse.a的header檔和圖檔加入專案。若沒有加入header檔,compile時會無法認得。

 



2012年3月3日 星期六

半遮面的百吻巴黎

感謝勇敢實現夢想的百吻巴黎楊雅晴提供照片,
http://www.wretch.cc/blog/angelduck777
今天彼得潘將以美麗的kiss來解答讀者的問題。


問題:

讀者A做了一個採用tab bar的App,
並且利用Supported Device Orientations設定App只支援Landscape (水平方向)


於Storyboard看到的view已經變為landscape,



但App真正執行時卻還是Portrait (直立方向),
造成原本水平的圖片被檔住一半,
關鍵的kiss被切掉了!




解答:

畫面要能變為Landscape還需搭配掌控畫面的view controller。
單單依靠內建的UIViewController是成不了氣候的。
因此彼得潘另外定義繼承自UIViewController的TestViewController來控制畫面,
然後再定義以下method來控制方向。


- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return   UIInterfaceOrientationIsLandscape(interfaceOrientation);
}

利用UIInterfaceOrientationIsLandscape判斷方向是否為Landscape,
只有Landscape才回傳YES。
如此即可讓App完美支援Landscape,
一刀未剪地呈現浪漫Paris下發生的Kiss!