在很多種語言中,alert都表示彈窗操作,彈窗功能非常有用,不僅可以用於正式的app功能中,也可以在調試中使用。在OC中,UIAlertController類用來控制彈窗操作。在IOS 8.0之前, 其使用UIAlertView類來控制彈窗,如果我們想彈出一個帶有輸入框的窗口,可以使用如下的代碼:
// Prior to iOS 8.0 UIAlertView *alert = [[UIAlertView init] initWithTitle:@"Alert Title" message:@"Alert Message" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil]; alert.alertViewStyle = UIAlertViewStylePlainTextInput; [alert textFieldAtIndex:0].text = @"Show Text Here"; [alert show]; - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { if (buttonIndex == 0) return; // Do something after clicking OK button }
我們可以看出如果要實現彈窗中的按鈕功能,需要使用代理模式,功能代碼需要寫在clickedButtonAtIndex()函數中,這種寫法固然可以實現功能,但是在某些情況下並不是很方便。比如說我們有一個UITableView,我們點擊任意某一行進行彈窗操作,那么上面聲明彈窗的代碼需要寫在didSelectRowAtIndexPath()函數中,但是由於彈窗按鈕的操作在另一個代理函數中,我們不能直接訪問當前行數indexPath.row,只能將其存入一個全局變量中,或者我們在聲明完彈窗后,將當前行數綁定到alert的tag上,這樣在代理函數中才可以直接使用。而且我們如果要用reloadRowsAtIndexPaths函數來更新當前行的時候,還需要自己創建一個包含indexPath類對象的數組,略顯麻煩。
而在IOS 8.0之后,UIAlertView被拋棄了,取而代之的是UIAlertController類,我們想實現相同功能的彈窗需要使用如下的代碼:
// After iOS 8.0 UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Alert Title" message:@"Alert Message" preferredStyle:UIAlertControllerStyleAlert]; [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) { textField.placeholder = NSLocalizedString(@"TextPlaceholder", @"Text"); }]; UIAlertAction *okButton = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { // Do something after clicking OK button UITextField *textField = alert.textFields.firstObject; }]; UIAlertAction *cancelButton = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) { // Do something after clicking Cancel button }]; [alert addAction:okButton]; [alert addAction:cancelButton]; [self presentViewController:alert animated:YES completion:nil];
我們發現貌似寫法變得更復雜了,雖然代碼量多了點,但是卻完全摒棄了代理模式,而且添加按鈕和輸入框的方式變的更加自由了,按鈕功能代碼也不必寫在其他的代理函數中,整個結構一目了然,面向對象的感覺撲面而來,感覺很叼。
參考資料: