1

Is there a way to know that a view controller is somewhere in the view controller lifecycle between -viewWillAppear and -viewWillDisappear?

I ask because I want to be damned sure that a method isn't fired when my view is either not on screen, or is about to disappear from the screen. When the view is about to disappear from the screen, certain objects which I cannot explicitly check at runtime may or may not be deallocated, so, obviously, interacting with them can lead to message sent to deallocated instance errors.

At present, I'm keeping track with a BOOL, like so:

- (void)viewWillAppear:(BOOL)animated {
    isOnScreen = YES;
    [super viewWillAppear:animated];
}

- (void)willWillDisappear:(BOOL)animated {
    isOnScreen = NO;
    [super viewWillAppear:animated];
}

And my method looks like this:

if (isOnScreen) [self doSomething];

Is there a simpler way to do this?

David Foster
  • 3,824
  • 4
  • 25
  • 28
  • David, why do you use a timer to select the annotation rather than select it immediately? – Itay Aug 10 '10 at 23:59
  • Because the annotations are animating their dropping, meaning if one selects an annotation immediately, its call out is visible as it drops onto the map. Looks a little weird, imho! – David Foster Aug 11 '10 at 06:06
  • I agree. You can do the selection in `mapView:didAddAnnotationViews:` - just set a boolean saying it needs to select the first one, and then once they're added, they'll get selected. (I had a similar problem) – Itay Aug 11 '10 at 18:23
  • `mapView:didAddAnnotationViews:` is precisely where I'm starting the `NSTimer`. Unfortunately `mapView:didAddAnnotationViews:` triggers before the animation is complete – roughly a third of a second before, by my calculations. According to the documentation, `mapView:didAddAnnotationViews:` "Tells the delegate that one or more annotation views were added to the map." Unfortunately it doesn't delay if you're animating the drop. – David Foster Aug 11 '10 at 22:10
  • Here's an SO answer relating directly to what we're discussing: http://stackoverflow.com/questions/1256875/wanted-how-to-reliably-consistently-select-an-mkmapview-annotation/2269821#2269821. As you'll notice, that fellow solved the problem exactly as I have. Unfortunately, by the looks of things, his code crashes if the map appears and is then swiftly deallocated. This is exactly what I'm trying to prevent with the code above. – David Foster Aug 11 '10 at 22:15
  • I think there are two separate issues. The issue described in the SO answer you linked above is resolved by what I said - doing a select on an annotation view in `mapView:didAddAnnotationViews:` is robust. However, you're trying to solve a problem where you don't want the selection to happen while the annotation view is still dropping. For that, I don't have a better suggestion than what you're already doing. Sorry :) – Itay Aug 12 '10 at 00:13
  • I do appreciate all your comments Itay. :) – David Foster Aug 12 '10 at 12:22

2 Answers2

1

your way seems to be the simplest approach, if not the most robust. (simply checking if that instance of the view exists seems like the correct approach (if it hasn't been dealloced yet)).

I also don't REALLY understand the purpose of this, unless you have another view controller running methods that pertain to the view controller being showed that you are using the boolean for. In that case, its more a design problem than an upkeep problem.

Jesse Naugher
  • 9,780
  • 1
  • 41
  • 56
  • I can appreciate that the way I have described this could lead anyone to believe I have serious design problems. Basically, I have an MKMapView which automatically selects the first annotation after a second using an NSTimer. The problem is a lot of stuff can happen in that second, including the view being removed from screen or entirely deallocated. Unfortunately, calling `invalidate` on the NSTimer when the view disappears is not robust enough, because very occasionally the NSTimer will fire a split second before, leading to `message sent to deallocated instance`. – David Foster Aug 10 '10 at 22:21
  • ah i see, well it seems you've exhausted the other possibilities, and your way seems like a good solution to me. – Jesse Naugher Aug 10 '10 at 22:22
0

Use viewDidDisappear

- (void)viewDidDisappear:(BOOL)animated {
    // Do stuff that has to be done when this view is off screen.
}
coneybeare
  • 33,113
  • 21
  • 131
  • 183
  • I'm afraid I may have been unclear. I don't want to do stuff when the view is off screen, I want to do stuff when the view is on screen or is not about to be removed from the screen. For this reason, I'm setting `isOnScreen` true when the view controller will appear (the `doSomething` method is okay to be called) and setting it false when the view controller will disappear (the method can no longer be called until the view is about to reappear). – David Foster Aug 10 '10 at 21:54