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中折旧。
重要提示: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)]; }