0

I placed a UIActivityIndicatorView in my nav bar by doing the following.

in the .h file

@property (strong, nonatomic) UIActivityIndicatorView *mySpinner;

in the .m file

- (void)viewDidLoad
{
    [super viewDidLoad];

    _mySpinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
    _mySpinner.translatesAutoresizingMaskIntoConstraints = NO;
    _mySpinner.hidesWhenStopped = YES; 
    UIBarButtonItem *spinnerButton = [[UIBarButtonItem alloc] initWithCustomView:_mySpinner];
    self.navigationItem.rightBarButtonItem = spinnerButton;
    [_mySpinner startAnimating];

    //some other stuff
}

This worked great for both iOS 7 and iOS 8, the only two systems I am targeting. The App went to Apple for review, passed and is now on the App Store. So I download it onto one of my phones (running iOS 8) from the store at it works, download it to another phone running iOS 7 and it crashes when I go to the screen with the UIActivityIndicatorView. I boot back up Xcode and run the App in release mode and was able to make it crash again. This is the message.

Assertion failure in -[UINavigationBar layoutSublayersOfLayer:]

and this

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Auto Layout still required after executing -layoutSubviews. UINavigationBar's implementation of -layoutSubviews needs to call super.'

I have tried to call layoutSublayersOfLayer, but that did not work. I also tried to use Auto Layout on the UIActivityIndicatorView, but that told me that I can't put constraints on this yet, because the view is not ready.

However, if I make a fresh project and run it, the UIActivityIndicatorView works, just like it did before I submitted my App. I even ran the test in release mode as well. I have deleted derived data, clean, build, restart, reboot. But now, in iOS 7 the app will always crash if I add the UIActivityIndicatorView. Does anyone have any insight as to what is happening? I have pretty much deleted everything from the viewDidLoad method to see if it was something else causing it, to no avail. Any help would be appreciated. Right now I am using an if then statement to check if the iOS is 7 or 8, if 8 I add the Indicator, but I really don't want to do that. Thanks!!

I see my question is very similar to THIS one, but that does not have any answers or comments.

Community
  • 1
  • 1
Douglas
  • 2,524
  • 3
  • 29
  • 44
  • Is your UINavigationBar or your spinner or your button bar indeed an instance of a subclass that overrides layoutSubviews? – RobP Feb 20 '15 at 21:58
  • @RobP, not that I am aware. The UINavigationBar is just the normal bar and the spinner was created in the header file, no subclassing at all. – Douglas Feb 20 '15 at 22:19
  • `_mySpinner.translatesAutoresizingMaskIntoConstraints = NO;` Why do this? It seems like you're telling the system to use autolayout, and then not actually laying it out. I bet if you remove this line it'll just work. Also, if you set a frame on it after removing this line it'll give you a little more predictable behavior when you put it in the nav bar. – Stakenborg Feb 20 '15 at 23:02
  • @Stakenborg, well that worked!! I thought I had to set translates to NO so that it would use AutoLayout. Guess I got that one backwards. Write that down as an answer and I will accept. Thanks for your time!! – Douglas Feb 20 '15 at 23:45

1 Answers1

1

If you're going to use initWithCustomView: with UIBarButtonItem for navigation controller bar button items, you should either allow it to set it's own constraints (by NOT setting translatesAutoresizingMaskIntoConstraints = NO), or you have to lay it out yourself.

In most cases, autolayout can be done on the subviews of the view you're going to use as the custom view for the button, and then you can just allow the containing view to expand as necessary by not setting translatesAutoresizingMaskIntoConstraints = NO.

Stakenborg
  • 2,890
  • 2
  • 24
  • 30