2009-09-03 13 views
4

私のメソッドの1つは、オブジェクトにメッセージを送ります(それについてあなたは何を知っていますか)。しかし、BOOLは受信オブジェクトのメソッドで作成されたUIAlertViewへの応答に基づいていると考えています。ただし、ユーザーがUIAlertViewに応答するのを待つ間、コードは一時停止しません。私の問題は次のとおりです。-alertView:メソッドの戻り値にclickedButtonAtIndexを使用するにはどうすればよいですか?UIAlertViewボタンが押されるまでコード実行を一時停止しますか?

ここでメッセージが(この構成では、私はnavigateAwayFromTabはUIAlertViewでのユーザー入力に基づいて変更するよう期待していたが、それはチャンスを得ることはありません)実行されるコードです:

- (BOOL)readyToNavigateAwayFromTab { 
    NSLog(@"message received by Medical View"); 
    navigateAwayFromTab = NO; 
    UIAlertView *alert = [[UIAlertView alloc] 
      initWithTitle:@"Navigate Away From Tab?" 
       message:@"Navigating away from this tab will save your work." 
       delegate:self 
     cancelButtonTitle:@"Cancel" 
     otherButtonTitles:@"OK", nil 
    ]; 
    [alert show]; 
    [alert release]; 
    return navigateAwayFromTab; 
} 
#define CANCEL 0 
#define OK 1 
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { 
    if(buttonIndex == OK) navigateAwayFromTab = YES; 
} 

私が読んできたが、モーダルUIAlertViewの議論では、アップルの実装に同意します。しかし、この場合、UIAlertViewに基づいてコードを実行する必要がないため、-alertView:clickedButtonAtIndexにコードを入れて問題を解決する方法はありません。ただ応答を読むだけです。どのように私は私のガールに達することができるかについての任意の提案?私は[alert show]の後にwhileループを試しましたが、警告は表示されず、さまざまな理由で-viewWillDisapearを使用できません。現代のiOS時代にこの質問を見た人のために

編集

、この質問には回答が提供されるまで2

答えて

10

UIAlertViewのショーは、ユーザーがボタンに触れるのを待つだけでなく、アラートビューが見えなくなるのを待つこともありません。すぐにを返します。です。

クラスにフラグを追加します。それがNOの場合は、readyToNavigateAwayFromTabからNOを返し、アラートを表示します。 clickedButtonAtIndexでは、readyToNavigateAwayFromTabがYESを返すことを知るようにフラグを設定します。引き続きclickedButtonAtIndexで、コードからタブナビゲーションを再試行してください。 NSConditionを使用して

+0

鮮やかな溶液。旗のために万歳!ありがとう。 – JoBu1324

+0

うわー。あなたが帰ってくるとは決して想像もしませんでした。私の答えはとても遅かったです。それが助けてくれてうれしい。 :) –

0

[alert show]文がアプリケーションを保持すべきであるIOSすることに関するものでした。

コントローラをUIAlertViewDelegateプロトコルに加入させましたか?実装では

@interface RootViewController : UIViewController <UIAlertViewDelegate> { 
    BOOL navigateAwayFromTab; 
} 

@property BOOL navigateAwayFromTab; 

... 

@end 

@implementation RootViewController 

@synthesize navigateAwayFromTab; 

... 

- (void) readyToNavigateAwayFromTab { 
    UIAlertView *alert = [[UIAlertView alloc] 
     initWithTitle:@"Navigate Away From Tab?" 
      message:@"Navigating away from this tab will save your work." 
      delegate:self 
    cancelButtonTitle:@"Cancel" 
    otherButtonTitles:@"OK", nil 
    ]; 
    [alert show]; 
    [alert release]; 
} 

#define CANCEL 0 
#define OK 1  
- (void) alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { 
    if ([actionSheet.title compare:@"Navigate Away From Tab?"] == NSOrderedSame) { 
    if (buttonIndex == OK) 
     self.navigateAwayFromTab = YES; 
    else 
     self.navigateAwayFromTab = NO; 
    } 
} 

@interface RootViewController : UIViewController <UIAlertViewDelegate, UITabBarDelegate, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate> 

また、例えば、あなたのnavigateAwayFromTab変数プロパティ、作るかもしれません:あなたは、コントローラのヘッダファイルに<UIAlertViewDelegate>を追加する必要がある場合など、チェック

+0

返信いただきありがとうございます!私はUIAlertViewDelegateを購読しても効果がありません。アラートが消えるまで[アラートショー]が待つことになっていますか?どこでも見たことがある人は、UIAlertViewをモーダルで動作させようとしている人を見てきました。 – JoBu1324

+0

[警告表示]が正しく動作しない場合は、XCodeで新しいプロジェクトを作成し、このテストプロジェクトでテストUIAlertViewを実行することをお勧めします。これは、より多くの仕事ですが、それはあなたの既存の問題のトラブルシューティングに役立ちます。 –

+0

私はUICatalogからリンゴコードを取り出し、[警告表示]の後にNSLog()メッセージを挿入しましたが、NSLogメッセージは警告を消す前に起動しました。私は、警告メソッドが呼び出された後も別のNSLog呼び出しを配置し​​ましたが、そのメッセージも警告を破棄する前に実行されました。私は疑わしいと思うのは嫌いですが、私は今2時には0です。 [alert show]は、呼び出されたメソッドでコードの実行を一時停止する必要がありますか?投稿できるコードがありますか?ありがとう、jb – JoBu1324

4

ソリューションバックグラウンドスレッドからトリガ:私が見つけてきた

// on background thread 
condition = [NSCondition new]; 
questionAnswered = NO; 
// display UIAlertView in a method on main thread with -performSelectorOnMainThread:withObject:waitUntilDone: 
[condition lock]; 
while (! questionAnswered) [condition wait]; 
questionAnswered = NO; 
[condition unlock]; 
[condition release]; 

// on main thread in delegate method -alertView:clickedButtonAtIndex: 
// (do something with choosen buttonIndex) 
questionAnswered = YES; 
[condition signal]; 
[condition unlock] 

ラファエル

+0

+1実際には正しい道を導いてくれるから、UIAlertView + MKBlockAdditions.hを呼び出すAlertViewクラスを自分で作成していたのですが、AlertViewクラスでは、上記のスレッドコードでMKUIAlertViewへの呼び出しをラップしました。私が気づいたのは、スレッドを数回アンロックしていくつかのエラーをスローすることだけです。 – J3RM

1

ベストソリューションは、彼のブログ記事Painless UIAlertViewにSasmito Adibowoからです。彼は、デリゲートハンドラとしてクロージャを使用できる汎用のUIAlertViewDelegate実装であるBSAlertViewDelegateBlockを作成しました。ここで

は、あなたがそれを使用する方法は次のとおりです。

UIAlertView* alert = ...; 
BSAlertViewDelegateBlock* alertDelegate = [[BSAlertViewDelegateBlock alloc] initWithAlertView:alert]; 
alertDelegate.didDismissWithButtonIndexBlock = ^(UIAlertView* alertView, NSInteger buttonIndex) 
{ 
    switch (buttonIndex) 
    { 
     ... 
    } 
}; 
[alert show]; 

BSAlertViewDelegateBlock.hBSAlertViewDelegateBlock.mの実装はGitHubの上で利用可能ですが、私はここにコードを転載しました:

BSAlertViewDelegateBlock.h

#import <UIKit/UIKit.h> 

/** 
Adapts UIAlertViewDelegate protocol into a block-friendly interface. 
*/ 
@interface BSAlertViewDelegateBlock : NSObject<UIAlertViewDelegate> 

/** 
Designated initializer. 
*/ 
-(id) initWithAlertView:(UIAlertView*) alertView; 

@property (nonatomic,strong) void(^clickedButtonAtIndexBlock)(UIAlertView* alertView,NSInteger buttonIndex); 
@property (nonatomic,strong) void(^alertViewCancelBlock)(UIAlertView* alertView); 
@property (nonatomic,strong) void(^willPresentAlertViewBlock)(UIAlertView* alertView); 
@property (nonatomic,strong) void(^didPresentAlertViewBlock)(UIAlertView* alertView); 

@property (nonatomic,strong) void(^willDismissWithButtonIndexBlock)(UIAlertView* alertView,NSInteger buttonIndex); 
@property (nonatomic,strong) void(^didDismissWithButtonIndexBlock)(UIAlertView* alertView,NSInteger buttonIndex); 

@property (nonatomic,strong) BOOL(^alertViewShouldEnableFirstOtherButtonBlock)(UIAlertView* alertView); 

@end 

BSAlertViewDelegateBlock.m

#import <objc/runtime.h> 

#import "BSAlertViewDelegateBlock.h" 

const char* const BSAlertViewDelegateBlockKey = "BSAlertViewDelegateBlockKey"; 

@interface BSAlertViewDelegateBlock() 

@property (nonatomic,weak) UIAlertView* alertView; 

@end 

@implementation BSAlertViewDelegateBlock 

-(void) alertViewDelegateBlock_cleanup 
{ 
UIAlertView* alertView = self.alertView; 
// remove all handler blocks in case one of these blocks inadvertendly caused a circular reference to this delegate object. 
self.clickedButtonAtIndexBlock = nil; 
self.alertViewCancelBlock = nil; 
self.willPresentAlertViewBlock = nil; 
self.didPresentAlertViewBlock = nil; 
self.willDismissWithButtonIndexBlock = nil; 
self.didDismissWithButtonIndexBlock = nil; 
self.alertViewShouldEnableFirstOtherButtonBlock = nil; 
// finally remove this delegate from the alert view 
if (alertView.delegate == self) { 
alertView.delegate = nil; 
objc_setAssociatedObject(alertView, BSAlertViewDelegateBlockKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 
} 
} 

-(id) initWithAlertView:(UIAlertView *)alertView 
{ 
if (self = [super init]) { 
self.alertView = alertView; 
objc_setAssociatedObject(alertView, BSAlertViewDelegateBlockKey, self, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 
alertView.delegate = self; 
} 
return self; 
} 


#pragma mark UIAlertViewDelegate 

// Called when a button is clicked. The view will be automatically dismissed after this call returns 
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex 
{ 
void(^clickedButtonAtIndexBlock)(UIAlertView* alertView,NSInteger buttonIndex) = self.clickedButtonAtIndexBlock; 
if (clickedButtonAtIndexBlock) { 
clickedButtonAtIndexBlock(alertView,buttonIndex); 
} 
} 

// Called when we cancel a view (eg. the user clicks the Home button). This is not called when the user clicks the cancel button. 
// If not defined in the delegate, we simulate a click in the cancel button 
- (void)alertViewCancel:(UIAlertView *)alertView 
{ 
void(^alertViewCancelBlock)(UIAlertView* alertView) = self.alertViewCancelBlock; 
if (alertViewCancelBlock) { 
alertViewCancelBlock(alertView); 
} 
[self alertViewDelegateBlock_cleanup]; 
} 

- (void)willPresentAlertView:(UIAlertView *)alertView 
{ 
void(^willPresentAlertViewBlock)(UIAlertView* alertView) = self.willPresentAlertViewBlock; 
if (willPresentAlertViewBlock) { 
willPresentAlertViewBlock(alertView); 
} 
} 


- (void)didPresentAlertView:(UIAlertView *)alertView 
{ 
void(^didPresentAlertViewBlock)(UIAlertView* alertView) = self.didPresentAlertViewBlock; 
if (didPresentAlertViewBlock) { 
didPresentAlertViewBlock(alertView); 
} 
} 


- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex 
{ 
void(^willDismissWithButtonIndexBlock)(UIAlertView* alertView,NSInteger buttonIndex) = self.willDismissWithButtonIndexBlock; 
if (willDismissWithButtonIndexBlock) { 
willDismissWithButtonIndexBlock(alertView,buttonIndex); 
} 
} 


- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex 
{ 
void(^didDismissWithButtonIndexBlock)(UIAlertView* alertView,NSInteger buttonIndex) = self.didDismissWithButtonIndexBlock; 
if (didDismissWithButtonIndexBlock) { 
didDismissWithButtonIndexBlock(alertView,buttonIndex); 
} 
[self alertViewDelegateBlock_cleanup]; 
} 


- (BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView 
{ 
BOOL(^alertViewShouldEnableFirstOtherButtonBlock)(UIAlertView* alertView) = self.alertViewShouldEnableFirstOtherButtonBlock; 
if (alertViewShouldEnableFirstOtherButtonBlock) { 
return alertViewShouldEnableFirstOtherButtonBlock(alertView); 
} 

// default to enable. 
return YES; 
} 


@end 
関連する問題