Fixed: Memory leak in CPTableView, CPScrollView

Prevously, when removing a CPTableView or a CPScrollView, the CPNotificationCenter kept a reference of these observers in the notification center.

Now, the CPNotificationCenter does only have a observer when necessary.
This commit is contained in:
Alexandre Wilhelm
2014-11-25 17:33:17 -08:00
parent d5b4d66272
commit b36cc8f1e9
3 changed files with 101 additions and 45 deletions
+7 -4
View File
@@ -62,6 +62,9 @@
- (void)_observeDocumentView
{
if (!_documentView)
return;
var defaultCenter = [CPNotificationCenter defaultCenter];
[_documentView setPostsFrameChangedNotifications:YES];
@@ -87,15 +90,15 @@
[defaultCenter
removeObserver:self
name:CPViewFrameDidChangeNotification
object:_documentView];
object:aDocumentView];
[defaultCenter
removeObserver:self
name:CPViewBoundsDidChangeNotification
object:_documentView];
object:aDocumentView];
}
- (void)_addObservers
/*- (void)_addObservers
{
if (_isObserving)
return;
@@ -115,7 +118,7 @@
if (_documentView)
[self _removeObserverDocumentView:_documentView];
}
}*/
/*!
Returns the document view.
+31 -5
View File
@@ -264,11 +264,6 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
_delegate = nil;
_scrollTimer = nil;
_implementedDelegateMethods = 0;
[[CPNotificationCenter defaultCenter] addObserver:self
selector:@selector(_didReceiveDefaultStyleChange:)
name:CPScrollerStyleGlobalChangeNotification
object:nil];
}
return self;
@@ -1270,6 +1265,37 @@ Notifies the delegate when the scroll view has finished scrolling.
#pragma mark -
#pragma mark Overrides
- (void)_removeObservers
{
if (!_isObserving)
return;
[[CPNotificationCenter defaultCenter] removeObserver:self
name:CPScrollerStyleGlobalChangeNotification
object:nil];
[super _removeObservers];
}
- (void)_addObservers
{
if (_isObserving)
return;
//Make sure to have the last global style for the scroller
[self _didReceiveDefaultStyleChange:nil];
[[CPNotificationCenter defaultCenter] addObserver:self
selector:@selector(_didReceiveDefaultStyleChange:)
name:CPScrollerStyleGlobalChangeNotification
object:nil];
[super _addObservers];
}
- (void)drawRect:(CGRect)aRect
{
[super drawRect:aRect];
+63 -36
View File
@@ -320,6 +320,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
CPTableColumn _draggedColumn;
CPArray _differedColumnDataToRemove;
CPView _observedClipView;
}
/*!
@@ -4454,41 +4456,15 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
*/
- (void)viewWillMoveToSuperview:(CPView)aView
{
[super viewWillMoveToSuperview:aView];
var superview = [self superview],
defaultCenter = [CPNotificationCenter defaultCenter];
if (superview)
{
[defaultCenter
removeObserver:self
name:CPViewFrameDidChangeNotification
object:superview];
[defaultCenter
removeObserver:self
name:CPViewBoundsDidChangeNotification
object:superview];
}
if ([aView isKindOfClass:[CPClipView class]])
_observedClipView = aView;
else
{
[aView setPostsFrameChangedNotifications:YES];
[aView setPostsBoundsChangedNotifications:YES];
[defaultCenter
addObserver:self
selector:@selector(superviewFrameChanged:)
name:CPViewFrameDidChangeNotification
object:aView];
[defaultCenter
addObserver:self
selector:@selector(superviewBoundsChanged:)
name:CPViewBoundsDidChangeNotification
object:aView];
[self _stopObservingClipView];
_observedClipView = nil;
}
[super viewWillMoveToSuperview:aView];
}
/*!
@@ -5138,8 +5114,8 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
if (!_isObserving)
return;
[self _stopObservingClipView];
[super _removeObservers];
[self _stopObservingFirstResponder];
}
- (void)_addObservers
@@ -5147,13 +5123,64 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
if (_isObserving)
return;
[self _startObservingClipView];
[super _addObservers];
[self _startObservingFirstResponder];
}
- (void)_startObservingFirstResponder
/*!
Called when the receiver is about to be moved to a new window.
@param aWindow the window to which the receiver will be moved.
*/
- (void)viewWillMoveToWindow:(CPWindow)aWindow
{
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_firstResponderDidChange:) name:_CPWindowDidChangeFirstResponderNotification object:[self window]];
[super viewWillMoveToWindow:aWindow];
[self _stopObservingFirstResponder];
if (aWindow)
[self _startObservingFirstResponderForWindow:aWindow];
}
- (void)_startObservingClipView
{
if (!_observedClipView)
return;
var defaultCenter = [CPNotificationCenter defaultCenter];
[_observedClipView setPostsFrameChangedNotifications:YES];
[_observedClipView setPostsBoundsChangedNotifications:YES];
[defaultCenter addObserver:self
selector:@selector(superviewFrameChanged:)
name:CPViewFrameDidChangeNotification
object:_observedClipView];
[defaultCenter addObserver:self
selector:@selector(superviewBoundsChanged:)
name:CPViewBoundsDidChangeNotification
object:_observedClipView];
}
- (void)_stopObservingClipView
{
if (!_observedClipView)
return;
var defaultCenter = [CPNotificationCenter defaultCenter];
[defaultCenter removeObserver:self
name:CPViewFrameDidChangeNotification
object:_observedClipView];
[defaultCenter removeObserver:self
name:CPViewBoundsDidChangeNotification
object:_observedClipView];
}
- (void)_startObservingFirstResponderForWindow:(CPWindow)aWindow
{
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_firstResponderDidChange:) name:_CPWindowDidChangeFirstResponderNotification object:aWindow];
}
- (void)_stopObservingFirstResponder