iOS 委托與文本輸入(內(nèi)容根據(jù)iOS編程編寫(xiě))
•文本框(UITextField)
本章節(jié)繼續(xù)編輯 JXHypnoNerd 。文件地址 。
首先我們繼續(xù)編輯 JXHypnosisViewController.m 修改 loadView 方法,向 view 中添加一個(gè) UITextField 對(duì)象:
#import "JXHypnosisViewController.h" #import "JXHypnosisView.h" @interface JXHypnosisViewController () @end @implementation JXHypnosisViewController - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // 設(shè)置標(biāo)簽項(xiàng)的標(biāo)題 self.tabBarItem.title = @"Hypnotize"; // 從圖片文件創(chuàng)建一個(gè) UIImage 對(duì)象 UIImage * i = [UIImage imageNamed:@"Hypno"]; // 將 UIImage 對(duì)象賦值給標(biāo)簽項(xiàng)的 iamge 屬性 self.tabBarItem.image = i; } return self; } - (void)viewDidLoad { [super viewDidLoad]; } - (void)loadView { // 創(chuàng)建一個(gè) JXHypnosisView 對(duì)象 JXHypnosisView * backgroundView = [[JXHypnosisView alloc] init]; CGRect textFieldRect = CGRectMake(40, 70, 240, 30); UITextField * textField = [[UITextField alloc] init]; textField.frame = textFieldRect; // 設(shè)置 UITextField 對(duì)象的邊框樣式,便于查看它在屏幕上的位置 textField.borderStyle = UITextBorderStyleRoundedRect; [backgroundView addSubview:textField]; // 將 JXHypnosisView 對(duì)象賦給視圖控制器的view 屬性 self.view = backgroundView; } @end
構(gòu)建并運(yùn)行應(yīng)用,項(xiàng)目中會(huì)顯示一個(gè)文本框,該文本框就是剛才我們添加的 UITextField 對(duì)象。點(diǎn)擊文本框,這時(shí)屏幕底部就會(huì)彈出鍵盤(pán),用于向文本框中輸入文字,下面我們介紹一下第一響應(yīng)者。
•UIResponder
UIResponder 是 UIKit 框架中的一個(gè)抽象類(lèi)。之前我們了解過(guò)他的幾個(gè)子類(lèi)。
1. UIView
2. UIViewController
3. UIApplication
UIResponder 定義了一系列方法,用于接收和處理用戶事件,例如 觸摸事件、運(yùn)動(dòng)事件(搖晃設(shè)備)和功能控制事件(如編輯文本或者音樂(lè)播放)等。 UIResponder 的子類(lèi)會(huì)覆蓋這些方法,實(shí)現(xiàn)自己的事件響應(yīng)代碼。
在以上事件中,觸摸事件顯然應(yīng)該由被觸摸的視圖負(fù)責(zé)處理。系統(tǒng)會(huì)將觸摸事件直接發(fā)送給被觸摸的視圖。
其他類(lèi)型的事件則會(huì)由第一響應(yīng)者負(fù)責(zé)處理,UIWindow 有一個(gè) firstResponder 屬性指向第一響應(yīng)者。例如,當(dāng)用戶點(diǎn)擊 UITextField 對(duì)象時(shí), UITextField 對(duì)象就會(huì)成為第一響應(yīng)者。UIWindow 會(huì)將 firstResponder 指向該對(duì)象,之后,如果應(yīng)用接收到運(yùn)動(dòng)事件和功能控制事件,都會(huì)發(fā)送給 UITextField 對(duì)象。
當(dāng)某個(gè) UITextField 對(duì)象或 UITextView 對(duì)象成為第一響應(yīng)者時(shí),屏幕就會(huì)彈出鍵盤(pán)。除了用戶點(diǎn)擊之外,還可以在代碼中向 UITextField 對(duì)象發(fā)送 becomeFirstResponder 消息,使其成為第一響應(yīng)者。相反,如果要關(guān)閉鍵盤(pán),則可以向 UITextField 對(duì)象發(fā)送 resignFirstResponder 消息,且要求改對(duì)象放棄第一響應(yīng)者狀態(tài)。一旦第一響應(yīng)者不是 UITextField 對(duì)象,鍵盤(pán)就會(huì)消失。
實(shí)際上,大部分視圖都不需要成為第一響應(yīng)者。例如 UISlider 對(duì)象,該對(duì)象只會(huì)處理觸摸事件(用戶拖拽滑塊),而不會(huì)接收其他類(lèi)型的事件,因此它不需要成為第一響應(yīng)者。
•設(shè)置 UITextField 的鍵盤(pán)
UITextField 對(duì)象有一系列屬性,用于設(shè)置彈出的鍵盤(pán)。下面就修改這些屬性,為 UITextField 對(duì)象添加占位符文本,并修改鍵盤(pán)的換行鍵盤(pán)類(lèi)型。
#import "JXHypnosisViewController.h" #import "JXHypnosisView.h" @interface JXHypnosisViewController () @end @implementation JXHypnosisViewController - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // 設(shè)置標(biāo)簽項(xiàng)的標(biāo)題 self.tabBarItem.title = @"Hypnotize"; // 從圖片文件創(chuàng)建一個(gè) UIImage 對(duì)象 UIImage * i = [UIImage imageNamed:@"Hypno"]; // 將 UIImage 對(duì)象賦值給標(biāo)簽項(xiàng)的 iamge 屬性 self.tabBarItem.image = i; } return self; } - (void)viewDidLoad { [super viewDidLoad]; } - (void)loadView { // 創(chuàng)建一個(gè) JXHypnosisView 對(duì)象 JXHypnosisView * backgroundView = [[JXHypnosisView alloc] init]; CGRect textFieldRect = CGRectMake(40, 70, 240, 30); UITextField * textField = [[UITextField alloc] init]; textField.frame = textFieldRect; // 設(shè)置 UITextField 對(duì)象的邊框樣式,便于查看它在屏幕上的位置 textField.borderStyle = UITextBorderStyleRoundedRect; // 修改占位符 textField.placeholder = @"Hypontize me"; // 修改鍵盤(pán)類(lèi)型 textField.returnKeyType = UIReturnKeyDone; [backgroundView addSubview:textField]; // 將 JXHypnosisView 對(duì)象賦給視圖控制器的view 屬性 self.view = backgroundView; } @end
構(gòu)建并運(yùn)行,在程序中就會(huì)發(fā)現(xiàn)有一行占位符文本 Hypontize me ,當(dāng)用戶在程序中輸入文字的時(shí)候,占位文本就會(huì)消失。換行鍵不再顯示默認(rèn)的 Return,而是 Done。
但是,如果我們點(diǎn)擊 Done 就會(huì)發(fā)現(xiàn)沒(méi)有任何反應(yīng)。實(shí)際上,修改換行鍵盤(pán)的類(lèi)型知識(shí)改變了換行鍵的外觀,如果需要實(shí)現(xiàn)用戶點(diǎn)擊換行鍵后的功能,必須實(shí)現(xiàn)編寫(xiě)響應(yīng)的代碼。在編寫(xiě)代碼之前,在介紹 UITextField 對(duì)象中另外介個(gè)有用的屬性
•委托
我們知道 目標(biāo)-動(dòng)作(Target-Action)設(shè)計(jì)模式。目標(biāo)-動(dòng)作 是 UIKit 中通常用的設(shè)計(jì)模式之一。目標(biāo)-動(dòng)作的工作方式為:當(dāng)某個(gè)特定的事件發(fā)生時(shí)(例如按下按鈕),發(fā)生事件的一方會(huì)向指定的目標(biāo)對(duì)象發(fā)送一個(gè)之前設(shè)定好的動(dòng)作消息。所有繼承 UIControl 對(duì)象都可以設(shè)置目標(biāo)-動(dòng)作。
在 目標(biāo)-動(dòng)作中,針對(duì)不同的事件,需要?jiǎng)?chuàng)建不同的動(dòng)作消息。UIButton 對(duì)象的事件比較簡(jiǎn)單,通常只需要處理點(diǎn)擊事件:相反,像 UITextField 這類(lèi)事件復(fù)雜的對(duì)象,偉大的蘋(píng)果使用了 委托設(shè)計(jì)模式 。UITextField 對(duì)象具有一個(gè)委托屬性,通過(guò)為 UITextField 對(duì)象設(shè)置委托,UITextField 對(duì)象會(huì)在發(fā)生事件時(shí)向委托發(fā)送響應(yīng)的消息,由委托處理該時(shí)間。例如,對(duì)于編輯 UITextField 對(duì)象文本內(nèi)容的事件,有對(duì)象的委托方法。
@protocol UITextFieldDelegate <NSObject> @optional - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField; // return NO to disallow editing. - (void)textFieldDidBeginEditing:(UITextField *)textField; // became first responder - (BOOL)textFieldShouldEndEditing:(UITextField *)textField; // return YES to allow editing to stop and to resign first responder status. NO to disallow the editing session to end - (void)textFieldDidEndEditing:(UITextField *)textField; // may be called if forced even if shouldEndEditing returns NO (e.g. view removed from window) or endEditing:YES called - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string; // return NO to not change text - (BOOL)textFieldShouldClear:(UITextField *)textField; // called when clear button pressed. return NO to ignore (no notifications) - (BOOL)textFieldShouldReturn:(UITextField *)textField; // called when 'return' key pressed. return NO to ignore. @end
注意:在委托方法中,通常應(yīng)該將對(duì)象自身作為第一個(gè)參數(shù)。多個(gè)對(duì)象可能具有相同的委托,當(dāng)委托收到消息的時(shí)候,需要根據(jù)該參數(shù)判斷發(fā)送該消息的對(duì)象。例如,如果某個(gè)視圖控制器中包含多個(gè) UITextField 對(duì)象,它們的委托都是該視圖控制器,那么視圖控制器就需要根據(jù) textField 參數(shù)獲取響應(yīng)的 UITextField 對(duì)象并執(zhí)行不同的操作。
下面我們就將 UITextField 對(duì)象所位于的視圖控制器- JXHypnosisViewController 設(shè)置為它的委托,并實(shí)現(xiàn) textFieldShouldReturn: 委托方法,當(dāng)用戶點(diǎn)擊 Done 按鈕時(shí),UITextField 對(duì)象就會(huì)調(diào)用該方法。
打開(kāi) JXHypnosisViewController 修改 loadView 方法,將 UITextField 對(duì)象的委托屬性設(shè)置為 JXHypnosisViewController 自身。
textFieldShouldReturn: 只有一個(gè)參數(shù),就是用戶點(diǎn)擊換行鍵的相應(yīng) UITextField 對(duì)象。目前,應(yīng)用只會(huì)向控制臺(tái)輸出 UITextField 對(duì)象的文本內(nèi)容。
接下來(lái)在代碼中實(shí)現(xiàn) textFieldShouldReturn: 方法。
#import "JXHypnosisViewController.h" #import "JXHypnosisView.h" @interface JXHypnosisViewController () @end @implementation JXHypnosisViewController - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // 設(shè)置標(biāo)簽項(xiàng)的標(biāo)題 self.tabBarItem.title = @"Hypnotize"; // 從圖片文件創(chuàng)建一個(gè) UIImage 對(duì)象 UIImage * i = [UIImage imageNamed:@"Hypno"]; // 將 UIImage 對(duì)象賦值給標(biāo)簽項(xiàng)的 iamge 屬性 self.tabBarItem.image = i; } return self; } - (void)viewDidLoad { [super viewDidLoad]; } - (void)loadView { // 創(chuàng)建一個(gè) JXHypnosisView 對(duì)象 JXHypnosisView * backgroundView = [[JXHypnosisView alloc] init]; CGRect textFieldRect = CGRectMake(40, 70, 240, 30); UITextField * textField = [[UITextField alloc] init]; textField.frame = textFieldRect; // 設(shè)置 UITextField 對(duì)象的邊框樣式,便于查看它在屏幕上的位置 textField.borderStyle = UITextBorderStyleRoundedRect; // 修改占位符 textField.placeholder = @"Hypontize me"; // 修改鍵盤(pán)類(lèi)型 textField.returnKeyType = UIReturnKeyDone; textField.delegate = self; [backgroundView addSubview:textField]; // 將 JXHypnosisView 對(duì)象賦給視圖控制器的view 屬性 self.view = backgroundView; } - (BOOL)textFieldShouldReturn:(UITextField *)textField { NSLog(@"%@",textField.text); return YES; } @end
構(gòu)建并運(yùn)行程序,就可以在控制臺(tái)打印信息,但是這里會(huì)有一處警告,暫時(shí)先不管。
請(qǐng)注意, JXHypnosisViewController 不需要實(shí)現(xiàn) UITextField 對(duì)象的所有委托方法,UITextField 對(duì)象會(huì)在運(yùn)行時(shí)檢查委托方法是否實(shí)現(xiàn)了某個(gè)方法,如果沒(méi)有實(shí)現(xiàn) UITextField 對(duì)象就不會(huì)調(diào)用該方法。
•協(xié)議
凡是支持委托的對(duì)象,其背后都有一個(gè)相應(yīng)的協(xié)議,聲明可以向該對(duì)象(例如:UITextField)的委托對(duì)象(例如:JXHypnosisViewController)發(fā)送的消息。委托對(duì)象(例如:JXHypnosisViewController)需要根據(jù)這個(gè)協(xié)議為其響應(yīng)的事件實(shí)現(xiàn)響應(yīng)的方法。如果一個(gè)類(lèi)實(shí)現(xiàn)了某個(gè)協(xié)議中規(guī)定的方法,就稱(chēng)這個(gè)類(lèi)遵守該協(xié)議。
聲明協(xié)議的語(yǔ)法是,使用 @protocol 指令開(kāi)頭,后跟協(xié)議的名稱(chēng)(例如:UITextFieldDelegate)。尖括號(hào)里的 NSObject 是指只 NSObject 協(xié)議,其作用是聲明 UITextFieldDelegate 中包含 NSObject 協(xié)議的全部方法。接著聲明新協(xié)議特有的方法,最后使用 @end 指令來(lái)結(jié)束。
協(xié)議不是類(lèi),只是一組方法聲明。不能為協(xié)議創(chuàng)建對(duì)象,或者添加實(shí)例變量。協(xié)議自身不實(shí)現(xiàn)方法,需要由遵守相應(yīng)協(xié)議的類(lèi)來(lái)實(shí)現(xiàn)。
協(xié)議所聲明的方法可以是必須的(required)或者是可選的(optional)。協(xié)議方法默認(rèn)都是必須的,所以當(dāng)我們自定義協(xié)議的時(shí)候最好設(shè)置一下。使用 @optional 指令,可以將寫(xiě)在該指令之后的方法去全部聲明為可選的。
發(fā)送方在發(fā)送可選方法之前,都會(huì)先向其委托發(fā)送另一個(gè)名為 respondsToSelector: 的消息。所有Objective-C 對(duì)象都從 NSObject 繼承了 respondsToSelector: 方法,該方法能在運(yùn)行時(shí)檢查對(duì)象是否實(shí)現(xiàn)了指定的方法。 @selector() 指令可以將選擇器(selector)轉(zhuǎn)換成數(shù)值,以便將其作為參數(shù)進(jìn)行傳遞。
- (void)clearButtonTapped { // textFieldShouldClear:是可選方法,需要先檢查委托是否實(shí)現(xiàn)了該方法 SEL clearSelector = @selector(textFieldShouldClear:); if ([self.delegate respondsToSelector:clearSelector]) { self.text = @""; } }
如果某個(gè)方法是必須的,那么發(fā)送發(fā)可以直接向其委托對(duì)象發(fā)送相應(yīng)的消息,不用檢查委托對(duì)象是否實(shí)現(xiàn)了該方法。這也就意味著,如果委托對(duì)象沒(méi)有實(shí)現(xiàn)相應(yīng)的方法,應(yīng)用就會(huì)拋出位置選擇器(unrecognized selector)異常,導(dǎo)致應(yīng)用崩潰。
為了防止問(wèn)題,編譯器會(huì)檢查某個(gè)類(lèi)是否實(shí)現(xiàn)了相關(guān)協(xié)議的必須方法。要讓編譯器能夠執(zhí)行此類(lèi)檢查,必須將相應(yīng)的類(lèi)聲明為遵守指定的協(xié)議,其語(yǔ)法格式為:在頭文件或類(lèi)擴(kuò)展 @interface 指令末尾,將類(lèi)所遵守的協(xié)議以都好分隔的列表形式寫(xiě)在尖括號(hào)里。
#import "JXHypnosisViewController.h" #import "JXHypnosisView.h" @interface JXHypnosisViewController ()<UITextFieldDelegate> @end @implementation JXHypnosisViewController - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // 設(shè)置標(biāo)簽項(xiàng)的標(biāo)題 self.tabBarItem.title = @"Hypnotize"; // 從圖片文件創(chuàng)建一個(gè) UIImage 對(duì)象 UIImage * i = [UIImage imageNamed:@"Hypno"]; // 將 UIImage 對(duì)象賦值給標(biāo)簽項(xiàng)的 iamge 屬性 self.tabBarItem.image = i; } return self; } - (void)viewDidLoad { [super viewDidLoad]; } - (void)loadView { // 創(chuàng)建一個(gè) JXHypnosisView 對(duì)象 JXHypnosisView * backgroundView = [[JXHypnosisView alloc] init]; CGRect textFieldRect = CGRectMake(40, 70, 240, 30); UITextField * textField = [[UITextField alloc] init]; textField.frame = textFieldRect; // 設(shè)置 UITextField 對(duì)象的邊框樣式,便于查看它在屏幕上的位置 textField.borderStyle = UITextBorderStyleRoundedRect; // 修改占位符 textField.placeholder = @"Hypontize me"; // 修改鍵盤(pán)類(lèi)型 textField.returnKeyType = UIReturnKeyDone; textField.delegate = self; [backgroundView addSubview:textField]; // 將 JXHypnosisView 對(duì)象賦給視圖控制器的view 屬性 self.view = backgroundView; } - (BOOL)textFieldShouldReturn:(UITextField *)textField { NSLog(@"%@",textField.text); return YES; } @end
幾乎所有的委托都是弱引用屬性。這是為了避免對(duì)象及其委托之間產(chǎn)生強(qiáng)引用循環(huán)。例如: JXHypnosisViewController 是 UITextField 對(duì)象的委托,而且 UITextField 對(duì)象是 JXHypnosisViewController 的強(qiáng)引用屬性,如果 UITextField 對(duì)象再對(duì)其委托保持強(qiáng)引用就會(huì)在兩者之間產(chǎn)生強(qiáng)引用循環(huán)。
•向屏幕中添加UILabel對(duì)象
下面我們?cè)?JXHypnosisViewController 中添加一個(gè)新方法,在屏幕中隨機(jī)位置繪制20個(gè) UILabel 對(duì)象。同時(shí),該方法有一個(gè) NSString 類(lèi)型的參數(shù),表示 UILabel 對(duì)象顯示的文字。
#import "JXHypnosisViewController.h" #import "JXHypnosisView.h" @interface JXHypnosisViewController ()<UITextFieldDelegate> @end @implementation JXHypnosisViewController - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // 設(shè)置標(biāo)簽項(xiàng)的標(biāo)題 self.tabBarItem.title = @"Hypnotize"; // 從圖片文件創(chuàng)建一個(gè) UIImage 對(duì)象 UIImage * i = [UIImage imageNamed:@"Hypno"]; // 將 UIImage 對(duì)象賦值給標(biāo)簽項(xiàng)的 iamge 屬性 self.tabBarItem.image = i; } return self; } - (void)viewDidLoad { [super viewDidLoad]; } - (void)loadView { // 創(chuàng)建一個(gè) JXHypnosisView 對(duì)象 JXHypnosisView * backgroundView = [[JXHypnosisView alloc] init]; CGRect textFieldRect = CGRectMake(40, 70, 240, 30); UITextField * textField = [[UITextField alloc] init]; textField.frame = textFieldRect; // 設(shè)置 UITextField 對(duì)象的邊框樣式,便于查看它在屏幕上的位置 textField.borderStyle = UITextBorderStyleRoundedRect; // 修改占位符 textField.placeholder = @"Hypontize me"; // 修改鍵盤(pán)類(lèi)型 textField.returnKeyType = UIReturnKeyDone; textField.delegate = self; [backgroundView addSubview:textField]; // 將 JXHypnosisView 對(duì)象賦給視圖控制器的view 屬性 self.view = backgroundView; } - (BOOL)textFieldShouldReturn:(UITextField *)textField { NSLog(@"%@",textField.text); return YES; } - (void)drawHypnoticMessage:(NSString *)message { for (NSInteger i = 0; i < 20; i++) { UILabel * messageLabel = [[UILabel alloc] init]; // 設(shè)置 UIlabel 對(duì)象的文字和顏色 messageLabel.backgroundColor = [UIColor clearColor]; messageLabel.textColor = [UIColor whiteColor]; messageLabel.text = message; //根據(jù)要顯示的文字調(diào)整 UILabel 對(duì)象的大小 [messageLabel sizeToFit]; // 獲取隨機(jī) x 坐標(biāo) // 使 UILabe 對(duì)象的寬度不超出控制器的 view 寬度 NSInteger width = self.view.bounds.size.width - messageLabel.bounds.size.width; NSInteger x = arc4random() % width; // 獲取隨機(jī) y 坐標(biāo) // 使 UILabel 對(duì)象的高度不超出控制器的 view 寬度 NSInteger height = self.view.bounds.size.height - messageLabel.bounds.size.height; NSInteger y = arc4random() % height; // 設(shè)置 UILabel 對(duì)象的 frame CGRect frame = messageLabel.frame; frame.origin = CGPointMake(x, y); messageLabel.frame = frame; // 將 UILabel 對(duì)象添加到控制器的 view 中 [self.view addSubview:messageLabel]; } } @end
接下來(lái)修改 textFieldShouldReturn: 將 UITextField 對(duì)象的文本內(nèi)容作為 參數(shù),調(diào)動(dòng)我們自定義的方法,之后清空文本內(nèi)容,最后調(diào)用 resignFirstResponder 關(guān)閉鍵盤(pán)。
#import "JXHypnosisViewController.h" #import "JXHypnosisView.h" @interface JXHypnosisViewController ()<UITextFieldDelegate> @end @implementation JXHypnosisViewController - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // 設(shè)置標(biāo)簽項(xiàng)的標(biāo)題 self.tabBarItem.title = @"Hypnotize"; // 從圖片文件創(chuàng)建一個(gè) UIImage 對(duì)象 UIImage * i = [UIImage imageNamed:@"Hypno"]; // 將 UIImage 對(duì)象賦值給標(biāo)簽項(xiàng)的 iamge 屬性 self.tabBarItem.image = i; } return self; } - (void)viewDidLoad { [super viewDidLoad]; } - (void)loadView { // 創(chuàng)建一個(gè) JXHypnosisView 對(duì)象 JXHypnosisView * backgroundView = [[JXHypnosisView alloc] init]; CGRect textFieldRect = CGRectMake(40, 70, 240, 30); UITextField * textField = [[UITextField alloc] init]; textField.frame = textFieldRect; // 設(shè)置 UITextField 對(duì)象的邊框樣式,便于查看它在屏幕上的位置 textField.borderStyle = UITextBorderStyleRoundedRect; // 修改占位符 textField.placeholder = @"Hypontize me"; // 修改鍵盤(pán)類(lèi)型 textField.returnKeyType = UIReturnKeyDone; textField.delegate = self; [backgroundView addSubview:textField]; // 將 JXHypnosisView 對(duì)象賦給視圖控制器的view 屬性 self.view = backgroundView; } - (BOOL)textFieldShouldReturn:(UITextField *)textField { NSLog(@"%@",textField.text); [self drawHypnoticMessage:textField.text]; textField.text = @""; [textField resignFirstResponder]; return YES; } - (void)drawHypnoticMessage:(NSString *)message { for (NSInteger i = 0; i < 20; i++) { UILabel * messageLabel = [[UILabel alloc] init]; // 設(shè)置 UIlabel 對(duì)象的文字和顏色 messageLabel.backgroundColor = [UIColor clearColor]; messageLabel.textColor = [UIColor whiteColor]; messageLabel.text = message; //根據(jù)要顯示的文字調(diào)整 UILabel 對(duì)象的大小 [messageLabel sizeToFit]; // 獲取隨機(jī) x 坐標(biāo) // 使 UILabe 對(duì)象的寬度不超出控制器的 view 寬度 NSInteger width = self.view.bounds.size.width - messageLabel.bounds.size.width; NSInteger x = arc4random() % width; // 獲取隨機(jī) y 坐標(biāo) // 使 UILabel 對(duì)象的高度不超出控制器的 view 寬度 NSInteger height = self.view.bounds.size.height - messageLabel.bounds.size.height; NSInteger y = arc4random() % height; // 設(shè)置 UILabel 對(duì)象的 frame CGRect frame = messageLabel.frame; frame.origin = CGPointMake(x, y); messageLabel.frame = frame; // 將 UILabel 對(duì)象添加到控制器的 view 中 [self.view addSubview:messageLabel]; } } @end
構(gòu)建并運(yùn)行。
•運(yùn)動(dòng)效果
iOS設(shè)備內(nèi)嵌了許多功能強(qiáng)大的傳感器,例如加速傳感器,磁場(chǎng)傳感器和三軸陀螺儀等。應(yīng)用可以通過(guò)這些傳感器了解設(shè)備加速,方向和角度,并實(shí)現(xiàn)有用的功能。例如,應(yīng)用可以根據(jù)設(shè)備的方向自動(dòng)將界面調(diào)整為橫屏或者豎屏模式。從iOS7開(kāi)始,蘋(píng)果引用了一些新 API 可以輕松為應(yīng)用添加一種通過(guò)傳感器實(shí)現(xiàn)的視覺(jué)差效果。
我們可以想象自己坐在一輛飛馳的大奔中,我們看想窗外,會(huì)發(fā)現(xiàn)遠(yuǎn)處的景物的倒退速度比近處的慢很多。這是大腦對(duì)空間和速度差異產(chǎn)生的一種錯(cuò)覺(jué),稱(chēng)之為視差。在iOS7 及之后這種效果隨處可見(jiàn),例如,在主屏幕中,如果稍微傾斜設(shè)備,可以發(fā)現(xiàn)主屏幕中的圖標(biāo)會(huì)隨著傾斜方向相對(duì)于壁紙移動(dòng)。
應(yīng)用可以通過(guò) UIInterpolatingMotionEffect 類(lèi)來(lái)實(shí)現(xiàn)相同的效果,我們只需要?jiǎng)?chuàng)建一個(gè) UIInterpolatingMotionEffect 對(duì)象,設(shè)置其方向(垂直或者水平)、鍵路勁(key path,需要使用視差效果的屬性)和相對(duì)最小/最大值(視覺(jué)差的范圍),再將其添加到某個(gè)視圖上,該視圖就能獲得相應(yīng)的視差效果。
#import "JXHypnosisViewController.h" #import "JXHypnosisView.h" @interface JXHypnosisViewController ()<UITextFieldDelegate> @end @implementation JXHypnosisViewController - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // 設(shè)置標(biāo)簽項(xiàng)的標(biāo)題 self.tabBarItem.title = @"Hypnotize"; // 從圖片文件創(chuàng)建一個(gè) UIImage 對(duì)象 UIImage * i = [UIImage imageNamed:@"Hypno"]; // 將 UIImage 對(duì)象賦值給標(biāo)簽項(xiàng)的 iamge 屬性 self.tabBarItem.image = i; } return self; } - (void)viewDidLoad { [super viewDidLoad]; } - (void)loadView { // 創(chuàng)建一個(gè) JXHypnosisView 對(duì)象 JXHypnosisView * backgroundView = [[JXHypnosisView alloc] init]; CGRect textFieldRect = CGRectMake(40, 70, 240, 30); UITextField * textField = [[UITextField alloc] init]; textField.frame = textFieldRect; // 設(shè)置 UITextField 對(duì)象的邊框樣式,便于查看它在屏幕上的位置 textField.borderStyle = UITextBorderStyleRoundedRect; // 修改占位符 textField.placeholder = @"Hypontize me"; // 修改鍵盤(pán)類(lèi)型 textField.returnKeyType = UIReturnKeyDone; textField.delegate = self; [backgroundView addSubview:textField]; // 將 JXHypnosisView 對(duì)象賦給視圖控制器的view 屬性 self.view = backgroundView; } - (BOOL)textFieldShouldReturn:(UITextField *)textField { [self drawHypnoticMessage:textField.text]; textField.text = @""; [textField resignFirstResponder]; return YES; } - (void)drawHypnoticMessage:(NSString *)message { for (NSInteger i = 0; i < 20; i++) { UILabel * messageLabel = [[UILabel alloc] init]; // 設(shè)置 UIlabel 對(duì)象的文字和顏色 messageLabel.backgroundColor = [UIColor clearColor]; messageLabel.textColor = [UIColor whiteColor]; messageLabel.text = message; //根據(jù)要顯示的文字調(diào)整 UILabel 對(duì)象的大小 [messageLabel sizeToFit]; // 獲取隨機(jī) x 坐標(biāo) // 使 UILabe 對(duì)象的寬度不超出控制器的 view 寬度 NSInteger width = self.view.bounds.size.width - messageLabel.bounds.size.width; NSInteger x = arc4random() % width; // 獲取隨機(jī) y 坐標(biāo) // 使 UILabel 對(duì)象的高度不超出控制器的 view 寬度 NSInteger height = self.view.bounds.size.height - messageLabel.bounds.size.height; NSInteger y = arc4random() % height; // 設(shè)置 UILabel 對(duì)象的 frame CGRect frame = messageLabel.frame; frame.origin = CGPointMake(x, y); messageLabel.frame = frame; // 將 UILabel 對(duì)象添加到控制器的 view 中 [self.view addSubview:messageLabel]; UIInterpolatingMotionEffect * motionEffect; motionEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; motionEffect.minimumRelativeValue = @(-25); motionEffect.maximumRelativeValue = @(25); [messageLabel addMotionEffect:motionEffect]; motionEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis]; motionEffect.minimumRelativeValue = @(-25); motionEffect.maximumRelativeValue = @(25); [messageLabel addMotionEffect:motionEffect]; } } @end
測(cè)試運(yùn)動(dòng)效果必須在真機(jī)上。
•深入學(xué)習(xí):main() 和 UIApplication
用C語(yǔ)言編寫(xiě)的程序,其至此那個(gè)入口都是 main() 。用 Objective-C 語(yǔ)言編寫(xiě)的程序也是這樣。
在 JXHypnoNerd 項(xiàng)目中我們?cè)?mian.m,可以看到有如下代碼
#import <UIKit/UIKit.h> #import "AppDelegate.h" int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } }
這段代碼中的 UIApplicationMain 函數(shù)會(huì)創(chuàng)建一個(gè) UIApplication 對(duì)象。 每個(gè)iOS應(yīng)用都有且只有一個(gè)UIApplication對(duì)象,該對(duì)象的作用就是維護(hù)運(yùn)行循環(huán)。一旦程序創(chuàng)建了某個(gè) UIApplication 對(duì)象,該對(duì)象的運(yùn)行循環(huán)就會(huì)一直循環(huán)下去,main() 的執(zhí)行也會(huì)因此堵塞。
此外, UIApplicationMain 函數(shù)還會(huì)創(chuàng)建某個(gè)指定類(lèi)的對(duì)象,并將其設(shè)置為 UIApplication 對(duì)象的 delegate 。該對(duì)象的類(lèi)是由 UIApplicationMain 函數(shù)的最后一個(gè)實(shí)參指定的,該實(shí)參的類(lèi)型是 NSString 對(duì)象,代表的是某個(gè)類(lèi)的類(lèi)名。所以在以上這段代碼中, UIApplicationMain 會(huì)創(chuàng)建一個(gè) AppDelegate 對(duì)象,并將其設(shè)置為 UIApplication 對(duì)象的 delegate 。
在應(yīng)用啟動(dòng)運(yùn)行循環(huán)并開(kāi)始接收事件之前,UIApplication 對(duì)象會(huì)向其委托發(fā)送一個(gè)特性的消息,使應(yīng)用能有機(jī)會(huì)完成相應(yīng)的初始化工作。這個(gè)消息的名稱(chēng)是
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
以上所述是小編給大家介紹的iOS 委托與文本輸入(內(nèi)容根據(jù)iOS編程編寫(xiě)),希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
IOSdrawRect實(shí)現(xiàn)雪花飄落效果
這篇文章主要為大家詳細(xì)介紹了IOSdrawRect實(shí)現(xiàn)雪花飄落效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06IOS利用CocoaHttpServer搭建手機(jī)本地服務(wù)器
這篇文章主要介紹了IOS利用CocoaHttpServer搭建手機(jī)本地服務(wù)器的步驟,幫助大家更好的理解和學(xué)習(xí)使用ios開(kāi)發(fā),感興趣的朋友可以了解下2021-04-04iOS實(shí)現(xiàn)淘寶上拉進(jìn)入詳情頁(yè)交互效果
最近遇到一個(gè)項(xiàng)目,項(xiàng)目中某個(gè)新需求的交互要求仿照淘寶上拉從下往上彈出寶貝詳情。所以死打開(kāi)淘寶APP仔細(xì)看了看,然后自己寫(xiě)了寫(xiě),現(xiàn)在感覺(jué)效果差不多了,記錄一下分享給大家,方法自己和大家需要的時(shí)候查看借鑒,感興趣的朋友們下面跟著小編一起來(lái)學(xué)習(xí)學(xué)習(xí)吧。2016-11-11iOS 斷點(diǎn)上傳文件的實(shí)現(xiàn)方法
這項(xiàng)目開(kāi)發(fā)中,有時(shí)候我們需要將本地的文件上傳到服務(wù)器,簡(jiǎn)單的幾張圖片還好,但是針對(duì)iPhone里面的視頻文件進(jìn)行上傳,為了用戶體驗(yàn),我們有必要實(shí)現(xiàn)斷點(diǎn)上傳。這篇文章主要介紹了iOS 斷點(diǎn)上傳文件的實(shí)現(xiàn)方法,需要的朋友可以參考下2017-12-12iOS中UITableView使用的常見(jiàn)問(wèn)題總結(jié)
這篇文章主要總結(jié)了iOS中UITableView使用的常見(jiàn)問(wèn)題,其中包括如何設(shè)置headerView以及其高度、去掉多余cell的分割線 以及如何設(shè)置section數(shù)、行數(shù)等一系列的問(wèn)題,文中介紹的更詳細(xì),需要的朋友們下面來(lái)一起看看詳細(xì)介紹吧。2017-03-03