0

my code snippet:

- (void)viewDidUnload{
    [super viewDidUnload];
    self.statusView = nil;
    self.tableView = nil;
    self.noDataView = nil;
}

In a rare situation, my app crashed in line self.noDataView = nil;. When I debug by po self, it seemed that it's pointing something other than current controller. What is possible reason?

PS:self.tableView's delegate and dataSource is set to self in init method. Does that have any relation to this?

Adi Inbar
  • 12,097
  • 13
  • 56
  • 69
naiyi1984
  • 3
  • 1
  • Don't implement viewDidUnload to nil out views... Apple has moved away from this method anyway. – mattyohe Sep 11 '13 at 03:51
  • These views are not created by NIB, are created by code in `init` or `loadView` method, then are added to `self.view` as subviews. – naiyi1984 Sep 11 '13 at 08:26

2 Answers2

1

First, [super viewDidUnload] should be used as the last statement. However, that won't fix your error, probably.

The reason for your problem is quite simple. Your controller is overreleased somewhere. Do you have zombie detection enabled? The code where the application crashes is usually irrelevant because the problem happened earlier.

Sulthan
  • 128,090
  • 22
  • 218
  • 270
  • I know the root reason is that `controller` is over released, but I can't find where this happened, because I used **ARC**. \r\nAnd I also understand `dangling point` won't bring destruction immediately, however I test many times and the debugger hang at the same code line position every time, the possibility of coincidence is little, I think. It is strange that not – naiyi1984 Sep 11 '13 at 11:19
  • It is strange that not every time App crash, it's rare, but sometimes it continuity crash and hang at same line `self.noDataView = nil;`, the line ahead of this used `self` too, but no error. – naiyi1984 Sep 11 '13 at 11:27
  • @naiyi1984 That's why I am telling you the problem is not in this code at all. The controller is already released and you get the crash when you try to overwrite memory that no longer belongs to you. Sometimes overwriting memory doesn't crash and sometimes it does. However, the problem is that your controller is overreleased. – Sulthan Sep 11 '13 at 11:51
  • Forget debugger and use instruments. – Sulthan Sep 14 '13 at 09:32
0

viewWillUnload is deprecated now, you can't count on it anymore, any question about it will lead you to the below references.

From Apple:

In iOS 6, the viewWillUnload and viewDidUnload methods of UIViewController are now deprecated. If you were using these methods to release data, use the didReceiveMemoryWarning method instead. You can also use this method to release references to the view controller’s view if it is not being used. You would need to test that the view is not in a window before doing this.

And Quote WWDC 2012:

The method viewWillUnload and viewDidUnload. We're not going to call them anymore. I mean, there's kind of a cost-benifit equation and analysis that we went through. In the early days, there was a real performance need for us to ensure that on memory warnings we unloaded views. There was all kinds of graphics and backing stores and so forth that would also get unloaded. We now unload those independently of the view, so it isn't that big of a deal for us for those to be unloaded, and there were so many bugs where there would be pointers into.

Edit: For your problem in iOS 5.1, viewDidUnload is used to release anything you have made when the view was created, so unless you are creating or retaining objects it in viewDidLoad or your nib, you may not release them in viewDidUnload.

Tarek Hallak
  • 18,422
  • 7
  • 59
  • 68
  • I know this method was deprecated from iOS6, but I get this crash in **iOS 5.1.1** which I think it should be still valid. – naiyi1984 Sep 11 '13 at 08:33
  • Are you initializing self.noDataView in `init` or `viewDidLoad`? and is it a `outelt`? – Tarek Hallak Sep 11 '13 at 08:55
  • Yes.I'm sure `self.noDataView` is correctly initialized. It is not a `outlet`. – naiyi1984 Sep 11 '13 at 11:13
  • No I am asking where do you initialize it? check my edit, if you are not initialize it in `viewDIdLoad` then don't release it in `viewDidUnload`, do it in `dealloc`. – Tarek Hallak Sep 11 '13 at 11:16
  • Oh,I init all these three view in `loadView` method, just after `[super loadView];` – naiyi1984 Sep 11 '13 at 11:31
  • From the apples doc: `If you use Interface Builder to create your views and initialize the view controller, you must not override this method.` so if you did put them in `viewDidLoad` instead, and I recommend to get `self.noDataView = nil;` out of viewDidUnload. – Tarek Hallak Sep 11 '13 at 11:37