This can happen if the view controller is being presented after iOS queues a rotate event, but before the rotate event is handled. From observation, I think rotate events are specific to the view controllers currently being presented.
This is a helpful way of thinking of it:
- The rotate event is queued up by iOS for the top view controller, A.
- Your code presents a view controller, B.
- The rotate event is dequeued, but it addresses only view controller A.
Thankfully, there's a really easy fix. Just assume there's a rotate event in the event queue, and make sure your view is actually presented after it. You do this by queuing the presentation of your new view controller, rather than presenting it directly. Blocks queued to the main queue will be executed after any events already queued (like rotate events) but before the user gets a chance to interact with your UI.
Change:
[self performSegueWithIdentifier: @"firstRun" sender: self];
To:
dispatch_async(dispatch_get_main_queue(), ^{
[self performSegueWithIdentifier: @"firstRun" sender: self];
});
After doing this, you get this behaviour instead:
- The rotate event is queued up by iOS for the top view controller, A.
- Your code schedules the block that will present the new view controller.
- The rotate event is dequeued, but it addresses only view controller A.
- The new view controller, B, is presented by your block. It gets the new orientation.