user4951
user4951

Reputation: 33090

How to fix the bug where viewDidScroll is called when UIViewController is already gone?

I often got excbadaccess. Very rare. But sometimes it happens.

I tried zombie build and I got this:

*** -[BGDetailBusinessViewController scrollViewDidScroll:]: message sent to deallocated instance 0x189f09c0

I suppose it happens due to the following

I pop out a BGDetailBusinessViewController while scrolling.

The view is still scrolling.

It sent notification somewhere to call it's delegate, namely the BGDetailBusinessViewController object. Because reference to delegate is weak, I suppose this what causes the problem.

Now, how exactly I can fix that?

The way weak reference work is if the object is deallocated it'll be nil right?

Perhaps it's not nil due to the zombie. However, that means this bug will show up if I build with zombie build.

If an object becomes zombie, will all weak reference to that object nilled?

In any case, I wonder how to fix this bug given that I have manage to found it.

Some says that I should set delegate to nil in dealloc.

Are all weak references nilled if we enable zombie object? suggest otherwise. When an object is deallocated, all weak references, such delegate should have been nilled.

Actually I really couldn't think of any reason why, with zombie or not, accessing deallocated object can happen at all. If a reference is strong, then object is not deallocated. If reference is weak then it's nilled when object is deallocated.

Yet, the app did crash with error: message sent to deallocated instance 0x189f09c0

Upvotes: 1

Views: 447

Answers (2)

AlexDenisov
AlexDenisov

Reputation: 4117

Have you tried to unsubscribe from scrollView 'notifications'?

- (void)dealloc
{
    self.scrollView.delegate = nil; // or tableView, collectionView, etc.
}

Upvotes: 3

slecorne
slecorne

Reputation: 1718

You have to set the delegate to nil in the dealloc method using

scrollView.delegate = nil;

A deallocated object is deallocated (and removed from memory) but not set to nil. You have to explicitly set it to nil.

Upvotes: 5

Related Questions