使UIAlertView阻止

时间:2010-09-20 15:51:49

标签: cocoa-touch ios

我需要阻止make UIAlertView。因为我有功能,我需要返回UIAlertView选项。但问题是在显示UIAlertView之后我的函数代码正在执行,所以我无法捕获UIAlertView选项(我可以在委托方法中执行,但我需要返回函数结果)。

我尝试使用UIAlertVIew进行NSCondition屏蔽。但是代码不起作用。

condition = [NSCondition new];
result = 0 ; 
[condition lock];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Fingerprint" message:@"test" delegate:window_self cancelButtonTitle:@"No" otherButtonTitles:@"Yes",nil];
[alert setDelegate:self];
[alert show];
while (result == 0) [condition wait];
[condition unlock] ;

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
 [condition lock] ;
 if (buttonIndex == 0)
 {
  result = 2; 
 }
 else if (buttonIndex == 1)
 {
  result = 3 ;
 }
 [condition signal] ;
 [condition unlock] ;
}

也许如何修复此代码或任何其他建议?感谢

5 个答案:

答案 0 :(得分:8)

没有办法实现你想要的。只有通过代表。你应该重新设计你的功能或拒绝使用UIAlertView

答案 1 :(得分:5)

这不会阻止它,但是我编写了一个子类来添加块样式语法,这使得处理buttonClickedAtIndex方法变得更加容易,而不必执行委托和一大堆if语句,如果你有多个UIAlertViews在一堂课。

#import <UIKit/UIKit.h>

@interface UIAlertViewBlock : UIAlertView<UIAlertViewDelegate>
- (id) initWithTitle:(NSString *)title message:(NSString *)message block: (void (^)(NSInteger buttonIndex))block
   cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... NS_AVAILABLE(10_6, 4_0);
@end


#import "UIAlertViewBlock.h"

@interface UIAlertViewBlock()
{
    void (^_block)(NSInteger);
}
@end

@implementation UIAlertViewBlock

- (id) initWithTitle:(NSString *)title message:(NSString *)message block: (void (^)(NSInteger buttonIndex))block
cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... NS_AVAILABLE(10_6, 4_0)
{
    if (self = [super initWithTitle:title message:message delegate:self cancelButtonTitle:cancelButtonTitle otherButtonTitles:otherButtonTitles, nil])
    {
        _block = block;
    }
    return self;
}

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

@end

然后在这里调用它是一些示例代码。另一个很酷的部分是,因为一个块关闭局部变量,我可以访问我显示UIAlertView时存在的所有状态。使用传统的委托方法,您必须将所有临时状态存储到类级变量中,以便在委托中对buttonClickedAtIndex的调用中访问它。这太清洁了。

{
    NSString *value = @"some random value";
    UIAlertViewBlock *b = [[UIAlertViewBlock alloc] initWithTitle:@"Title" message:@"Message" block:^(NSInteger buttonIndex)
        {
            if (buttonIndex == 0)
                NSLog(@"%@", [value stringByAppendingString: @" Cancel pressed"]);
            else if (buttonIndex == 1)
                NSLog(@"Other pressed");
            else
                NSLog(@"Something else pressed");
        }
        cancelButtonTitle:@"Cancel" otherButtonTitles:@"Other", nil];

    [b show];
}

答案 2 :(得分:2)

我刚遇到同样的问题。虽然没有解决方案,但我至少有2种解决方法。

循环&#34;解决方案&#34; 在调用UIAlert之后,您启动一​​个循环,查找对象的全局变量(而不是整个项目,请注意)变量是您在UIAlert委托中设置的变量。所以基本上你等待&#34; A == 1,如果不是DoEvents&#34;然后循环它。

然后在代表上,当你得到答案时,你将A = 1

之前有人说Cocoa中没有DoEvents:

void MyTestClass::DoEvents()
{

  NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
  NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
    untilDate:[NSDate distantPast]
    inMode:NSDefaultRunLoopMode
    dequeue:YES];
  if (event) {
    [NSApp sendEvent:event];
    [NSApp updateWindows];
  }
  [pool release];
}

代表解决方案 而不是在调用Alert的函数中使用处理答案A,B或C的代码,而是在委托本身中使用代码。

希望它有所帮助。 我在我的项目中使用了第二个,它起作用了。

答案 3 :(得分:1)

我偶然发现了这个问题,甚至通过发布这个问题进入Apple地狱,我特此声明这是一个概念证据:

@interface EvilShitClass () <UIAlertViewDelegate>
@end

@implementation EvilShitClass {
    BOOL _isCanceled, _wasYes;
}

以下是是/否查询的静态方法:

+ (BOOL)yesNoQueryWithTitle:(NSString*)title text:(NSString*)text {

    EvilShitClass *shit = [EvilShitClass new];
    UIAlertView *alertView = [UIAlertView new];
    alertView.delegate = shit;
    alertView.title = title;
    alertView.message = text;
    [alertView addButtonWithTitle:@"Yes"];
    [alertView addButtonWithTitle:@"No"];

    NSRunLoop *run_loop = [NSRunLoop currentRunLoop];

    [alertView show];

    while( !shit->_isCanceled ) {
        BOOL tmp = [run_loop runMode:NSDefaultRunLoopMode beforeDate:[NSDate date]];
    }

    return shit->_wasYes;
}

最后处理按钮点击和的委托方法 停止runloop处理:

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    _wasYes = (buttonIndex == 0);
    _isCanceled = YES;
}

这有效但记住:你不应该这样做:-D 相当请不要争论风格和东西,它只是一个5分钟快速黑客证明它可以做!这应该没有ARC(新的 - &gt; autorelease) 但如果我错了你知道如何处理它;)

免责声明:对于使用此代码段对您的应用程序或设备造成的任何可能的损害,我概不负责。谢谢。

答案 4 :(得分:1)

将UIAlertView与来自Joseph的块一起使用,并为其添加一个信号量。 声明全局信号量

dispatch_semaphore_t generateNotificationsSemaphore;

并在块处理程序中发出信号量信号

[alert showWithHandler:^(UIAlertView *alertView, NSInteger buttonIndex) {
    if (buttonIndex == [alertView cancelButtonIndex]) {

    } else {

    }

    dispatch_semaphore_signal(generateNotificationsSemaphore);
}];

调用showWithHandler后,使用信号量

添加一个等待循环
while (dispatch_semaphore_wait(generateNotificationsSemaphore, DISPATCH_TIME_NOW )) {
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:20]];

}

根据您的需要,您的实际超时值可能会有所不同。