closuresios 7中的UIAlertView无法正常工作?

我想解雇一个UIAlertView之前显示另一个,我在这里find答案: iOS解雇UIAlertView显示另一个

问题是,这不适用于iOS7,但适用于iOS6。

这是在iOS6中工作

-(void)closePreviousAlert{ for (UIWindow* w in [UIApplication sharedApplication].windows) for (NSObject* o in w.subviews) if ([o isKindOfClass:[UIAlertView class]]) [(UIAlertView*)o dismissWithClickedButtonIndex:[(UIAlertView*)o cancelButtonIndex] animated:YES]; } 

有没有另一种解决scheme呢?

而不是使用你的O(n ^ 2)方法来closures警报,它可能会更轻量级(和iOS 7有效)为您的警报创build私有属性,并通过他们的合成获得者引用和解雇他们。 此外,我不时在alertview上设置一个标签,并通过它的标签引用它作为一个快速和肮脏的解决scheme。

如果这些解决scheme中的任何一个对于您的应用程序的上下文都太简单,我可能会build议您重新考虑使用alertview。 太多的应用程序滥用alertviews,在我看来,他们应该非常谨慎地使用 – 只是添加一些不请自来的反馈:)。

一个可以帮助你的不同方法是在完成alertview的生命周期时实现一个基于块的callback。 请参阅使用块简化UIAlertView 。

您的代码在iOS7中无效,因为[UIApplication sharedApplication].windows没有引用UIAlertView因为UIAlertView本身从未添加到iOS7的任何窗口。

你需要继续参考你的actionSheet,这是你可以做的最好的事情。

你可以通过参考https://stackoverflow.com/a/19275311/1262634来做到这一点:

 Class UIAlertManager = NSClassFromString(@"_UIAlertManager"); UIAlertView *alertView = [UIAlertManager performSelector:@selector(topMostAlert)]; 

编辑 :这是一个私人API。

另一种跟踪可见UIAlertView实例的方法可以通过使用方法swizzling:

UIAlertView中+ Dismiss.h:

 #import <UIKit/UIKit.h> @interface UIAlertView (Dismiss) + (void)dismissAllVisibleAlertViews; @end 

UIAlertView中+ Dismiss.m:

 #import "UIAlertView+Dismiss.h" #import <objc/runtime.h> // see http://nshipster.com/method-swizzling/ static inline void swizzle(Class class, SEL originalSelector, SEL swizzledSelector) { Method originalMethod = class_getInstanceMethod(class, originalSelector); Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)); if (didAddMethod) { class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); } else { method_exchangeImplementations(originalMethod, swizzledMethod); } } @implementation UIAlertView (Dismiss) + (void)load { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ swizzle([self class], @selector(show), @selector(xxx_show)); swizzle([self class], @selector(dismissWithClickedButtonIndex:animated:), @selector(xxx_dismissWithClickedButtonIndex:animated:)); }); } + (void)dismissAllVisibleAlertViews { for (NSValue *value in [self visibleAlertViews]) { id val = value.nonretainedObjectValue; if ([val isKindOfClass: [UIAlertView class]]) { [val dismissWithClickedButtonIndex: 0 animated: YES]; } } } #pragma mark - Method Swizzling - (void)xxx_show { [self xxx_show]; [[self.class visibleAlertViews] addObject: [NSValue valueWithNonretainedObject: self]]; } - (void)xxx_dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated { [self xxx_dismissWithClickedButtonIndex: buttonIndex animated: animated]; [[self.class visibleAlertViews] removeObject: [NSValue valueWithNonretainedObject: self]]; } #pragma mark - Cache + (NSMutableSet *)visibleAlertViews { static NSMutableSet *views = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ views = [NSMutableSet new]; }); return views; } @end 

这是因为通过调用show方法show UIAlertViews 。 然后用swizzled方法跟踪实例,直到通过dismissWithClickedButtonIndex:animated:方法被解散。 然后,您可以通过调用[UIAlertView dismissAllVisibleAlertViews];轻松解除所有警报视图[UIAlertView dismissAllVisibleAlertViews];

Xcode 6.4,对于iOS8.4,启用ARC

这个主题有很多post。 我似乎没有一个明确的解决scheme,所以我花了几个小时的时间进行testing,并最终提出了解决OP问题的解决scheme:

“我试图在显示另一个之前解除UIAlertView …”

由于OP声明".windows"方法将不再起作用。 还有一些其他的方法,我已经阅读了涉及创build一个类别UIAlertView和其他人使用通知; 不过,对我来说太复杂了。

这是做什么…

1)使你的课程符合UIAlertViewDelegate。

在你的class级的“* .h”文件中…

 @interface YourViewController : UIViewController <UIAlertViewDelegate> 

这将允许类中的UIAlertView对象向以下方法发送消息:

 - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex 

并为您的类中的UIAlertView对象接收来自以下方法的消息:

 - (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated: 

一个智者的话,你不必,在某些情况下,你的class符合UIAlertViewDelegate,但它是更安全的select。 这一切都取决于你将如何在课堂上使用你的对象。

2)将UIAlertView objet声明为类variables或属性。

创build属性的一些好处是你可以访问对象的一些getter和setter。

作为实例variables,在你的类的“* .h”文件中…

 @interface YourViewController : UIViewController <UIAlertViewDelegate> { UIAlertView *yourAlertView; { //other properties @end 

作为属性(推荐)在你的class级的“* .h”文件中…

 @interface YourViewController : UIViewController <UIAlertViewDelegate> { //other instance variables { @property (strong, nonatomic) UIAlertView *yourAlertView; @end 

3)避免生成对你的UIAlertView对象的多个引用。

例如,如果您有监视某个条件并显示警报的方法,则不要每次都立即对UIAlertView对象进行实例化。 而是在-(void)viewDidLoad实例化一次,并在需要的地方使用它。 否则,这将阻止

 - (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated: 

方法将所需的消息发送到正确的UIAlertView对象。

4)将标签分配给UIAlertView对象并操作属性以更改标题,消息等

 self.yourAlertView.title = @"some title string"; self.yourAlertView.message = @"some message string"; 

5)显示UIAlertView对象。

 [self.yourAlertView show]; 

6)在显示更改的UIAlertView对象之前closures。

 self.yourAlertView.title = @"some other title string"; self.yourAlertView.message = @"some other message string"; [self.yourAlertView show]; 

7)UIAlertView在iOS8中折旧。

https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UIAlertView_Class/index.html#//apple_ref/doc/uid/TP40006802-CH3-SW8

重要提示:UIAlertView在iOS 8中已弃用。(请注意,UIAlertViewDelegate也被弃用。)要在iOS 8及更高版本中创build和pipe理警报,请使用带有UIAlertControllerStyleAlert的preferredStyle的UIAlertController。

在iOS 8以前版本的iOS中运行的应用程序中,使用UIAlertView类向用户显示警报消息。 警报视图function与操作表(UIActionSheet的一个实例)function相似但外观不同。

使用此类中定义的属性和方法来设置警报视图的标题,消息和委托并configurationbutton。 如果您添加自定义button,则必须设置委托。 该委托应符合UIAlertViewDelegate协议。 使用show方法在configuration完成后显示警报视图。

我有同样的问题,我不想保存所有可能的警报视图作为属性。 我在这里find一个很好的select:

 UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Alert!" message:@"This alert will dismiss when application resigns active!" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillResignActiveNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notification){ [alert dismissWithClickedButtonIndex:0 animated:NO]; }]; 

在同一个线程中,作为对其中一个post的评论,有一个解释为什么旧的方法在iOS 7中不起作用:

在iOS7中,Windows不包含警报视图窗口。 他们是由另一堆未被暴露的窗口pipe理的。

希望它可以帮助别人。 🙂

代码closures所有警报视图。 这是PRIVATE API,因此上传到Appstore时,您的应用可能会被Apple拒绝:

 Class UIAlertManager = objc_getClass("_UIAlertManager"); UIAlertView *topMostAlert = [UIAlertManager performSelector:@selector(topMostAlert)]; while (topMostAlert) { [topMostAlert dismissWithClickedButtonIndex:0 animated:NO]; topMostAlert = [UIAlertManager performSelector:@selector(topMostAlert)]; }