2.1 增強版Hello World
2.2 MVC設計模式
2.3 Cocoa MVC
2.4 視圖控制器的方法
2.5 輸出口和動作
2.6 鍵盤輸入
2.7 使用AlertView
2.8 使用ActionSheet
2.8 等待有關控件
2.9 屏幕旋轉
2.1 增強版Hello World
實現步驟
1.創建Hello World工程
在Xcode中創建Hello World工程,基於iPhone試圖基礎應用程序。
iPhone OS ->Application ->View-based Application
2.修改Hello_WorldViewController.h
需要UITextField控件接受文字和響應一個按鈕點擊事件,所以在h文件中我們要定義一個UITextField屬性和一個響應事件方法
#import <UIKit/UIKit.h> @interface Hello_WorldViewController : UIViewController { UITextField *txtField; } @property (nonatomic, retain) IBOutlet UITextField *txtField; -(IBAction)onClickButton:(id)sender; @end
3.修改Hello_WorldViewController.m
實現txtField屬性
實現-(IBAction)onClickButton:(id)sender 方法
#import "Hello_WorldViewController.h" @implementation Hello_WorldViewController @synthesize txtField; -(IBAction)onClickButton:(id)sender { txtField.text = @"Hello World."; } - (void)viewDidUnload { self.txtField = nil; } - (void)dealloc { [txtField dealloc]; [super dealloc]; } @end
4.使用IB設計頁面,擺放控件
Resources/Hello_WorldViewController.xib文件,打開Library將控件拖入設計窗口
5.連接輸出口
為了將控件屬性通過屏幕“輸入”或“輸出”,我們需要定義“輸出口”,在控制器中我們已經定義了與這個數據對 應的屬性:
@property (nonatomic, retain) IBOutlet
UITextField *txtField;
UITextField用於展示輸出和輸入數據。在iPhone(包括Mac)開發時候控件屬性要通過定義輸出口才能在屏幕中使用 的。
6.處理事件
為了響應控件的事件,我們需要在控制器中定義一個事件處理方法:
-(IBAction)onClickButton:(id)sender;
在iPhone(包括Mac)開發控件事件處理要自己編寫對應方法,並在IB中將控件的事件與該方法連接起來。
2.2 MVC設計模式
MVC是一種設計模式,所謂設計模式就是解決某一特定問題的方案,MVC是解決具有UI的應用系統的成熟解決方案,
在Cocoa應用系統中嚴格按照該模式實現。M-Model(模型)是應用系統中與視圖對於部分的數據。V -View(視圖)是應用系統中用戶看到並與之交互的界面。C-Controller(控制器)是應用系統中起到控制器作用,接受用戶事件,顯示數據等等,與視圖進行交互等。
2.3 Cocoa MVC
采用MVC 設計模式意味着,Interface Builder 不需要編寫或生成任何代碼,您只需專注於應用程序的視圖。Mac 的Cocoa 綁定消除了大部分的黏合代碼,它就像連接在Xcode 編寫的控制器和Interface Builder 設計的視圖之間的一條線,用圖形化的表示方法簡化了二者之間的關系。Interface Builder 和Cocoa 可以快速開發地您的應用程序。
File's owner:
2.4 視圖控制器的方法
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
如果視圖使用NIB文件創建,在加載視圖之前調用這個方法,做一些初始化工作。
- (void)loadView
視圖加載的時候調用的方法一般不使用NIB文件創建視圖的時候使用,而是使用代碼創建視圖對象。
- (void)viewDidLoad
視圖加載之后調用的方法,我們常常在這個方法中做視圖初始化出來。
- (void)didReceiveMemoryWarning
當系統內存警告的時候調用的方法,我們一般在該方法釋放消耗資源的對象。
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
用於處理屏幕旋轉的方法。
- (void)viewDidUnload
視圖對象卸載的使用調用的方法,一般在把內存視圖中的屬性設置為nil值。
- (void)viewDidUnload { self.txtField = nil; }
- (void)dealloc
視圖對象內存釋放的時候調用的方法,在該方法中先要釋放掉成員變量。
- (void)dealloc { [txtField dealloc]; [super dealloc]; }
2.5 輸出口和動作
輸出口(Outlet),為了實現控制器在視圖上輸入輸出結果,需要定義輸出口。
定義輸出口,是在ViewController定義一個控件屬性,如下:
//h文件 @interface Hello_WorldViewController : UIViewController { UITextField *txtField; } @property (nonatomic, retain) IBOutlet UITextField *txtField; //m文件 @synthesize txtField;
動作(Action),為了實現視圖控制器響應視圖事件,需要定義動作。
定義動作,是在ViewController定義一個方法,如下:
//h文件 -(IBAction)onClickButton:(id)sender; //m文件 -(IBAction)onClickButton:(id)sender { txtField.text = @"Hello World."; }
動作(Action)是在控件器中的方法,但它的返回類型必須是IBAction聲明的,該關鍵字告訴IB,此方法是個Action,可以被某個事件觸發。
2.6 鍵盤輸入
在iPhone應用程序中,鍵盤輸入處理比較麻煩。在輸入完成后我們需要自己關閉鍵盤。
在iPhone中我們還可以指定鍵盤輸入類型,可以是Email、電話和數字等類型。
輸入完成關閉鍵盤:
Phone中文本框輸入后,鍵盤是不會關閉的,必須編寫代碼。
1 為關閉鍵盤添加事件處理方法:
//h file -(IBAction)textFieldDoneEditing:(id)sender; //m file -(IBAction)textFieldDoneEditing:(id)sender { [sender resignFirstResponder]; }
2 鏈接事件
文本框對象的Did End On Exit事件鏈接到File’s Owner。
3 小結
點擊鍵盤中的“換行”或“return”鍵關閉鍵盤。 第一響應者是當前與用戶交互的控件,在這個例子中,點擊TextField控件,它就變成第一響應者鍵盤就會自動出現。
[sender resignFirstResponder];
是使TextField控件放棄第一響應者狀態。
4 通過觸摸背景關閉鍵盤
點擊關閉鍵盤中的“return”關閉鍵盤比較麻煩,我們可以通過觸摸背景關閉鍵盤。
//h -(IBAction)backgroundTap:(id)sender; //m -(IBAction)backgroundTap:(id)sender { [txtField resignFirstResponder]; }
5 連接動作和事件
為了使背景控件能夠響應事件,我們需要背景View的父類(UIView)修改成為UIControl,UIControl是能夠觸發actionɼ所有控件都是UIControl的子類。而UIControl是UIView子類,也具有View基本特征。
從Touch Down事件拖到File’s Owner圖標,然后選擇backgroundTap:動作。這樣觸摸視圖中沒有活動的控件的任何位置就可以觸發backgroundTap:動作,關閉鍵盤。
6 鍵盤輸入類型
在iPhone中我們還可以指定鍵盤輸入類型,可以是Email、電話和數字等類型。
Email鍵盤 數字鍵盤 電話鍵盤
7 Return Key設定
在鍵盤輸入屬性框中我們可以定義Return Key,可以有Google等等。但是這些並沒有實際的含義,只是代表它可以觸發輸入完成事件(Did End On Exit)。
2.7 使用AlertView
修改Hello World項目代碼,添加AlertView:
修改Hello-.m代碼
-(IBAction)onClickButton:(id)sender { //txtField.text = @"Hello World."; NSString *str = [[NSString alloc] initWithFormat:@"Hello. %@", txtField.text]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Hello!" message:str delegate:self cancelButtonTitle:@"Done" otherButtonTitles:nil]; [alert show]; [alert release]; [str release]; }
2.8 使用ActionSheet
ActionSheet和AlertView比較相似都是給用戶一個提示信息。它是從底部彈出。它通常用於確認潛在的危險或不能撤消的操作,如刪除一個數據。 為了使用ActionSheet我們需要在h文件中實現UIActionSheetDelegate協議。其中,我們常常需
要實現: actionSheet:didDismissWithButtonIndex:
該方法是ActionSheet消失的時候調用。
修改Hello-.h文件
在Hello_WorldViewController.h文件中添加協議UIActionSheetDelegate:
//h #import <UIKit/UIKit.h> @interface Hello_WorldViewController : UIViewController <UIActionSheetDelegate> { UITextField *txtField; } @property (nonatomic, retain) IBOutlet UITextField *txtField; -(IBAction)onClickButton:(id)sender; @end
//m #import "Hello_WorldViewController.h" @implementation Hello_WorldViewController @synthesize txtField; -(IBAction)onClickButton:(id)sender { //txtField.text = @"Hello World."; UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"您確認清除文本框中的數據嗎?" delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:@"確定" otherButtonTitles:nil]; // NSArray *array = [[NSArray alloc] initWithObjects: // [NSString stringWithString:@"1st Button"], // [NSString stringWithString:@"2nd Button"], // [NSString stringWithString:@"3rd Button"], // [NSString stringWithString:@"4th Button"], // nil]; // // UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"Title Here" // delegate:self // cancelButtonTitle:nil // destructiveButtonTitle:nil // otherButtonTitles:nil]; // // for (int i = 0; i < 3; i++) { // // [actionSheet addButtonWithTitle:[array objectAtIndex:i]]; // // } // // [actionSheet addButtonWithTitle:@"Cancel"]; // actionSheet.cancelButtonIndex = 4; [actionSheet showInView:self.view]; [actionSheet release]; } -(void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex { if (buttonIndex == [actionSheet destructiveButtonIndex]) { txtField.text = @""; } } - (void)viewDidUnload { self.txtField = nil; } - (void)dealloc { [txtField dealloc]; [super dealloc]; } @end
2.8 等待有關控件
對於一些費時的處理,需要使用一些等待控件消除用戶心里等待的時間。
等待有關的控件有:
" UIActivityIndicatorView
" UIProgressView
UIActivityIndicatorView:
UIActivity-.h
@interface UIActivityIndicatorViewController : UIViewController { UIActivityIndicatorView * myActivityView; } @property (nonatomic, retain) IBOutlet UIActivityIndicatorView * myActivityView; -(IBAction)onClickButton: (id)sender; @end
UIActivity-.m
#import "UIActivityIndicatorViewController.h" @implementation UIActivityIndicatorViewController @synthesize myActivityView; -(IBAction)onClickButton: (id)sender { if ([myActivityView isAnimating]) { [myActivityView stopAnimating]; } else { [myActivityView startAnimating]; } } - (void)dealloc { [myActivityView release]; [super dealloc]; } @end
UIProgressView
Progress-.h
@interface ProgressViewViewController : UIViewController { IBOutlet UIProgressView *Progress; NSTimer *timer; } @property (nonatomic, retain) IBOutlet UIProgressView *Progress; @property (nonatomic, assign) NSTimer *timer; -(IBAction)start; @end
Progress-.m
@synthesize Progress; @synthesize timer; - (void)viewDidLoad { [super viewDidLoad]; } -(IBAction)start{ Progress.progress = 0.0; timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(update) userInfo:nil repeats:YES]; }
NSTimer是可以隱式地啟動一個線程,scheduledTimerWithTimeInterval指定線程要休眠多少時間調用一次,selector所指定的方法update
Progress-.m
-(void)update{ Progress.progress = Progress.progress + 0.1; if (Progress.progress == 1.0) { [timer invalidate]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"任務通知" message:@"硬盤格式化完成!" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; [alert release]; } } - (void)viewDidUnload { self.Progress = nil; } - (void)dealloc { [Progress release]; [super dealloc]; }
UIProgressView控件的progress屬性是0.0~1.0煩范圍。0.0時候在開始的位置,1.0時候是進度到了100%。
2.9 屏幕旋轉
iPhone中有重力感應我們可以通過旋轉手機使屏幕旋轉。但是屏幕旋轉后頁面的布局需要注意。
屏幕旋轉的類型
UIInterfaceOrientationPortrait,垂直向上
UIInterfaceOrientationPortraitUpsideDown,垂直倒放。
UIInterfaceOrientationLandscapeLeft,水平向左。
UIInterfaceOrientationLandscapeRight,水平向右。
注意:以手機屏幕為參照物的向左、向右。
開啟旋轉 :可以通過shouldAutorotateToInterfaceOrientation:方法開啟或禁止旋轉。
允許任何方向的旋轉:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return YES; }
垂直向上和水平向右:
- (void)willAnimateRotationToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation duration: (NSTimeInterval) duration { if (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) { } else { } }
觸發旋轉事件 :
我們可以在屏幕旋轉的時候觸發很多事件,其中willAnimateRotationToInterfaceOrientation是我們常用的事件,這個事件是在即將開始屏幕旋轉動畫的時候觸發。
- (void)willAnimateRotationToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation duration: (NSTimeInterval) duration { if (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) { txtField.text = @"垂直顯示。"; } else { txtField.text = @"水平顯示。"; } }
自動調整屏幕控件
由於屏幕旋轉后,控件的位置會發生變化,我們要讓這些控件能夠擺放相對比較合理。我們可以通過“Control Size”調整。 其中紅色實線代表絕對位置, 紅色虛線代表相對位置。
橫屏豎屏切換不同視圖
新建工程Swap
SwapViewController.h文件
#import <UIKit/UIKit.h> #define degreesToRadians(x) (M_PI * (x) / 180.0) @interface SwapViewController : UIViewController { UIView *landscape; UIView *portrait; UIButton *landscapeFooButton;//Foo UIButton *portraitFooButton; UIButton *landscapeBarButton;//Bar UIButton *portraitBarButton; } @property (nonatomic, retain) IBOutlet UIView *landscape; @property (nonatomic, retain) IBOutlet UIView *portrait; @property (nonatomic, retain) IBOutlet UIButton *landscapeFooButton; @property (nonatomic, retain) IBOutlet UIButton *portraitFooButton; @property (nonatomic, retain) IBOutlet UIButton *landscapeBarButton; @property (nonatomic, retain) IBOutlet UIButton *portraitBarButton; -(IBAction) buttonPressed:(id)sender; @end
#define degreesToRadians(X) (M_PI * (x) / 180.0)這是一個宏,用於在度數和弧度之間的轉換。
landscape水平視圖,portrait垂直視圖;
landscapeFooButton水平視圖中Foo按鈕;
portraitFooButton垂直視圖中Foo按鈕;
landscapeBarButton水平視圖中Bar按鈕;
portraitBarButton垂直視圖中Bar按鈕。
視圖設計
輸出口和事件
編寫m實現文件
#import "SwapViewController.h" @implementation SwapViewController @synthesize landscape; @synthesize portrait; @synthesize landscapeFooButton; @synthesize portraitFooButton; @synthesize landscapeBarButton; @synthesize portraitBarButton; -(IBAction) buttonPressed:(id)sender { if (sender == portraitFooButton) { NSLog(@"portraitFooButton press."); } else if (sender == landscapeFooButton) { NSLog(@"landscapeFooButton press."); } else if (sender == landscapeBarButton) { NSLog(@"landscapeBarButton press."); } else { NSLog(@"portraitBarButton press."); } } // Override to allow orientations other than the default portrait orientation. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations //return (interfaceOrientation == UIInterfaceOrientationPortrait); return YES; } -(void) willAnimateRotationToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation duration: (NSTimeInterval)duration{ if (interfaceOrientation == UIInterfaceOrientationPortrait) { self.view = self.portrait; self.view.transform = CGAffineTransformIdentity; self.view.transform = CGAffineTransformMakeRotation(degreesToRadians(0)); self.view.bounds = CGRectMake(0.0, 0.0, 320.0, 460.0); } else if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft) { self.view = self.landscape; self.view.transform = CGAffineTransformIdentity; self.view.transform = CGAffineTransformMakeRotation(degreesToRadians(-90)); self.view.bounds = CGRectMake(0.0, 0.0, 480.0, 300.0); } else if (interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) { self.view = self.portrait; self.view.transform = CGAffineTransformIdentity; self.view.transform = CGAffineTransformMakeRotation(degreesToRadians(180)); self.view.bounds = CGRectMake(0.0, 0.0, 320.0, 460.0); } else if (interfaceOrientation == UIInterfaceOrientationLandscapeRight) { self.view = self.landscape; self.view.transform = CGAffineTransformIdentity; self.view.transform = CGAffineTransformMakeRotation(degreesToRadians(90)); self.view.bounds = CGRectMake(0.0, 0.0, 480.0, 300.0); } } - (void)didReceiveMemoryWarning { // Releases the view if it doesn't have a superview. [super didReceiveMemoryWarning]; // Release any cached data, images, etc that aren't in use. } - (void)viewDidUnload { // Release any retained subviews of the main view. self.landscape = nil; self.portrait = nil; self.landscapeFooButton = nil; self.portraitFooButton = nil; self.landscapeBarButton = nil; self.portraitBarButton = nil; } - (void)dealloc { [landscape release]; [portrait release]; [landscapeFooButton release]; [portraitFooButton release]; [landscapeBarButton release]; [portraitBarButton release]; [super dealloc]; } @end
willAnimateRotationToInterfaceOrientationduration:這個方法來自我們重寫的一個父類,這個方法在旋轉開始之后與旋轉實際發生之前被調用。
CGAffineTransformIdentity,重置變換屬性。
CGAffineTransformMakeRotation來創建一個旋轉變換。
注:
1 本教程是基於關東升老師的教程
2 基於黑蘋果10.6.8和xcode4.2
3 本人初學,有什么不對的望指教
4 教程會隨着本人學習,持續更新
5 教程是本人從word筆記中拷貝出來了,所以格式請見諒