2012-03-12 180 views
8

我有一個函數,顯示一個UIAlertView與YES/NO按鈕,它只用於函數的範圍內,所以我不想實現一個委託來捕捉用戶反饋。有沒有委託處理UIAlertView結果的簡單方法?

有沒有辦法知道哪個按鈕用戶點擊不落實UIAlertViewDelegate,是這樣的:

[alert show]; 
if([alert indexOfClickedButton] == indexOfYes) 
{ 
.... 
} 

或lambda表達式,如動畫

+1

UIAlertView中沒有代表團只有一個,ü創建一個自定義UIAlertView中的方式。 – ios 2012-03-12 05:03:46

+2

這裏是一個實現基於塊的UIAlertview的網站(以及其他內容):http://blog.mugunthkumar.com/coding/ios-code-block-based-uialertview-and-uiactionsheet/ – lnafziger 2012-03-12 05:18:13

+0

UIAlertView * aletView = [[UIAlertView alloc] initWithTitle:@「Any Title」message:@「Hiii」delegate:self cancelButtonTitle:@「Cancel」otherButtonTitles:nil,nil]; [alert show];如果需要, 不使用任何委託。 – 2012-03-12 09:46:51

回答

23

沒有辦法完全避免委託,但是您可以沿着這些方向創建一個包裝效果:

@interface MyAlertViewDelegate : NSObject<UIAlertViewDelegate> 

typedef void (^AlertViewCompletionBlock)(NSInteger buttonIndex); 
@property (strong,nonatomic) AlertViewCompletionBlock callback; 

+ (void)showAlertView:(UIAlertView *)alertView withCallback:(AlertViewCompletionBlock)callback; 

@end 


@implementation MyAlertViewDelegate 
@synthesize callback; 

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { 
    callback(buttonIndex); 
} 

+ (void)showAlertView:(UIAlertView *)alertView 
     withCallback:(AlertViewCompletionBlock)callback { 
    __block MyAlertViewDelegate *delegate = [[MyAlertViewDelegate alloc] init]; 
    alertView.delegate = delegate; 
    delegate.callback = ^(NSInteger buttonIndex) { 
     callback(buttonIndex); 
     alertView.delegate = nil; 
     delegate = nil; 
    }; 
    [alertView show]; 
} 

@end 

(假設ARC,如果你不使用它改變delegate = nil[delegate release]

用法是這樣的:

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Confirm" message:@"Yes or No?" delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles:@"Yes",@"No", nil]; 
[MyAlertViewDelegate showAlertView:alert withCallback:^(NSInteger buttonIndex) { 
    // code to take action depending on the value of buttonIndex 
}]; 
+0

謝謝,您的解決方案的工作原理。 – jAckOdE 2012-03-13 01:27:41

+1

我在執行'delegate = nil'的行上收到編譯器警告:在此塊中強烈地捕獲委託很可能導致保留週期。這在iOS 5.1 ARC下。 – 2012-05-20 13:25:42

+1

'delegate = nil'是必須的,因爲'alertView.delegate'是一個非保留屬性,我們需要保持對象爲「委託」,直到警報視圖爲按鈕回調完成。這個警告(誤報)可以用'#pragma clang diagnostic push'和'#pragma clang diagnostic ignored'-Warc-retain-cycles''忽略,並在該行後面加上'#pragma clang diagnostic pop'。 – AndiDog 2013-09-23 11:24:51

1

這很容易。假設你有一個警告,這樣的事情:

//Alert 
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Confirm" message:@"Yes or No?" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Yes",@"No", nil]; 
[alert show]; 

你將需要添加這個方法:

- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex 

一種可能實現這個方法的是這樣的:

- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { 

//Checks For Approval 
    if (buttonIndex == 1) { 
     //do something because they selected button one, yes 
    } else { 
     //do nothing because they selected no 
    } 
} 
+13

但他特意問了怎麼做_overout delegation_ ... – Arkku 2012-03-12 04:58:30

+0

沒有仔細閱讀。如果它有幫助 – JTApps 2012-03-12 04:59:35

+0

謝謝!是的,它會爲我節省一些代碼行,但我仍然需要在函數範圍之外編寫一些代碼,並且可能會保存alertview的引用,這正是我不想要的。我正在尋找一個基於塊的解決方案,如果沒有簡單的方法來做到這一點,我認爲你的解決方案將是最好的。 – jAckOdE 2012-03-12 05:31:27

0

你可以做哪些可以隱藏這一點使用自定義視圖並顯示爲避免動作片

UIView *AlertVw=[UIView alloc]initWithFrame:CGRect(x,y,w,h)]]; 

UIButton *SaveButton=[UIButton alloc]initWithFrame:CGRect(x,y,w,h)]]; 
[CustomButton setTitle:@"Ok" forState:UIControlStateNormal]; 
[SaveButton addTarget:self action:@selector(SaveClicked)   forControlEvents:UIControlEventTouchUpInside]; 

UIButton *CancelButton=[UIButton alloc]initWithFrame:CGRect(x,y,w,h)]]; 
[CustomButton setTitle:@"Cancel" forState:UIControlStateNormal]; 
[CancelButton addTarget:self action:@selector(CancelClicked)   forControlEvents:UIControlEventTouchUpInside]; 

[AlertVw addSubview:SaveButton]; 
[AlertVw addSubview:CancelButton]; 

[self.view addSubview:AlertVw]; 

-(void)SaveButton 
{ 
    //Code to apply on Save clicked 
    [AlertVw removeFromSuperView]; //Also you can use AlertView.hidden=YES; 

} 
-(void)CancelButton 
{ 
    //Code to apply on cancel clicked 
    [AlertVw removeFromSuperView]; //Also you can use AlertView.hidden=YES; 

} 
0

無需派生類。使用Block,可以很容易地獲得用戶選擇的按鈕索引。

typedef void(^AlertViewCallBackBlock)(NSInteger selectedIndex); 

@interface ABC() 
    @property (nonatomic, copy) AlertViewCallBackBlock alertViewBlock; 
@end 

@implementation 

- (void)showAlert { 
    self.alertViewBlock = ^(NSInteger selectedIndex) { 
     if (selectedIndex == 1) { 

     } 
    }; 
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Confirm" message:@"Yes or No?" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Yes",@"No", nil]; 
    [alert show]; 
} 

- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { 
    self.alertViewBlock(buttonIndex); 
} 
@end 
3

我寫了一個博客張貼有關如何(以及爲何)加擋回調來提醒觀點,動作片和動畫:

http://blog.innovattic.com/uikitblocks/

如果你只是想這樣一個工作實現你可以從GitHub下載源文件:

https://github.com/Innovattic/UIKit-Blocks

用法:

UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"My easy alert" 
               message:@"Would you like to perform some kind of action?" 
             cancelButtonTitle:@"No" 
             otherButtonTitles:@"Yes", nil]; 
[alert setHandler:^(UIAlertView* alert, NSInteger buttonIndex) { 
    NSLog(@"Perform some kind of action"); 
} forButtonAtIndex:[alert firstOtherButtonIndex]]; 
[alert show]; 
+0

很久以前找到答案,但仍然是很好的作品 – jAckOdE 2014-02-27 02:59:52

0

UIAlertView從iOS版8.0中,建議更好的解決方案將使用UIAlertController

let alert = UIAlertController(title: "message", message: "Title", preferredStyle: .Alert) 

alert.addAction(UIAlertAction(title: "YES", style: .Default, handler: { (action) -> Void in 
    // Action for YES 
})) 
alert.addAction(UIAlertAction(title: "NO", style: .Default, handler: { (action) -> Void in 
    // Action for NO 
})) 

self.view.window!.rootViewController!.presentViewController(alert, animated: true, completion: nil)