2010年3月18日 星期四

iPhone 開發教學 - 環境設置和第一支程式 Hello World 範例

此範例參考 Stanford CS 193P iPhone
Application Development
教學課程 Lecture #4 - Anatomy of an App, MVC, Nib files, Controls
& Target-Action

之影片,剛好解除我大半疑惑,因此想寫一下來當作筆記,也幫需要的人解惑。主因是看了很多教學,都沒有提到怎樣設定 Interface Builder 上的物件跟程式的結合,所以我才打算寫一篇來記錄一下,過程中若不知道要按熱鍵,那就會一直卡在那邊 orz


這次我第一次學 iPhone 的開發,原先看了很多 Objective C ,但一切入 Xcode 時,被他冗長的程式碼搞混,感覺看得懂每一小段的程式碼,但就不清楚真正的程式流程,我在 iPhone SDK開發範例大全第一章 看到用 debug 的方式來 trace 程式流程,一種不錯的學習方式,只是我還不太習慣 XD 但這篇的確是不錯的教學。關於我的背景,學過一點點 C++ ,但偏向於 C 語法而已,而後又學了 Java ,但都趨向於自修的模式甚至只是亂翻網路上的資料,算是沒有很正統的學習,因此我自己的筆記可能不適合其他人。


Xcode


關於 iPhone 開發環境,建議還是使用 Mac OS ,除此之外還需要學習 Objective C 的語法,以下先筆記簡單的開發環境的設置:



  1. 首先需要 Mac OS 環境,在此不多贅述

  2. 下載 iPhone SDK ,可在 Apple Developer 網站之 iPhone Dev Center 下載

    • 需要登入註冊一個 Apple ID ,請點選右上角的 Register ,若過去你已經有用 iTunes store 或是 App Store 的經驗,那應該就已經有一組帳號可以用,但在這邊申請的 Apple ID 是不需要信用卡資訊的,若你要使用 iTunes store 的話,又不想用信用卡,請逛逛 Google:apple id 免信用卡,的此原理是利用在 iTunes store 下載免費的東西時,當下註冊一個新的帳號,該帳號的信用卡選項中會有 none 可以選擇

    • 登入後,請依自己的作業系統狀態下載版本,在此使用 iphone_sdk_3.1.3_with_xcode_3.2.1__snow_leopard__10m2003a.dmg ,該檔案約 3.03 GB ,下載完就可以安裝他,安裝完後即可在 Macintosh HD/Developer/Applications/Xcode 開啟




關於 iPhone 開發上的文件,可參考此:



關於 Objective C 的學習資料,可參考此:



若你覺得看上面那種東湊西併的方式很累,那就直接開大絕了!請看看史丹佛的課程:Stanford
CS 193P iPhone
Application Development
!對我的學習也解除不少疑惑,最重要的是影片中的 demo 囉!投影片用看的可以很快的,但重點反而是不會用 Xcode 或 Interface Builder,起初我一直想要脫離 Mac OS 或 Xcode 的開發環境,直到我看 Stanford 的投影片中,看到了一句話:


Don’t fight the frameworks



因此,開始調整自己的心態了!


開始進入第一支 Hello World!(另外也可以用官方的 MoveMe
解壓縮後可以找 *.xcodeproj 開啟,接著就可以編譯並跑模擬器)


Create a new Xcode project > iPhone OS > Application > Window-based Application > 填寫 HelloWorld 即可


Hello World


接著看一下左上角,選一下 Simulator,只要按下 Build and Run 就會出現 iPhone 模擬器囉!但以上的範例就只是空蕩蕩的而已。以下就開始實作我心目中的 Hello World 啦!


在 HelloWorldAppDelegate.h 中 UIWindow *window; 下面增加兩行以及下面一行的函數宣告,這是用來串連等會設計的UI物件:


#import <UIKit/UIKit.h>

@interface HelloWorldAppDelegate : NSObject <UIApplicationDelegate> {
    UIWindow *window;
    IBOutlet UILabel *showLabel;
    IBOutlet UIButton *actionButton;

}

@property (nonatomic, retain) IBOutlet UIWindow *window;

- (IBAction)updateLabel;

@end


並且在 HelloWorldAppDelegate.m 多實作兩個函數:


#import "HelloWorldAppDelegate.h"

@implementation HelloWorldAppDelegate

@synthesize window;


- (void)applicationDidFinishLaunching:(UIApplication *)application {    

    // Override point for customization after application launch
    [window makeKeyAndVisible];
}

- (void)awakeFromNib {
    showLabel.text = @"Hello World!";
}

- (IBAction)updateLabel {
    static int counter = 0;
    showLabel.text = [NSString stringWithFormat: @"Value: %d" , ++counter];
}


- (void)dealloc {
    [window release];
    [super dealloc];
}

@end


以上是程式上的佈署,接下要安排 UI 上的物件了!請點選 MainWindow.xib 檔案,接著會自動開啟 Interface Builder 並在上方 Tools 叫出 Library,接著可以從 Library 裡拉出 Label 和一個 Button 到 Window 上面,也可以點一下 Label 去調整 Layout 讓字可以置中,以及把它拉寬一點。


view


接著,就是設定 UI 物件與程式的結合,點選 Hello World App Delegate 並按著 ctrl 拉他,此時會出現一條線,把它移到 Label ,就會出現 Outlets 可以選,依我們的程式碼就是選擇 showLabel ,同理處理 Button ,選擇 actionButton 囉


connect


然後,來串接 Button 事件,點選下面的 Button 後,在右邊選單可以選擇 Touch Down ,按著那個 + 號移到 Hello World App Delegate 身上,就會看到剛剛實作的 updateLabel 可以選,如此就接上事件跟程式了!記得做完要去存檔一下喔 [File]->[Save]


Touch Down event


最後,切回 Xcode 並編譯執行就會看到模擬上的呈現囉!按下 Button 就會更新 Label 上的字樣了!這就是我心目中的 Hello World 啦!iPhone Hello World


相關文章:



相關問題:



2010年3月14日 星期日

[動畫] 十二國記


來源:http://zh.wikipedia.org/wiki/十二國記


週六開始看這齣動畫,記得以前常常在電視上看到,總覺得他的背景很有中國風,但還是不知道再說甚麼,有次開始看了第一集時,沒看完我就把他關掉了。幾天前跟同事閒聊,才又回想起這部動畫。


第一次看時,我想到的是動畫夢幻遊戲,所以就把它當成夢幻遊戲之類的動畫,事實證明,我錯了。這是一齣與人性很深相關性的動畫,故事是從日本高中女生開始的,剩下的就如同 wiki 上寫的吧!


看完後,讓我想起週邊也有些人有一點像劇中人物的個性,像是覺得自己過得太辛苦、為何要來這裡等等的疑問,我記得高中有個簡端的英文詩,大意是一個人在樹林中看到兩個岔路,一條是有人走過的痕跡,另一條是雜草叢生的小路,那這時候到底要挑哪一條路走呢?要符合世人眼光的嗎?那又是真正自己想走的路嗎?


這也讓我想起日劇華麗一族:「為何不看看明天的太陽呢?」而支持我繼續走下去的正是家人,還有一些簡單的信念,那就是繼續走下去,感受悲傷難過的,享受溫馨快樂的,沒有所謂的絕對,只有相對的存在的,就像一顆雞蛋,持住的方式不是用最大也不是小到不能支撐重量的,生活需要很多的耐心跟智慧,美好的、快樂的就會呈現在眼前,但也不代表沒有痛苦的、悲傷的。
















2010年3月9日 星期二

不要輕易相信廟口上廣告效果誇張的偏方藥

記得那幾年前,隔壁鄰居發生車禍後,幾個禮拜稍稍復原後,到中部廟宇拜拜求平安。


當時碰到一對也前來拜拜的老夫妻,看著鄰居受傷未拆封的繃帶,唏噓幾句,便也分享自己的故事。說著以前身體不好,但有次碰到一位老師,教導他們怎樣練身體,像是每天透過在單槓上拉拉身體,可以處理久坐的脊髓側彎問題,抑或透過泡澡的方式改善血液循環等等的,說的讓我那鄰居好似心動,隨後拜拜完後則一起繞道過去那位老師家裡坐一坐。


鄉下的房子,看似小間,沒想到踏入後又是另一片天,有張大大的木桌,氣派氣派,老師在熱心地請大家喝高山茶,剛剛那對夫妻則越來越少話,直到後面才發現,原來老師是賣藥酒的,就是那一兩幾千的鹿茸,看著我那鄰居,還說便宜賣給他們,並且看著他們受傷的地方,提供很多健身養氣的方式,但最終還是要他們買那瓶算一算幾萬元的鹿茸酒!


老實的鄰居就這樣抱了一瓶回家,但心裡越想越奇怪,後找我聊聊,彼此討論後,才想起來以前常常有在賣假藥酒的事,也是以一對夫妻去外地拉人的情境,賣的正是鹿茸酒,漸漸地也覺得越來越多的疑點,於是鄰居在我的建議下,展開小小地退件計畫。雖然那位老師一開始並沒有收錢,還特許過陣子再給錢,但這一切仍是太多奇怪的事。最後,幸運地終於把藥酒退還了!鄰居們心中的重擔也放了下來。


有一則小故事:「有隻小鳥在天寒中受凍,這時有隻大象在牠身上大了一坨熱熱大便,讓小鳥活了過來,然而牠仍動彈不了,不久後來了隻替牠拍掉身上的大便,卻一口吃掉了牠。」


人在低潮時期,很容易接受別人的援助,但有可能如同故事中的小鳥的遭遇,看似對牠壞的,其實救了牠一命,看似對牠好的,卻要了牠的命。對於身體保健,千萬不要購買來路不明的藥品,人體是豐富的化學變化,隨便用藥很容易造成連鎖反應而引起後遺症的,還是透過專業醫生的診斷處理才是維持健康身體的不二法門囉!盡管這次事件並沒有真正造成鄰居的損失,但也上了寶貴的一課囉!


相關網站:http://pharmacists.pixnet.net/blog/
衛生署藥物資訊網:http://drug.doh.gov.tw/
衛生署食品資訊網:http://food.doh.gov.tw
台南縣藥師公會:http://www.tainan-pharmacist.org.tw/


第一次用 Mac OS 的筆記 @ Mac 10.6.2

最近手邊多了一台 Mac Mini 可以用,所以還可以用來開發 iPhone 程式!只是對 Mac 不熟的我而言,反而什麼都用不順,就多筆記一下吧,並且我只有一般的鍵盤可以用。


之後會持續慢慢補東西



  1. 切換輸入法:視窗鍵+space

  2. 快速尋找:ctrl+space

    • 有點類似 Windows 上的 視窗鍵+r ,可以接著輸入 textedit 就可以叫出文字編輯器囉



  3. 安裝 Yahoo! 奇摩輸入法

    • 因為內建的輸入法有些不順手,改用 Yahoo! 輸入法後,關於一些標點符號可以用 ctrl + 鍵盤位置 打出來,另外一提的,在 Windows 上新注音選字是直接按下,但在 mac 上則是要按 space 囉,但換成 Yahoo! 輸入法後,就可以用下鍵去選字囉



  4. 使用 Safari 瀏覽器

    • 用 firefox 時,常常搭配 ctrl 做事,例如開啟新的一頁 ctrl+t ,在 mac 上是使用 視窗鍵,如 視窗鍵+t



  5. 很多在 Windows 或 Linux 上會搭配 ctrl 做事的,如全選、複製、貼上,請用視窗鍵還替換 ctrl 鍵囉

  6. 關於作業系統版本,請從最左上角 mac logo 點進去,裡頭有"關於這台 Mac",不用再傻傻用 uname -a 啦

  7. 安裝軟體後,在右下角有個長得很像資料夾的,上頭有個 A 字樣,可以從那邊去去找,但不是所有安裝完的軟體都可以在那邊找到

  8. 在 Mac 上的 Finder 有一點點類似在 Windows 上的檔案總管,快速鍵:視窗鍵+n

  9. 切換工作視窗:ctrl+F4


2010年2月22日 星期一

Facebook API Stream.publish 與 Extended permissions 應用 - 同步發文至個人塗鴉牆

這邊所定義的發文是指,當使用者允許某個 Facebook 上的應用程式,給予它 status_update 權力後,擁有 status_update 的權限時,將使得該應用程式擁有發布資訊到使用者塗鴉牆上的權限,可以用在同步資料的處理。這些也就上許多 Facebook 應用程式所使用到的基本互動,如玩遊戲玩到一半時,因為一些事件想要發怖到使用者塗鴉牆上來提供更多互動,像等級提昇、獲得獎品、菜園裡出現大蟲子等等的訊息。


Plurk Facebook Connect
來源:http://www.plurk.com


關於權限部份,請參考 Extended permissions - Facebook Developer Wiki 頁面,上頭有詳細的權限資訊。至於要讓使用者點選允許的方式,一開始我參考了 Plurk 同步發文至 Facebook 的權限設定,才發現原來有 FB.Connect.showPermissionDialog 這東西可以使用!非常方便,例如跳出要求允許 offline_access 權限:


 FB.Connect.showPermissionDialog("offline_access", function(perms) {
   if (!perms) {
     continue_without_permission();
   } else {
     save_session();
   }
 });


然而,我預計要開發的環境,可能連 Javascript 都可能不能跑,所以,我又參考了 Authentication and Authorization for Facebook for Mobile Applications ,發現也有簡單版的純網頁方式囉。


我把它寫成簡單的程式,列出權限清單:


<?php

define( 'APP_API_KEY' , '################################' );
define( 'APP_SECRET_KEY' , '********************************' );

function get_permission_url( $permission )
{
        $params = array();
        $params['api_key'] = APP_API_KEY;
        $params['ext_perm'] = $permission;
        $params['next'] = 'The next URL to request after the user logs in to your application.';
        $params['cancel'] = 'The URL to redirect a user who cancels the dialog.';
        //$params['display'] = 'wap';
        return 'http://www.facebook.com/connect/prompt_permissions.php?' . http_build_query( $params );
}

if( !isset( $_REQUEST['auth_token'] ) )
{
        $params = array();
        $params['api_key'] = APP_API_KEY;
        $params['next'] = 'The URL to redirect a user who successfully logging in to Facebook.';
        $params['cancel'] = 'The URL to redirect a user who cancels the login.';
        $params['v'] = '1.0';

        header( 'LOCATION: http://m.facebook.com/tos.php?'. http_build_query( $params ) );
        exit;
}

$p = array( 'publish_stream' , 'read_stream' , 'email' , 'read_mailbox' , 'offline_access' , 'create_event' , 'rsvp_event' , 'sms' , 'status_update' , 'photo_upload' , 'video_upload' , 'create_note' , 'share_item' );

foreach( $p as $v )
        echo '<a href="'.get_permission_url($v).'" target="_blank">'.$v.'</a><br />';
?>


上例是以 Mobile Device 為例,如果一開使未登入時,那就導回去登入頁面,若登入完後,那就會列出一個清單,每個清單上的項目就是一個超連結,點選超連結就會看到權限的確認頁面,清單如下:


publish_stream
read_stream
email
read_mailbox
offline_access
create_event
rsvp_event
sms
status_update
photo_upload
video_upload
create_note
share_item


以上一旦該使用者允許了 status_update 後,那程式其實就擁有遠端發訊息至個人塗鴉牆的權力,因為不需要 session 資訊,取而代之的是要去紀錄使用者的 ID。


以 PHP 當作範例(post.php):


<?php

define( 'APP_API_KEY' , '################################' );
define( 'APP_SECRET_KEY' , '********************************' );

require_once 'facebook.php';
$facebook = new Facebook( APP_API_KEY , APP_SECRET_KEY );

$message = 'message';
$target_id = 'uid';
$facebook->api_client->stream_publish( $message , null , null , null , $target_id );
?>


由於可以遠端發文,所以就不需透過瀏覽器來執行啦


# php post.php


若沒有彈跳任何訊息,那就代表發文成功吧!其中上頭的 $target_id 就是使用者的數字帳號 ID ,如 "123456789000",另外,倘若是使用以下程式碼


$facebook->api_client->stream_publish( $message , null ,  null , $target_id );


會得到 'parameter uid or session key required' 的錯誤訊息


Fatal error: Uncaught exception 'FacebookRestClientException' with message 'parameter uid or session key required' in /path/facebookapi_php5_restlib.php:3065
Stack trace:
#0 /path/facebookapi_php5_restlib.php(926): FacebookRestClient->call_method('facebook.stream...', Array)
#1 /path/post.php(9): FacebookRestClient->stream_publish('message', NULL, NULL, '123456789000')
#2 {main}
  thrown in /path/facebookapi_php5_restlib.php on line 3065


如果 status_update 的權限沒有給予,那就會有 'The user hasn't authorized the application to perform this action' 錯誤訊息


Fatal error: Uncaught exception 'FacebookRestClientException' with message 'The user hasn't authorized the application to perform this action' in /path/facebookapi_php5_restlib.php:3065
Stack trace:
#0 /path/facebookapi_php5_restlib.php(926): FacebookRestClient->call_method('facebook.stream...', Array)
#1 /path/post.php(9): FacebookRestClient->stream_publish('message', NULL, NULL, NULL, '123456789000')
#2 {main}
  thrown in /home/frank/public_html/threeupaxman/facebookapi_php5_restlib.php on line 3065


最後,比較完善但連線次數會較多的程式碼:


<?php

require( 'facebook.php' );

define( 'APP_API_KEY' , '################################' );
define( 'APP_SECRET_KEY' , '********************************' );

require_once 'facebook.php';
$facebook = new Facebook( APP_API_KEY , APP_SECRET_KEY );

$message = 'message';
$target_id = 'uid';
if( $facebook->api_client->users_hasAppPermission( 'status_update' , $target_id ) )
        $facebook->api_client->stream_publish( $message , null , null , null , $target_id );
?>