UIKit簡(jiǎn)介
- 之前我們學(xué)習(xí)了如何在OS X平臺(tái)(即Mac操作系統(tǒng))編寫應(yīng)用程序闽寡。
- 接下來我們學(xué)習(xí)iOS平臺(tái)編寫應(yīng)用程序。
- Mac應(yīng)用程序使用的是AppKit框架相味,而iOS應(yīng)用程序使用的是UIKit框架拾积,它包含了所有的UI組件和構(gòu)成iOS應(yīng)用程序的資源。
iOS和OS X的不同
- iOS沒有命令行使權(quán)丰涉,所以我們無法像在OS X上一樣創(chuàng)建命令工具程序
- iOS沒有shell和控制臺(tái)
- iOS應(yīng)用程序在Mac電腦的模擬器中運(yùn)行
- iOS無法支持一些無UI界面的API
源代碼及程序鏈接:https://pan.baidu.com/s/16g1nQ0WGW9LtEIMuvs-D3Q 密碼:xkex
重新構(gòu)建CaseTool
創(chuàng)建項(xiàng)目:
-
打開Xcode,選擇iOS下的Single View App拓巧。
-
輸入工程名稱,并選擇Next一死。
-
產(chǎn)生的界面
Single View Application圖標(biāo)肛度,顧名思義就是這個(gè)程序只顯示一個(gè)視圖。這種類型的應(yīng)用程序通常非常簡(jiǎn)單投慈,用戶界面也很簡(jiǎn)單贤斜。
其它模板的介紹
- Master-Detail應(yīng)用程序:用一個(gè)導(dǎo)航控制器和一個(gè)表視圖來顯示項(xiàng)目列表以及項(xiàng)目的詳細(xì)信息。
- Game:用來創(chuàng)建打發(fā)時(shí)間的絕妙游戲逛裤。
- Page-Based:創(chuàng)建一個(gè)類似書本的應(yīng)用程序瘩绒,它擁有翻頁動(dòng)畫效果(只支持iPad)。
- Tabbed:用來創(chuàng)建多視圖應(yīng)用程序带族,就像你在iPhone上見到的底部有一個(gè)標(biāo)簽欄并且每個(gè)標(biāo)簽都與一個(gè)視圖有關(guān)聯(lián)的那種應(yīng)用程序锁荔。
- Utility應(yīng)用程序模板:擁有一個(gè)主視圖,與Single View Application中的相似蝙砌,但是還多出一個(gè)翻轉(zhuǎn)視圖阳堕。
- Empty應(yīng)用程序是一個(gè)高級(jí)選項(xiàng)跋理,如果沒有合適的模板,或是你非常了解如何構(gòu)建你的應(yīng)用程序恬总,那么可以選擇使用這個(gè)模板前普。
代碼介紹
//AppDelegate.h
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
//AppDelegate.m
#import "AppDelegate.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
// Override point for customization after application launch.
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
@end
- 我們來看一下應(yīng)用程序委托的頭文件。首先是我們的老朋友#import壹堰,因?yàn)槲覀兪褂玫氖荱IKit框架而不是AppKit框架拭卿,所以iOS界面元素都是以UI為前綴的。
- 我們還導(dǎo)入了Foundation框架贱纠,它在iOS平臺(tái)上的工作原理與在OS X上的工作原理相似峻厚。因此,像NSString這樣的類在iOS上是有效的谆焊,且使用方式與在OS X平臺(tái)上相似惠桃。
- 實(shí)現(xiàn)文件的
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
系統(tǒng)默認(rèn)提供了一個(gè)窗口對(duì)象和視圖控制器。我們也可以在其中自定義辖试。 - 如果你是自己定義的辜王,那么你的自定義代碼在窗口創(chuàng)建時(shí)便會(huì)調(diào)用,所有的應(yīng)用程序都是在主窗口內(nèi)運(yùn)行的罐孝。接下來還要?jiǎng)?chuàng)建視圖控制器誓禁。如果使用系統(tǒng)默認(rèn)的,會(huì)有創(chuàng)建好的視圖控制器文件肾档。
視圖控制器
- 之前說過,Cocoa主要使用的是MVC(Model-View-Controller)模式辫继。確實(shí)怒见,我們?cè)趹?yīng)用程序擁有一個(gè)視圖,一個(gè)控制器以及一組數(shù)據(jù)姑宽。
- 我們是從nib文件中獲取視圖的遣耍。這種方式非常便利,因?yàn)橥ㄟ^nib文件界面來設(shè)計(jì)和加載視圖要比手動(dòng)來做快得多炮车。
- 我們的類ViewController是UIViewController的子類舵变。UIViewController知道如何管理視圖,比如將其放在屏幕上瘦穆,調(diào)整大小纪隙,旋轉(zhuǎn),等等扛或。如果想要管理視圖的話绵咱,創(chuàng)建這個(gè)類的子類是非常有必要的。
- 那為什么不直接使用UIViewController類呢?因?yàn)槲覀冃枰蛞晥D添加一些內(nèi)容熙兔,而UIViewController并不知道有這些東西悲伶,所以我們需要?jiǎng)?chuàng)建它的子類并告訴子類如何處理我們新添加的內(nèi)容艾恼。
在Nib文件中添加控件
- 打開Main.storyboard,你會(huì)看到以iPhone屏幕為尺寸顯示的應(yīng)用程序視圖麸锉。你會(huì)看到钠绍,庫對(duì)象面板中顯示的內(nèi)容都是針對(duì)iOS平臺(tái)的
- 下面我們開始編輯nib文件。從右下角的對(duì)象面板中選擇一個(gè)TextField對(duì)象并將其拖動(dòng)到視圖中花沉。調(diào)整其大小以適應(yīng)屏幕寬度柳爽,調(diào)整大小時(shí)可以參考引導(dǎo)線。
- 接下來主穗,我們將一個(gè)label對(duì)象拖出并放入視圖中泻拦,然后調(diào)整其大小。
- 下一步是添加一個(gè)按鈕忽媒。在對(duì)象面板中選擇Button圖標(biāo)争拐,并將其拖動(dòng)到視圖中文本框和標(biāo)簽的下面。按鈕完成以后晦雨,調(diào)整按鈕大小使其能夠匹配文本框的寬度架曹。雙擊圓角按鈕并給它命名,我們可以叫它UpperCase闹瞧。
- 同樣的绑雄,我們繼續(xù)添加一個(gè)按鈕,并將其放在第一個(gè)按鈕的下方奥邮,調(diào)整其大小使它看上去與第一個(gè)按鈕相似万牺,并給它命名為LowerCase。
創(chuàng)建連接
- 在頭文件的@interface和@end之間的位置放開鼠標(biāo)洽腺,Xcode就會(huì)彈出這樣的窗口脚粟。
- 窗口要求你填入輸出口的名稱。不過在這之前蘸朋,請(qǐng)注意Object旁邊的文字是File's Owner核无。這是什么意思呢?其實(shí)在你加載nib文件的時(shí)候,會(huì)有一個(gè)控制器作為它的擁有者藕坯。
- 當(dāng)通過模板自動(dòng)創(chuàng)建nib文件和控制器時(shí)团南,它會(huì)讓控制器成為nib文件的擁有者。如果你需要的話炼彪,可以在nib文件中選擇File's Owner圖標(biāo)并更改它的類吐根。
1連接輸出口(IBOutlet)
- Xcode窗口的右上角有三個(gè)標(biāo)記為Editor的按鈕,點(diǎn)擊中間的按鈕辐马,就會(huì)將編輯器從中間垂直分成兩部分佑惠,這就是輔助編輯器。
- 接下來,按住Control鍵并將光標(biāo)拖動(dòng)到頭文件膜楷,出現(xiàn)“Insert Outlet or Action”提示消息再松手旭咽。松開鼠標(biāo)會(huì)彈出如上圖的一個(gè)對(duì)話框崔挖。
- 對(duì)話框第一項(xiàng)是選擇Outlet還是Action礁竞,第二項(xiàng)是Name文本框,我們輸入“textField”,并點(diǎn)擊Connect按鈕嘶朱。這樣做會(huì)在頭文件中創(chuàng)建“textField”屬性特愿。
- 接下來對(duì)標(biāo)簽(label)重復(fù)之前的連接步驟并將其命名為“resultField”仲墨。
2連接操作(IBAction)
- 現(xiàn)在,我們將代碼連接到操作揍障,這樣按下按鈕就會(huì)觸發(fā)代碼
- 按住Control鍵并拖動(dòng)鼠標(biāo)到頭文件目养,連接對(duì)話框會(huì)再次彈出。這次毒嫡,要將連接類型改成Action癌蚁。在Name文本框中輸入U(xiǎn)pperCase,并點(diǎn)擊Connect按鈕兜畸。
- 上面的操作將會(huì)在頭文件中創(chuàng)建方法的聲明努释,并會(huì)在.m文件中創(chuàng)建方法的實(shí)現(xiàn)(內(nèi)容為空)。
- 現(xiàn)在咬摇,只要單擊該按鈕伐蒂,UpperCase:消息就會(huì)如我們所想的那樣發(fā)送給ViewController。我們可以在其中UpperCase執(zhí)行任何想要的代碼肛鹏。
- 最后連接LowerCase按鈕逸邦,按住Control鍵并拖動(dòng)鼠標(biāo)到頭文件,將連接類型改成Action在扰,連接名稱設(shè)為“LowerCase”
Connection對(duì)話框中各項(xiàng)的信息
- Name(名稱):該項(xiàng)包含了我們正在創(chuàng)建的操作的名稱缕减。
- Type(類型):操作方法參數(shù)的類名稱。默認(rèn)情況下這個(gè)值是id(泛型類)健田,不過你可以將其改成發(fā)送消息給操作的任何類。在我們這個(gè)例子中佛纫,發(fā)送消息給操作的是一個(gè)UIButton類妓局。
- Event(事件):在OS X和iOS平臺(tái)之間有很大的不同,在iOS中有非常多的事件類型呈宇,都是由于觸摸界面引起的好爬。在這個(gè)例子中,我們打算使用Touch Up Inside事件甥啄。這意味著存炮,當(dāng)手指還在按鈕上時(shí)停止屏幕觸摸,便會(huì)調(diào)用按鈕的操作方法
- Arguements(參數(shù)):在OS X應(yīng)用程序中,沒有Arguements選項(xiàng)穆桂,因?yàn)樗械牟僮鞫贾挥幸粋€(gè)參數(shù)宫盔。在iOS環(huán)境下,我們有三種參數(shù)可以選擇:None享完,Sender(OS X上的默認(rèn)選項(xiàng))和Event(包含一個(gè)UIEvent參數(shù)灼芭,你可以通過它來決定應(yīng)該做什么)。我們將為操作選擇None般又。
手動(dòng)添加代碼
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (nil != self) {
NSLog(@"init: text %@/ result %@",_textField,_resultsField);
}
return self;
}
- (void)awakeFromNib{
[super awakeFromNib];
NSLog(@"awake: text %@/ result %@",_textField,_resultsField);
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
這個(gè)方法是父類的方法彼绷,因此,我們不需要去實(shí)現(xiàn)它茴迁。我們調(diào)用這個(gè)代碼以加載nib文件來訪問輸出口寄悯。- 視圖控制器會(huì)在nib文件加載和對(duì)象初始化完成后調(diào)用viewDidLoad方法。一些較早版本的iOS系統(tǒng)還會(huì)調(diào)用awakeFromNib方法堕义,不過在iOS 5中猜旬,已經(jīng)不再調(diào)用了。
主要代碼實(shí)現(xiàn)
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//更改背景
self.view.backgroundColor = [UIColor greenColor];
//初始化文本數(shù)據(jù)
[_textField setPlaceholder:@"Enter text here"];
_resultsField.text = @"Results";
}
- 我們將為viewDidLoad方法添加一些簡(jiǎn)單的實(shí)現(xiàn)胳螟。通常它們都是用來修改輸出口和設(shè)置其它UI用的昔馋,當(dāng)viewDidLoad方法調(diào)用了,你便能確定你的nib文件已經(jīng)加完畢了糖耸。我們打算使用這個(gè)方法來設(shè)置一些文本框的默認(rèn)值秘遏。
- 這段代碼設(shè)定了textField文本框的占位符,它是在用戶向文本框輸入內(nèi)容前顯示的灰色文本嘉竟。我們還要設(shè)置標(biāo)簽的默認(rèn)值邦危,以便用戶知道這里將能看到轉(zhuǎn)化后的結(jié)果。
- 在代碼的后面舍扰,你將會(huì)看到viewDidLoad方法倦蚪。視圖從視圖層級(jí)中移除后會(huì)調(diào)用這個(gè)方法。為什么要在意這些細(xì)節(jié)呢边苹?為了保護(hù)內(nèi)存不被泄露陵且。
- iOS不支持虛擬內(nèi)存。應(yīng)用程序只能使用設(shè)備中可用的內(nèi)存个束。此外如果使用了太多的內(nèi)存慕购,iOS將會(huì)強(qiáng)行退出應(yīng)用程序以示抗議。我們通過viewDidLoad方法在事后清理內(nèi)存茬底。
- 在iOS(尤其是iPhone)應(yīng)用程序中沪悲,大多數(shù)情況下,一個(gè)視圖離開后另一個(gè)視圖會(huì)來填滿屏幕阱表。這時(shí)殿如,先前的那個(gè)視圖便看不到了贡珊,因此就不需要再保留它了。
- iOS需要卸載視圖來節(jié)約內(nèi)存涉馁,所以viewDidLoad方法可以幫我們移除視圖上的各項(xiàng)內(nèi)容以節(jié)約一些內(nèi)存门岔,在這個(gè)示例中,我們移除了textField和resultsField控件谨胞。這兩個(gè)方法(viewDidLoad和viewDidUnLoad)在視圖的聲明周期內(nèi)只會(huì)調(diào)用到一次固歪。
- 還有四個(gè)方法(viewWillAppear:、viewDidAppear:胯努、viewWillDisAppear:牢裳、viewDidDisAppear:)也會(huì)在視圖離開或出現(xiàn)的時(shí)候得到調(diào)用。每當(dāng)條件合適的時(shí)候他們就會(huì)被調(diào)用叶沛,即便視圖沒有被卸載蒲讯。
//實(shí)際執(zhí)行大小寫轉(zhuǎn)化的代碼
- (IBAction)uppercase:(id)sender {
//獲取
NSString *original = _textField.text;
//改變
NSString *uppercase = [original uppercaseString];
//傳遞
_resultsField.text = uppercase;
}
- (IBAction)lowercase:(id)sender {
//獲取
NSString *original = _textField.text;
//改變
NSString *lowercase = [original lowercaseString];
//傳遞
_resultsField.text = lowercase;
}
- 對(duì)于iOS的文本框,我們使用一個(gè)NSString方法來轉(zhuǎn)換它的文本灰署,將標(biāo)簽的文本值設(shè)置為修改后的字符串判帮。就像在OS X上的那個(gè)應(yīng)用一樣,我們?cè)谶@個(gè)例子中使用了stringValue和setStringValue:方法溉箕。