《iPhone與iPad開發實戰—iOS經典應用剖析》連載七
3.3.4主視圖代碼在本應用中主視圖中使用的視圖是MainView,事實上在很多應用中我們不用為視圖控製器自定義一個視圖類的而是直接使用UIView基類就可以了。由於本應用是按照舊版本的Xcode模板編寫的,我們還是按照舊版本介紹吧。在Cocoa MVC設計模式中,視圖中的控件在視圖控製器或者視圖中都要有對應的控件變量,沒有自定義視圖類的時候,這些控件變量是在視圖控製器中定義的,有了自定義視圖類後,這些控件變量可以在視圖類中定義,本應用就是這樣子的。
主視圖類是MainView,它的h文件定義請參考“代碼清單3-3Password/Classes/MainView.h”所示。
【代碼清單3-1】 Password/Classes/MainView.h
<pre >
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
@interface MainView : UIView {
IBOutletUITextField *passwordLength;
IBOutletUITextField *emailAddress;
IBOutletUISwitch *includeLowerCase;
IBOutletUISwitch *includeNumbers;
IBOutletUISwitch *includePunctuation;
IBOutletUISwitch *includeUpperCase;
IBOutletUISwitch *showPhonetics;
IBOutletUITextField *password;
IBOutletUITextView *phoneticPassword;
IBOutletUIButton *emailPasswordButton;
}
@property (nonatomic, retain) UITextField*emailAddress;
@property (nonatomic, retain) UITextView*phoneticPassword;
@property (nonatomic, retain) UITextField*passwordLength;
@property (nonatomic, retain) UIButton*emailPasswordButton;
- (IBAction)setPasssword;
- (IBAction)resignResponder;
- (IBAction)emailPassword;
@end
</pre>
從“代碼清單3-3 Password/Classes/MainView.h”可以看到定義的控件變量,這需要注意的是在本應用中這些變量都定義了IBOutlet(輸出口)其實沒有這個必要,一個控件是否定義輸出口要看是否需要通過程序修改其屬性。此外還定義了3個方法,setPasssword方法是響應Generate Password按鈕事件,resignResponder是放棄第一響應者方法,在文本框等控件中可以輸入數據,輸入數據過程中會出現鍵盤,通過文本框放棄第一響應者後才能關閉鍵盤。emailPassword是響應E-Mail Password按鈕事件把產生的密碼通過E-Mail發送出去。
主視圖類是MainView,它的m文件定義請參考“代碼清單3-4Password/Classes/MainView.m”所示。
【代碼清單3-2】 Password/Classes/MainView.m
<pre >
#import "MainView.h"
#define RANDOM_SEED() srandom(time(NULL))
#define RANDOM_INT(__MIN__, __MAX__) ((__MIN__) +random() % ((__MAX__+1) - (__MIN__)))
@implementation MainView
@synthesize phoneticPassword;
@synthesize passwordLength;
@synthesize emailPasswordButton;
@synthesize emailAddress;
- (id)initWithFrame:(CGRect)frame {
if(self = [super initWithFrame:frame]) {
}
returnself;
}
- (IBAction)setPasssword {
[UIViewbeginAnimations:nil context:NULL];
[UIViewsetAnimationDuration:1];
[passwordsetAlpha:0.0];
[phoneticPasswordsetAlpha:0.0];
[emailPasswordButtonsetAlpha:0.0];
[UIViewcommitAnimations];
[UIViewbeginAnimations:nil context:NULL];
[UIViewsetAnimationDuration:1];
[passwordsetAlpha:0.85];
if(showPhonetics.on){[phoneticPassword setAlpha:0.85];}
[emailPasswordButtonsetAlpha:0.85];
[UIViewcommitAnimations];
… …
}
-(IBAction) resignResponder {
[passwordresignFirstResponder];
[passwordLengthresignFirstResponder];
}
- (BOOL)textFieldShouldReturn:(UITextField*)textField {
if(textField == password) {
[passwordresignFirstResponder];
}
if(textField == passwordLength) {
[passwordLengthresignFirstResponder];
}
returnYES;
}
-(IBAction) emailPassword {
NSString*urlString = @"mailto:?subject=Password%20Generator&body=";
urlString= [urlString stringByAppendingString:@"Password:%20"];
urlString= [urlString stringByAppendingString:password.text];
if(showPhonetics.on){
urlString= [urlString stringByAppendingString:@"%20Phonetic:%20"];
urlString= [urlString stringByAppendingString:[phoneticPassword.textstringByReplacingOccurrencesOfString:@" "withString:@"%20"]];
}
NSURL*mailURL = [NSURL URLWithString: urlString];
[[UIApplicationsharedApplication] openURL: mailURL];
}
@end
</pre>
下麵我們分析一下上麵的代碼,在m文件的開始定義了兩個宏RANDOM_SEED和RANDOM_INT。RANDOM_SEED產生隨機數種子值,RANDOM_INT是參數隨機數,其中函數srandom()、random()和time()都是C語言中的函數。
#define RANDOM_SEED() srandom(time(NULL))
#define RANDOM_INT(__MIN__, __MAX__) ((__MIN__) +random() % ((__MAX__+1) - (__MIN__)))
在主視圖控製器m文件中最為主要的幾個方法是:setPasssword、emailPassword、resignResponder和textFieldShouldReturn:其中前3個方法是有關事件處理的,下麵我們一一介紹一下這幾個方法。
setPasssword方法是主要實現了密碼的計算和視圖中下麵3個控件的動畫顯示。關於如何計算和產生密碼,本書就不再介紹了。在本方法裏我們重點研究視圖中3個控件的動畫顯示問題,這部分的動畫也屬於UIView級別動畫,使用UIViewbeginAnimations:開始UIViewcommitAnimations結束,事實上這是兩個動畫,先是通過下麵的代碼將3個控件Alpha設置為0.0,即不可見。
[UIViewbeginAnimations:nil context:NULL];
[UIViewsetAnimationDuration:1];
[passwordsetAlpha:0.0];
[phoneticPasswordsetAlpha:0.0];
[emailPasswordButtonsetAlpha:0.0];
[UIViewcommitAnimations];
然後再通過下麵的代碼將3個控件Alpha設置為0.85,即可見但是還有一點模煳的效果。這樣兩個動畫分別作用於3個控件,如果控件不可見,控件就變成可見,如果控件已經可見,就先變成不可見,再可見。持續時間都是1秒鍾。
[UIViewbeginAnimations:nil context:NULL];
[UIViewsetAnimationDuration:1];
[passwordsetAlpha:0.85];
if(showPhonetics.on){[phoneticPassword setAlpha:0.85];}
[emailPasswordButtonsetAlpha:0.85];
[UIViewcommitAnimations];
emailPassword方法是將密碼通過E-Mail發送出去,其中在iOS中E-Mail發送可以通過MFMailComposeViewController和MFMailComposeViewControllerDelegate發送,如果郵件中沒有圖片和附件也可以通過本應用采用的簡單發送方式:
[[UIApplication sharedApplication] openURL:mailURL];
通過應用程序內部對象的openURL方法發送E-Mail,其中mailURL是一個特定格式的字符串其中,開頭是mailto,其中主題部分subject,內容部分body,還有cc等參數。
NSString *urlString = @"mailto:?subject=Password%20Generator&body=";
iOS中這個[UIApplication sharedApplication] openURL方法可以做很多事情,其中可以:
· 打開瀏覽器,格式“https://itunesconnect.apple.com”;
· 打開Google地圖,格式“https://maps.google.com/maps?q=${QUERY_STRING}”,這是使用Web瀏覽器方式打開地圖,其中q是查詢的參數,例如:經緯度等信息,在iOSSDK中還可以通過本地API方式打開地圖;
· 撥打電話,格式“tel://10086”;
· 發送短信,格式“sms://10086”。
但是要注意的是除了打開瀏覽器可以在模擬器上打開,其它的幾個包括E-Mail的發送,都是不能在模擬器上打開,必須在真機上打開的。
resignResponder和textFieldShouldReturn:都是放棄第一響應的,經過測試本應用中的resignResponder方法並沒有觸發,沒有實際意義,而textFieldShouldReturn:方法起到了作用,該方法是來源於UITextFieldDelegate協議中的方法,在iOS中delegate(委托)是一種設計模式,它通過一個協議(類似於Java中的接口)定義,要求它的實現類必須實現它的方法,這些方法將在某些事件發生的時候被觸發(或回調)。- (BOOL)textFieldShouldReturn:方法就是在文本框編輯狀態時候,點擊鍵盤的回車按鈕時候觸發的方法。
事實上我們需要在主視圖的h文件這樣定義MainView:
@interface MainView :UIView<UITextFieldDelegate> {}
而本應用中沒有<UITextFieldDelegate>方式定義,這裏涉及到Objective-C的動態方法調用問題,與Java等麵向對象的語言不同的是,Objective-C不用必須在聲明中指定協議,而直接在m文件給出該協議的實現方法也是可以的。
@interface MainView : UIView {}
在textFieldShouldReturn方法執行的時候判斷當前的文本框是密碼還是密碼長度,從而放棄對應文本框的第一響應者。
[passwordresignFirstResponder];
[passwordLengthresignFirstResponder];
最後更新:2017-04-02 16:47:37