28

After upgrading Xcode from Version 4 to 5 and therefore from iOS 6 to iOS 7 i get the following error:

'NSInvalidArgumentException', reason: 'Sheet can not be presented because the view is not in a window

in this line:

[actionSheet showInView:self.view];
Thorsten Niehues
  • 13,712
  • 22
  • 78
  • 113
  • Interesting. Among other iOS7 issues, I just encountered this one. However, rather than self.view I was using self.myOwnView. In the debugger, I have an object for both actionSheet and self.myOwnView, and the details seem right. So I really have no idea what the problem is. In my case, a selection in a collection view controller calls a method of its delegate (the main VC) to put up an actionsheet, where the user confirms the selection just made from the collectionview controller. – Victor Engel Oct 28 '13 at 03:42
  • I just had an idea. I think what may be happening is that I'm having the collectionview controller call the delegate to update information followed by another call to the delegate to dismiss the controller. The first call is the one that is presenting the action sheet. Probably I get the error because the collection view controller is still on screen. I'll try consolidating the two calls into one. That way, the controller should be off-screen, I think. – Victor Engel Oct 28 '13 at 04:51

9 Answers9

48

I literally just had this exact same problem and unfortunately I'm still not sure what the root cause of the problem is. However, you'll find my current solution below. If I make any progress on root causing the issue I'll let you know.

UIWindow* window = [[[UIApplication sharedApplication] delegate] window];
if ([window.subviews containsObject:self.view]) {
    [emailSheet showInView:self.view];
} else {
    [emailSheet showInView:window];
}
Idan
  • 9,880
  • 10
  • 47
  • 76
Jeremy Fox
  • 2,668
  • 1
  • 25
  • 26
  • 3
    This code returns nil for the window in my case. So I use `UIWindow* window = [[[UIApplication sharedApplication] delegate] window];` – Thorsten Niehues Sep 22 '13 at 20:08
  • And [here](http://stackoverflow.com/questions/3359501/uiapplication-sharedapplication-keywindow-is-nil) is the explanation for the nil window – Thorsten Niehues Sep 22 '13 at 20:11
  • Kindly let me know as soon as you get know any thing about its root issue – Mashhadi Sep 23 '13 at 07:38
  • Hmmm. In my case (see my previous comment), I don't think this would work. In the debugger, if I query the keyWindow, I get the collection view wrapper. I don't want that. I want a view in the delegate's view hierarchy. The delegate is set correctly, and the view looks right. In fact, this function worked before. – Victor Engel Oct 28 '13 at 03:51
  • I just noticed this in the help text: "Generally, if you want to present an action sheet in an iPad application, you should use the showFromRect:inView:animated: method to display the action sheet instead.". My app is a universal app, but this function is in an iPad-only portion of the code. I guess I'll try this, although I don't see why it would be better. – Victor Engel Oct 28 '13 at 04:02
  • Why not `if (self.view.window)...`? Isn't it more mistake proof? – Aviel Gross May 22 '14 at 21:04
11

I got the same problem. In my code, the reason obviously was that I wanted to show an action sheet in viewWillAppear:. After moving the code to viewDidAppear:, the error was gone.

Reinhard Männer
  • 14,022
  • 5
  • 54
  • 116
  • 2
    This is probably the real issue. Can't present an action sheet before the view has appeared. – DanM Jan 17 '14 at 20:18
  • This should be the accepted answer; the behaviour in `viewWillAppear:`, `viewDidLoad:` was tolerated in <= iOS6 but breaks in iOS7. – lucasart Mar 06 '14 at 06:54
  • 1
    In my case I was getting this error AFTER the view was fully initialized and displayed on screen (viewDidAppear). I was presenting an action sheet based on user interaction and still getting this error. So this solution wouldn't have made any difference in my case. – Jeremy Fox Mar 06 '14 at 17:56
7

I don't know what is the root cause of the problem is, but I found a solution which is working for me. In place of self.view, place this line:

[[[[UIApplication sharedApplication] keyWindow] subviews] lastObject]

for example:

[actionSheet showInView:[[[[UIApplication sharedApplication] keyWindow] subviews] lastObject]];
2

I had the same problem and in my case this happened when I tried to show an ActionSheet on my self.view while my self.view was presenting another viewController.

This is the crash: "Sheet can not be presented because the view is not in a window"

example for the problem:

[modalViewController dismissModalViewControllerAnimated:YES];
[actionSheet showInView:self.view];

I solved the problem by waiting for the modalViewController to dismiss and then show the ActionSheet.

Solution:

[modalViewController dismissModalViewControllerAnimated:YES];
[actionSheet performSelector:@selector(showInView:) withObject:self.view afterDelay:0.6];

Hope this helps a lot of people :)

Refael.S
  • 1,634
  • 1
  • 12
  • 22
2

I had the same issue [actionSheet showInView:self.view]; and I solved it with [actionSheet showInView:[UIApplication sharedApplication].keyWindow];.

Perhaps the problem is related to the paragraph of the Apple documentation:

Subclassing Notes:

UIActionSheet is not designed to be subclassed, nor should you add views to its hierarchy. If you need to present a sheet with more customization than provided by the UIActionSheet API, you can create your own and present it modally with presentViewController:animated:completion:.

David Cain
  • 16,484
  • 14
  • 65
  • 75
omi5489
  • 381
  • 3
  • 8
1

In my case this happens when a viewcontroller that has just been pushed onto the stack decides it wants to show an alert sheet. But, apparently the viewcontroller is not yet entirely ready to do that right after it is pushed. I use [actionSheet showInView:self.parentViewController.view]; instead of [actionSheet showInView:self.view];.

RickJansen
  • 1,615
  • 18
  • 24
1

I had a similar problem with a toolbar and it should be better always to check if the passed view to the selector showInView has a window not nil. For example:

if (self.view.window)
    [actionSheet showInView:self.view];

In this way, we can avoid annoying exceptions. Then, according to your application layout, you should search a valid view to show the action sheet. If your app has a tabbar or a toolbar, it should be better to use

- (void)showFromToolbar:(UIToolbar *)view;
- (void)showFromTabBar:(UITabBar *)view;
1

I have previously used

- (void)showFromTabBar:(UITabBar *)view;

and hit a similar problem with one of my controllers (I have a utility method that handles showing action sheets from various controllers) as it sets

hidesBottomBarWhenPushed = YES;

With iOS 7 this now appears to set window to nil on the tabBar causing the error mentioned. My workaround is to check the window property of the tabBar and if nil call

if (nil == tabBar.window) {
    [actionSheet showInView:self.window];
}
else {
    [actionSheet showFromTabBar:tabBar];
}
David Knight
  • 763
  • 6
  • 12
0

In iOS 7, the view send to the showInView: should be the part of the view hierarchy. It should be added as the subview of some view.
You can check whether some view can be used in showInView: by checking whether the view.window is nil or not.
view.superview should also be non-nil

Udit Agarwal
  • 868
  • 9
  • 22