很多情况下,我们需要将其它控件产生的window 隐藏,这几天做项目的时候发现,当自己打开一个带有winodw的控件,然后收到一下抢登消息,自己的app回到了首页,但是这个window还在,因此需要隐藏它。
注意点
- UIAlertView 与 UIActionSheet无法从UIApplication.sharedApplication.windows取得。
- 既然要隐藏window 级别是Normal的自然不能隐藏。
方案
为了全局取到 UIAlertView 和 UIActionSheet Hook它们的show方法。或者直接用方法替换的方式,将自定义方法与show方法替换,起到存储的作用。
做个判断即可。
实现
我这里因为工程里已经集成了Aspects所以就用hook的方式
UIActionSheet
+ (void)load
{
id sheetShowInViewHook = ^(id<AspectInfo> aspectInfo) {
if ([aspectInfo.instance isKindOfClass:[UIActionSheet class]]){
UIActionSheet *sheet = aspectInfo.instance;
[UIWindow saveAlertOrSheetView:sheet];
}
};
[self aspect_hookSelector:@selector(showInView:)
withOptions:AspectPositionAfter
usingBlock:sheetShowInViewHook
error:nil];
}
UIAlertView
+ (void)load
{
id alertShowHook = ^(id<AspectInfo> aspectInfo) {
if ([aspectInfo.instance isKindOfClass:[UIAlertView class]]){
UIAlertView *alertView = aspectInfo.instance;
[UIWindow saveAlertOrSheetView:alertView];
}
};
[self aspect_hookSelector:@selector(show)
withOptions:AspectPositionAfter
usingBlock:alertShowHook
error:nil];
}
为了使用方便,就直接给window定一个分类
==这里用NSHashTable 防止重复储存==
static NSHashTable *viewTable;
+ (void)load
{
viewTable = [NSHashTable weakObjectsHashTable];
}
+ (void)saveAlertOrSheetView:(UIView *)view
{
[viewTable addObject:view];
}
+ (void)hideAllWindowsExceptNormal
{
for (UIWindow *window in UIApplication.sharedApplication.windows) {
BOOL windowLevelNormal = (window.windowLevel != UIWindowLevelNormal);
if(windowLevelNormal) {
[window setHidden:YES];
}
}
for (UIView *view in viewTable) {
if ([view isKindOfClass:[UIAlertView class]]) {
UIAlertView *alertView = view;
[alertView dismissWithClickedButtonIndex:alertView.cancelButtonIndex animated:NO];
}
if ([view isKindOfClass:[UIActionSheet class]]) {
UIActionSheet *acitonSheet = view;
[acitonSheet dismissWithClickedButtonIndex:acitonSheet.cancelButtonIndex animated:NO];
}
}
}