2011年3月29日 星期二

淺嘗 delegate



delegate  若對C語言比較熟,其目的有點像是 function pointer。
在 C語言寫作時,我們為了要撰寫 像是 
1.  call back function,亦即執行某個程式,而在程式結束之後,自動返回。
2. 在compile期間,尚不知道會給哪個 function進行。




參考developer.apple.com的說明
Delegation is a simple and powerful pattern in which one object in a program acts on behalf of, or in coordination with, another object.The delegating object keeps a reference to the other object—the delegate—and at the appropriate time sends a message to it. The message informs the delegate of an event that the delegating object is about to handle or has just handled. The delegate may respond to the message by updating the appearance or state of itself or other objects in the application, and in some cases it can return a value that affects how an impending event is handled. The main value of delegation is that it allows you to easily customize the behavior of several objects in one central object.
換言之,這就像是 我知道 要完成一個任務,需要a技能,而 "小寶" 他有a技能,那麼我就delegate給小寶,並在需要的時候,委由小寶幫我執行。


因此像底下的例子  HelloAppDelegate 有<UIApplicationDelegate>
HelloAppDelegate 就需要處理 applicationDidFinishLaunching、applicationWillTerminate、applicationDidReceiveMemoryWarning....等。





物件中 has a的關係在大部份的Design Pattern書籍中,將之說成Delegate(委派)。
設計類別時,在一般情況下應儘量使用委派(delegate)而少用繼承。
以委派取代繼承的時機:某個subclass只使用super classes 介面中的一部份,或是根本沒用到繼承而來的資料。
以繼承取代委派的時機:當在二個classes中使用delegate,並經常為二個classes間寫作許多簡單的delegate function。











(資料來源: http://blog.joomla.org.tw/iphone-ipad/112-delegate-controller1.html )
這一陣子學了不少的應用和實作許多相關的開發學習範例。最近最有疑問的是有關於Delegate(委託)和Controller(控制者)的相關性,這兩個看起來似乎很像,但又有些不同。找了不少相關的資料之後,大致上有了一些結論,把它整理到這裡。


Delegate實際上也是一種Design Pattern(設計模式),在官方的文件中,有很清楚的說明這個的運作過程:
The delegating object is typically a framework object, and the delegate is typically a custom controller object. The delegating object holds a weak reference to its delegate.
"進行委託的"物件(稱為host object)基本上是一個框架物件,而"委託代表"是基本上是一個自訂的控制者物件。進行委託的物件維繫一個弱的參考到它的代表。

在上述文件的例子中,使用者在視窗上點下關閉的按鈕,視窗會送出一個訊息給委託代表,由委託代表負責回應是不是可以關閉這個視窗。這是一個最簡單的委託的例子。

文件在接下來的說明又談到另一個設計模式,稱為Observer(觀察者)模式,委託和notification(通知)之間的關係在於,委託代表在Cocoa中會自動成為訊息的觀察者,訊息會在事件發生之後產生,用廣播的方式通知所有的觀察者,這是這個模式的主要實作的用途。

至於最後一項稱為data source(資料源),字義上看起來似乎是MVC中的Model部份,實際並不是,它也是一種委託代表,和上述的委託代表不同處,在於委託它的物件,從上述的UI(使用者操作介面),換成了資料。

委託在實作的部份,都是透過protocol(協定)的方式,Objective-C的protocol的行為類似Java中interface。在Cocoa中,可以在NSApplication, UIApplication, UITableView, 和NSView的子類別中看到委託的設計。以下是有關於iPhone OS的委託說明:
The application delegate is extremely important in an application running on iPhone OS, as it must respond to application-launch, application-quit, low-memory, and other messages from the application object. The application delegate must adopt the UIApplicationDelegate protocol.
在iPhone OS上執行的應用程式中應用程式委託是非常重要的,因為它需要回應程式的開始執行、程式關閉、低記憶體及其他從程式物件中發出的訊息。應用程式委託需要採用UIApplicationDelegate協定。

當然目前我所接觸到的,最常見的只有這個UIApplicationDelegate,在每個iPhone的應用程式都可以看到一個委託的檔案,例如在最基本的Hello範例中:


HelloAppDelegate.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#import <UIKit/UIKit.h>
 
@class HelloViewController;
 
//START:code.HelloAppDelegate.interface
@interface HelloAppDelegate : NSObject <UIApplicationDelegate> {
 IBOutlet UIWindow *window;
 IBOutlet HelloViewController *viewController;
}
 
@property (nonatomic, retain) UIWindow *window;
@property (nonatomic, retain) HelloViewController *viewController;
 
@end


第6行就有宣告要使用UIApplicationDelegate協定。在這個委託中可以實作的方法又有那些?對照上述的官方敘述,有以下的方法可以應用(只是大概列出一些,詳情請參考上面連結):
  • applicationDidFinishLaunching:」程式啟動完成後通知,這裡通常會加入應用程式的初始化的工作
  • applicationWillTerminate:」程式結束前通知,結束前應作好重要設定或資料的儲存,例如遊戲應儲存目前的狀態,下次才能從這個狀態再繼續。
  • applicationDidReceiveMemoryWarning:」程式收到系統通知記憶體警告,如果收到警告後不釋放足夠的記憶體,系統將會強制中止程式。(註:之類後會談到UIViewController中的didReceiveMemoryWarning方法,類似功用 )
  • applicationWillResignActive:」程式將進入無效狀態通知,系統收到郵件或來電時、iPhone上鎖的通知,程式委託將不再接受任何的互動操作。程式要在此作一些暫時停止運作的工作。
  • applicationDidBecomeActive:」程式將回復原本的有效狀態,並繼續原來的工作。

委託在許屬控制元件中很常見,例如在使用UIWebView、UIPickerView、UITableView、UITextField這些控制元件時,也有自己對應的UIWebViewDelegateUIPickerViewDelegateUITableViewDelegateUITextFieldDelegate協定,那倒底有那些控製元件有對應的委託協定?這份表中的Protocol References列出了所有UIKit系列的委託和資料源協定。

總結一下委託的機制用法,委託即是會自動收到在某些應用程式事件發生時的通知,在這些事件發生時的前或後,可以讓你作一些工作。

上一篇談到有關於Delegate的概念,那Delegate和Controller又有什麼關係?先了解所謂的MVC設計模式,就可以很清楚的了解Controller的意義是什麼了,以下是一張來自官方文件Controller object的解說圖片:

image: Art/controller_object.jpg

有關於Controller(控制器)的說明我把它摘錄在下面:
A controller object acts as a coordinator or as an intermediary between one or more view objects and one or more model objects. In the Model-View-Controller design pattern, a controller object (or, simply, a controller) interprets user actions and intentions made in view objects-such as when the user taps or clicks a button or enters text in a text field-and communicates new or changed data to the model objects.
控制器物件扮演一個或多個的view物件和一個或多個的model物件的的協調者或是媒介。在Model-View-Controller設計模式中,一個控制器元件翻譯了使用者對view物件的動作和意圖,例如使用者觸碰或按下按鈕,或是在文字欄位中輸入文字,會傳送新的或更動的資料到model物件。

在這篇文件中,雖然區分出了三種控制者物件,但特別有指出在iPhone OS中,View Controllers(視圖控制器)就是扮演Coordinating Controllers(協調控制器)的角色,協調控制器的功能如下:

  • Responding to delegation messages and observing notifications
    負責委託訊息和觀察通知
  • Responding to action messages (which are are sent by controls such as buttons when users tap or click them)
    負責動作訊息
  • Establishing connections between objects and performing other setup tasks, such as when the application launches
    建立物件間的連結,和執行其他設定的工作,例如程式開發執行的工作
  • Managing the life cycle of “owned” objects
    管理擁有物件的生命週期

而視圖控制器的其他說明如下(這段有點長 @@"我去掉了一些):
A view controller manages a full-screen view, which it keeps a reference to and may create or load from a nib file. The controller manages the presentation of this view and the next view ...The navigation bar and the tab bar, and all their associated presentation behavior, are managed and implemented by view controller objects. View controllers can also display modal views, respond to low-memory warnings, and rotate views when the orientation changes.
一個視圖控制器管理並維繫了一個參考到由nib檔案所建立或載入的一個全螢幕的視圖。控制器管理這個視圖呈現方式,以及下一個在使用者介面中要呈現的首要視圖。導覽列和分頁列,以及所有相關的呈現行為,都被視圖控制物件管理和實現。視圖控制器也可以顯示獨佔的視圖、回應低記憶體警告,以及當方向改變時旋轉視圖。

A view controller is an instance of a subclass of UIViewController. The UIKit provides several special-purpose subclasses of UIViewController, such as UITableViewController.... View controllers are typically the delegate or data source objects for many types of framework objects.
視圖控制器是一個UIViewController子類別的實體。UIKit提供了一些針對特別需求的UIViewController子類別,像是UITableViewController。視圖控制器基本上是針對於許多框架物件的委託或資料源物件。

透過理解控制器的功能之後,先看一下最常接觸到的UIViewController中的可用方法有那些:
  • 「initWithNibName: bundle:」載入nib檔案來初始化
  • 「loadView」載入視圖
  • 「viewDidLoad」在載入視圖至記憶體後會呼叫的方法
  • 「viewDidUnload」在視圖從記憶體中釋放後會呼叫的方法
  • 「viewWillAppear」當收到視圖在視窗將可見時的通知會呼叫的方法
  • 「viewWillDisappear」當收到視圖在視窗將不可見時的通知會呼叫的方法
  • 「viewDidAppear」當收到視圖已加入到視窗時的通知會呼叫的方法
  • 「viewDidDisappear」當收到視圖已去除、被覆蓋或隱藏於視窗時的通知會呼叫的方法
  • 「didReceiveMemoryWarning」收到系統傳來的記憶體警告通知後會執行的方法
  • 「shouldAutorotateToInterfaceOrientation」是否支援不同方向的旋轉視圖
  • 「willAnimateRotationToInterfaceOrientation」在進行旋轉視圖前的會執行的方法(用於調整旋轉視圖之用)

這些只有列出常見的,詳細的方法可以在這個文件中找到。看到了嗎?這些收到訊息後或前執行的方法,都和視圖有關,可以說視圖控制器主要是用來管理和控制視圖的。執行熟悉了UIViewController之後,剩下的像繼承自這個類別的子類別有三大個:有UITableViewControllerUITabBarControllerUINavigationController如果能熟悉各自的應用方法,大致上Controller部份就沒問題了。

最後要談到最前面的問題:那Delegate和Controller又有什麼關係?有何不同,我在stackoverflow找到覺得比較好的說明
A delegate is a protocol (interface) that defines methods that an object implements in order to receive specific messages from other objects. Delegates objects are most often used to receive asynchronous callbacks such as user input, I/O.
委記是一個協定(介面),定義了許多物件可以實作的方法,為了接收來自其他物件的特定訊息。委託物件經常使用於接收非同步的回應呼叫,例如使用者輸入或I/O。

A controller is an object that usually contains UI elements (views, controls, etc.) and data, and both receives and send messages to the various objects within it. In many cases, a controller is a delegate and can implement several delegate protocols to receive events from multiple objects.
控制器是一個物件,通常其中包含UI元素(視圖、控制器…等)和資料,以及接收和傳送兩種訊息到其中的眾多物件。在大部份時候,控制器是一個委託且可以實作各種委託協定,以便可以接收來自多個物件的事件。

了解嗎?還是有點模糊?我的理解是Controller是在於MVC設計模式中的C這個角色,扮演Model和View的居中協調者的工作。當然ViewController的工作就是針對視圖的控制器工作,管理視圖,例如在需要的時候載入它到記憶體中,不需要時在記憶體中釋放它。要記得在iPhone OS中,通常一個視圖只會有一個視圖控制器。


而Delegate/data source是另一種實作事件控制的模式,也是位於MVC中C這個位置的機制,只是因為它是利用協定而非一般的子類別繼承實體而來,變成另一類處理控制的機制。但是,這兩種並不會是衝突或只能擇一使用,在很多情況下,反而是兩種都要搭配使用才能完成所需的工作。

2011年3月25日 星期五

iPad OS 4.3 又到了更新的時候,清理磁碟

每當 iOS推出新版,一來是怕和舊版本不相容。

二來 每 次想昇級,還得先把 mac OSX 先往上昇,然後才能再安裝新版 SDK

但要安裝時,又會遇到一個問題,硬碟空間不足……

要清理磁碟,最主要是為了 要把 空間擠出來,這個時候當然是找出最大size的file,給他刪下去。

問題是,要從哪裡找到 最大 size 的file。

起先,還試著一個一個資料夾找,真的是超麻煩的。

還好後來發現一個軟體,相當好用,可以把每個資料夾都 par 出來。

讓你知道 大的檔案是哪幾個,再來考慮是不是要直接刪掉。

OmniDiskSweeper ...

http://www.omnigroup.com/products/omnidisksweeper/download/

2011年3月16日 星期三

view Controller programming on iOS

View Controller Programming Guide for iOS

這是一個 iPhone 軟體典型的畫面,在這個畫面,有一個 Tab bar 與 Navigation bar 的結合。


可以先讀

View Controller Programming Guide for iOS



從 Xcode 裡 New Project 的範本裡有 Tab Bar 與 Navigation Bar,不過裡面有提到 you should never add a tab bar controller to a navigation controller,所以要先有 Tab Bar 再加入 Navigation Bar,像這樣:


在這裡找到 Combining Tab Bar and Navigation Controllers 的範例。
另一份範例 How to embed a navigation controller inside a tab bar controller,這一份還有第二篇,講到再加入 table view controller

***

基本閱讀:
iPhone Application Programming Guide
iPhone Human Interface Guidelines
Interface Builder User Guide

延伸閱讀:
Table View Programming Guide for iPhone OS

SSH 免密碼登入

由於 使用 git ,採用 ssh 登入,但每次都需要輸入密碼 相當麻煩,因此網路上找了資料,建立public key、private key。

在自己的 MAC 機器上

打入

(1)   ssh-keygen -t rsa   產生中會詢問你是否要輸入 passphrase 以及兩把key所存放之位置。
(2) 用 scp  [key]   username@server:[位置]   ex:  scp ~/.ssh/*.pub   abc@abc.com:~/.ssh/

但需注意 在 abc.com 上面 abc的家目錄,需要先有 .ssh 資料夾
(3) $ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys


(4) 改權限 $ chmod 711 ~/.ssh
   $ chmod 644 ~/.ssh/authorized_keys

使用 smart git






原文請參閱
http://josephjiang.com/article/understand-ssh-key/


一、基本流程說明

1. 私密與公開金鑰

以 SSH 登入任何主機都必需要打帳號、密碼,除了不方便、另外還增加了被竊取的風險(有些軟體如 winscp 是可儲存的)。
解決的方式就是使用金鑰產生器來產生一筆公開金鑰(Public Key)與私密金鑰(Private Key)對應做免密碼的登入。
使用者只需將公開金鑰的內容附加系統上特定的檔案中,以及在自己的環境指定好私密金鑰,系統在登入流程中即會自動對應,正確無誤即可登入。
讓整個登入流程快速且安全。

2. 金鑰種類

但是對應並沒有想像中這麼簡單,就像是木門上只能裝喇吧鎖而無法裝大鎖,不同的主機所能使用的金鑰機制也有所不同
SSH 有 Protocol 1 及 Protocol 2 兩種,常見金鑰編碼機制則有 RSA1、RSA2、以及 DSA 等三種。

3. 保護金鑰的措施

而另外一個問題,如果有人拿到了你的私密金鑰,就相當於他可以在你的主機為所欲為。
保護的措施就是使用 Passphrase(也可以不設)、私密金鑰的密碼,每次要用時就得輸入。

4. Agent 機制

有 Passphrase 保護當然是安全多了,但原本想用金鑰的好處就是可以省去每次打密碼的步驟,
現在若每次又得打 Passphrase,這樣的好處就沒有了,可能還得多記一套密碼、增加打錯的可能性。
還好有 Agent 機制,他相當是你的管家、我們只要把鑰匙及 Passphrase 請他保管,在登入主機時他就會幫你解決輸入 Passphrase 的問題

二、一步一步教到會

以下就只針對 Mac OSX 及 *nix 系統做介紹(若你是使用 Windows 中的 PuTTY,請先做完步驟一與二,再看這裡):

步驟 1. 產生金鑰

在 Command Line 中你可以使用 ssh-keygen 來產生各種類的金鑰,而我也會鼓勵大家一次把三種金鑰產生好,省得碰到不同系統麻煩。

a. 產生 RSA 1 金鑰

這種金鑰是給比較舊的系統,例如 FreeBSD 4 及以前的版本、是走 SSH Protocol 1 的,最好就使用 RSA 1 這種金鑰
ssh-keygen -t rsa1
Generating RSA keys: Key generation complete.
Enter file in which to save the key ($HOME/.ssh/identity): [按 Enter 使用預設值(建議)]
Enter passphrase: 輸入你的 Passphrase [建議要使用 passphrase,最少 9 碼]
Enter same passphrase again: 再一次輸入你的 Passphrase
Your identification has been saved in /home/username/.ssh/identity.
Your public key has been saved in /home/username/.ssh/identity.pub.
The key fingerprint is: 6c:96:8c:a8:86:1b:3b:eb:1b:48:8d:3d:8d:c1:4f:dc username@abc.com

b. 產生 RSA 2 金鑰

比較新的系統,如 FreeBSD 5 及之後版本或 Linux,用 RSA 2 或 DSA 這兩種金鑰
ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/username/.ssh/id_rsa): [按 Enter 使用預設值(建議)]
Enter passphrase: 輸入你的 Passphrase
Enter same passphrase again: 再一次輸入你的 Passphrase
Your identification has been saved in /home/username/.ssh/id_rsa.
Your public key has been saved in /home/username/.ssh/id_rsa.pub.
The key fingerprint is: cc:e8:a9:da:a3:41:c6:a9:97:52:59:ef:0c:cf:45:b6 username@abc.com

c. 產生 DSA 金鑰

ssh-keygen -t dsa
Generating public/private dsa key pair.
Enter file in which to save the key (/home/username/.ssh/id_dsa): [按 Enter 使用預設值(建議)]
Enter passphrase: 輸入你的 Passphrase
Enter same passphrase again: 再一次輸入你的 Passphrase
Your identification has been saved in /home/username/.ssh/id_dsa.
Your public key has been saved in /home/username/.ssh/id_dsa.pub.
The key fingerprint is: cc:e8:a9:da:a3:41:c6:a9:97:52:59:ef:0c:cf:45:b6 username@abc.com
經過這樣的程序,我們總共會有公私鑰共三對:RSA1 ( identity.pub / identity )、RSA2 ( id_rsa.pub / id_rsa )、及 ( id_dsa.pub / id_rsa )。
我過去有一個錯誤的觀念,以為金鑰是對應系統的,所以在對每一台主機得另外產生一次。
事實上如果沒有特殊需求,你可以只用一份、用任一系統產生、並把這一份給保存好即可。希望大家不要跟我有一樣的錯誤囉!

步驟 2. 將公開金鑰放到主機

你現在在自己的機器上已經有了三對金鑰,接下來我們要把公開的三隻 (*.pub) 放到我們要登入的主機上。
$ scp ~/.ssh/*.pub 你欲登入的主機:~/.ssh/.
接著登入該系統,在沒設定好之前當然還是得乖乖打密碼
$ ssh 你欲登入的主機
系統預設處理放置公鑰的檔案叫做 authorized_keys,所以我們要把剛剛所傳的公鑰附加到這個檔案中:
$ cat ~/.ssh/identity.pub >> ~/.ssh/authorized_keys
$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
$ cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
$ chmod 711 ~/.ssh
$ chmod 644 ~/.ssh/authorized_keys
如果沒有意外,你登出再登入主機,就會看到它請你輸入 Passphrase 的訊息。

步驟 3. 設定 ssh-agent

前面所提到,每次都要打 Passphrase 就太麻煩了,所以這裡要設定管家 ssh-agent、以保管私鑰及 Passphrase。
在你每次啟動 shell 後,請照這樣的方式來做:

a. 啟動 ssh-agent

$ eval `ssh-agent -s`

b. 將私密金鑰交給 ssh-agent 保管:ssh-add

我們將要用 ssh-add 來指定金鑰,如果你都照上面放預設的位置及相同的檔名,那就不用有任何的參數。
$ ssh-add
接著會要求你設定輸入 passphrase,如果三個都一樣,就只要打一次。
Enter passphrase for /home/username/.ssh/id_rsa:你的 Passphrase
Identity added: /home/username/.ssh/id_rsa (/home/username/.ssh/id_rsa)
Identity added: /home/username/.ssh/id_dsa (/home/username/.ssh/id_dsa)
Identity added: /home/username/.ssh/identity (username@username.com)
接著再試看看登入已經放好公鑰的主機,應該就可以不用密碼登入了!

c. 自動化流程

如果每次進 Shell 都要做 a、b 動作,可能還是太麻煩且忘記,也因此我去找了可以放在 .bash_profile 的 script ( Joseph M. Reagle Jr ),
一進入 Shell 就會把該做的動作做好,且詢問你 Passphrase:SH_ENV="$HOME/.ssh/environment"

function start_agent {
echo "Initialising new SSH agent..."
/usr/bin/ssh-agent | sed 's/^echo/#echo/' > "${SSH_ENV}"
echo succeeded
chmod 600 "${SSH_ENV}"
. "${SSH_ENV}" > /dev/lull
/usr/bin/ssh-add;
}

# Source SSH settings, if applicable

if [ -f "${SSH_ENV}" ]; then
. "${SSH_ENV}" > /dev/null
#ps ${SSH_AGENT_PID} doesn’t work under cywgin
ps -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {
start_agent;
}
else
start_agent;
fi

三、公私鑰所需放的機器

我的歸納是,在本機上你必需一直保有這兩份以便後續的再製。而公鑰整理成 authorized_keys,以後有新機器需要登入時一律傳此檔案上去做附加
而除了本機外,那些機器需要放私鑰呢?我的情況是最常用的那台開發機,因為你可能會利用他去 SSH 其它台機器。不然的話,應該減少私鑰的存放地點,以求安全

2011年3月7日 星期一

apple 動畫功能 ...程式碼範例

Apple 提供了流暢的動畫功能給各位開發者,差不多每一個 App 都會用到的動畫功能,無需複雜的程式碼便可以輕鬆使用到。
在這裡簡單介紹一下。

使用以下的程式碼便可以制作出動畫效果。
UIViewAnimationTransition transition = UIViewAnimationTransitionCurlUp;
UIViewAnimationCurve curve = UIViewAnimationCurveEaseInOut;
[UIView beginAnimations:@"anim" context:NULL];
[UIView setAnimationCurve:curve];
[UIView setAnimationTransition:transition forView:[self view] cache:YES];
[UIView setAnimationDuration:1.0f];
[UIView commitAnimations];

現在雖然有動畫效果,但頁面還是沒有改變,例如要新增一個黑色的頁面。
以下程式碼要加到動畫程式碼之前。
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
[view setBackgroundColor:[UIColor blackColor]];
[self.view addSubview:view];

完整轉頁效果:
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
[view setBackgroundColor:[UIColor blackColor]];
[self.view addSubview:view];

UIViewAnimationTransition transition = UIViewAnimationTransitionCurlUp;
UIViewAnimationCurve curve = UIViewAnimationCurveEaseInOut;
[UIView beginAnimations:@"anim" context:NULL];
[UIView setAnimationCurve:curve];
[UIView setAnimationTransition:transition forView:[self view] cache:YES];
[UIView setAnimationDuration:1.0f];
[UIView commitAnimations];
[view release];

是否很簡單其實 Apple 已經提供了四動晝效果和四種速度變化。

向上翻頁的效果:
//Curl Up
UIViewAnimationTransition transition = UIViewAnimationTransitionCurlUp;

向下翻頁的效果:
//Curl Down
UIViewAnimationTransition transition = UIViewAnimationTransitionCurlDown;

由左向右旋轉的效果:
//Flip From Left
UIViewAnimationTransition transition = UIViewAnimationTransitionFlipFromLeft;

由右向左旋轉的效果:
//Flip From Right
UIViewAnimationTransition transition = UIViewAnimationTransitionFlipFromRight;

開始時慢慢加速,結束前慢慢減速:
UIViewAnimationCurve curve = UIViewAnimationCurveEaseInOut;

開始時慢慢加速:
UIViewAnimationCurve curve = UIViewAnimationCurveEaseIn;

結束前慢慢減速:
UIViewAnimationCurve curve = UIViewAnimationCurveEaseOut;

開始到尾也是均速:
UIViewAnimationCurve curve = UIViewAnimationCurveLinear;

大家可以試試那一個效果最適合你的 App

2011年3月1日 星期二

UML -- 使用範例

相當不錯,且完整的一個小小 UML 使用範例

請直接連至 網頁  http://www.csie.nctu.edu.tw/~skyang/umlsamples.htm  觀看

( 為免以後看不到,因此貼於此處,但相關權利屬原作者所有!)

一般的遊戲或虛擬實境軟體把描繪好的 3D 畫面呈現在電腦螢幕上, 但一些環場模擬需要呈現多視角的多重顯示,例如賽車模擬可能需要前後左右四個顯示幕, 來表現四個車窗看到的景物,這個時候就需要用到多重顯示(multi-display)系統。 話說到這裡只是個願景(vision),接下來實際演練如何使用 UML 規劃出這樣的一個軟體系統。

第一步、需求分析

所有軟體工程最關鍵的第一步就是需求分析,同時也根據這些需求進行技術可行性分析, 以一個多重顯示系統來講,目的當然是能夠多面同步顯示 3D 場景,此外, 根據應用場合列出以下的需求項目(requirement)。

PURPOSE (需求分析)

  • 目標:多面同步顯示3D場景
  • 需求:
    1. 多面顯示須保證逐畫面同步,否則立體效果(stereo)會失敗。
    2. 多面可顯示不同視角 (viewport)。
    3. 可更換自訂節目,負責描繪各面顯示幕的電腦不需要人為的重新啟動。
    4. 與現有描繪引擎整合,減低應用程式開發負擔。

技術分析

  1. 最直觀的多重顯示系統架構就是主從架構(master/slave), 有一部 master 端的電腦負責模擬運算, 而每一個顯示幕都由一部 slave 個人電腦負責描繪,master 端與 slave 端之間透過網路纜線直接連結。
  2. 此外,如果把所有的場景資料都由 master 端即時輸送給 slave 端, 除了增加 master 端的負擔以外, 以現今記憶體輸出入速率與網路纜線傳輸速率尚難達成,故選擇在 slave 端磁碟事先放置與 master 端相同的場景資料,執行時期載入並隨時與 master 端同步,以減低資料的傳輸量。

第二步、靜態建模

權責劃分

簡明的元件部署在日後的分工、維護、延伸、傳承上都是非常關鍵的因素, 根據需求項目,多重顯示軟體系統分為三個角色。在 slave 端放置一支描繪程式當然無庸置疑,而 master 端的軟體分割為固定的 master 端控制元件,以及可替換的 master 端應用程式, 以因應第三項需求項目:可更換自訂節目。
角色(role)責任(responsibility)
Slave端描繪程式接受同步訊息描繪3D場景
Master 端控制元件發出視角設定與同步訊號
Master端應用程式進行節目流程

部署圖(Depolyment Diagram)

從系統的觀點來看,多重顯示系統是一台 master 主控電腦連接多部 slave 描繪電腦,每一部 slave 電腦可能連接一部投影機,單一組顯示幕的部署圖如下圖, 明確地標示出 slave 端是被 master 端同步的畫面訊號來源。

元件圖(Component Diagram)

元件圖比部署圖更細節地描述各個節點的構成元素,其中 master 端的應用程式是個主動類別,持有控制元件的 dll handle 和主要的 camera 設定, 而 master 端的控制元件根據應用程式的主要 camera 產生各面顯示幕的 camera 設定, slave 端的描繪程式也是個主動類別,持有場景資料,根據接收而得的 camera 設定和同步訊號描繪畫面。

類別圖(Class Diagram)

最細節的類別圖出爐,就可以開始寫程式了,為了需求項目第四項:與現有描繪引擎整合, 所以 master 端的控制元件類別 RACaveRenderer 衍生自描繪引擎的場景描繪類別 RAGraphRenderer,如下圖所示,這個類別儲存主要 camera 設定,持有各 slave 的設定(configuration)和上下傳連線。它的操作有啟用(enable)多重顯示、 描繪畫面(render)、停用(disable)多重顯示。
附註:工研院亦專門為此目的開發了 2D/3D 多重顯示系統, 尚且加入了許多加速與模組擴充功能,其軟體架構不只如本文所描述的這麼單純。

第三步、動態建模

合作圖(Collaboration Diagram)

到此已規劃了多重顯示系統中的各個角色,以及它們不同細節程度的架構描述和權責劃分, 接下來要描述他們是如何動作的。在下圖方格中為各結構體產生的物件實體命名以利分辨, 也可以不命名(例如圖中的應用程式)。沿著圖中訊息的序號,很明白地能夠了解到, 當應用程式呼叫了控制元件 r 的 Render(),控制元件 r 先對 slave 端 s 傳送更新端場景的資料,然後對 s 下達描繪指令。s 描繪完成以後回覆 acknowledgement,然後 r 對 s 下達換畫面的指令、完成一次描繪流程。

順序圖(Sequence Diagram)

在合作圖當中可以描述這三個物件實體的訊息交流, 但是無法描述它們動態生成的因果關係,下面的順序圖把這三個實體橫向排開, 在縱向的時間軸上標註他們的生命週期, 並在時間軸上呈現訊息產生的時間而不只是序號而已。由圖上可以看到, Slave 端描繪程式 s 是先啟動的,接著應用程式啟動了,並由應用程式喚醒控制元件 r, 然後連線、載入場景、描繪畫面。而停用多重顯示的時候,首先 r 與 s 斷線, 然後 r 消滅了、應用程式中止,描繪程式 s 繼續等待著與下一個應用程式連線。

狀態圖(State-Chart Diagram)

把 slave 端的描繪程式下圖分成三個狀態來舉例,收到來自 master 端控制元件的不同訊息,導致它在這三個狀態間跳躍,其實這就是很單純的有限狀態機 (finite state machine)描述法,不需贅述。此外,活動圖(activity diagram)就是眾人皆知的流程圖(flow chart),在此也不再舉例。
五、以 UML 為基礎的軟體開發流程
UML 圖形和軟體工程之間的關係,就像藍圖和建設工程之間的關係, 把工程粗略地分成設計、實作、驗證三個階段, 這三個階段可能承辦者都是彼此不相識的不同人員, 如下圖,在設計階段產出 UML 圖形以後,負責實作的人便按圖施工, 如果在實作當中發現問題,便回到 UML 圖形上檢討原設計, 更正圖形之後再繼續按圖施工。而實作完成以後,品質管制人員依照 UML 圖形所描述的架構規格和行為,驗證實作是否正確。 在這設計、實作、到驗證完成的期間就算有人員替換,也不會有問題。
懂 UML 圖例不等於會畫 UML 圖,就像不是每個會用 PowerPoint 的人都能做出陳述清晰明確的投影片。UML 不是萬靈丹, 先天不佳的設計或不健康的軟體工程流程,並不會因為使用了 UML 就變良好,最關鍵的仍是從團隊領導者到所有組員對軟體工程的共識, 並一再琢磨自身的塑模觀念與技巧。
在畫 UML 圖的時候,不要老想要把所有的東西塞在同一張圖面上,以免模糊焦點, 寧願分門別類、提綱挈領地多分成幾張圖,這時候善用子系統(或套件)圖示就很重要了。 有許多繪製 UML 圖形的商用軟體兼有管理甚至產生原始程式碼的功能, 筆者奉勸一句:那些功能可以使用但是不能依賴, 程式碼的穩健化和最佳化基本功還是要練習的, 原始程式碼就算是半自動產生的,還是要一行一行自己看過才能校調到最佳狀況。

uikit overview and send email

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/Art/uikit_classes.jpg

detect touch event on imageview
http://stackoverflow.com/questions/855095/how-can-i-detect-the-touch-event-of-an-uiimageview

openurl to send email from APP

http://www.icodeblog.com/2009/02/20/iphone-programming-tutorial-using-openurl-to-send-email-from-your-app/

with attachement
http://howtomakeiphoneapps.com/2009/07/how-to-make-your-iphone-app-send-email-with-attachments/