mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-06 14:25:04 +00:00
Fix retain cycles in ASDisplayNode and ASTableView
This commit is contained in:
parent
f83f113493
commit
41c3289a11
@ -120,6 +120,7 @@
|
|||||||
058D0A84195D060300B7D73C /* ASDisplayNodeExtraIvars.h in Headers */ = {isa = PBXBuildFile; fileRef = 058D0A45195D058D00B7D73C /* ASDisplayNodeExtraIvars.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
058D0A84195D060300B7D73C /* ASDisplayNodeExtraIvars.h in Headers */ = {isa = PBXBuildFile; fileRef = 058D0A45195D058D00B7D73C /* ASDisplayNodeExtraIvars.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
05A6D05A19D0EB64002DD95E /* ASDealloc2MainObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 05A6D05819D0EB64002DD95E /* ASDealloc2MainObject.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
05A6D05A19D0EB64002DD95E /* ASDealloc2MainObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 05A6D05819D0EB64002DD95E /* ASDealloc2MainObject.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
05A6D05B19D0EB64002DD95E /* ASDealloc2MainObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 05A6D05919D0EB64002DD95E /* ASDealloc2MainObject.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
05A6D05B19D0EB64002DD95E /* ASDealloc2MainObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 05A6D05919D0EB64002DD95E /* ASDealloc2MainObject.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
||||||
|
3C9C128519E616EF00E942A0 /* ASTableViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C9C128419E616EF00E942A0 /* ASTableViewTests.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
||||||
6BDC61F61979037800E50D21 /* AsyncDisplayKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 6BDC61F51978FEA400E50D21 /* AsyncDisplayKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
6BDC61F61979037800E50D21 /* AsyncDisplayKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 6BDC61F51978FEA400E50D21 /* AsyncDisplayKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
DB7121BCD50849C498C886FB /* libPods-AsyncDisplayKitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EFA731F0396842FF8AB635EE /* libPods-AsyncDisplayKitTests.a */; };
|
DB7121BCD50849C498C886FB /* libPods-AsyncDisplayKitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EFA731F0396842FF8AB635EE /* libPods-AsyncDisplayKitTests.a */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
@ -238,6 +239,7 @@
|
|||||||
058D0A45195D058D00B7D73C /* ASDisplayNodeExtraIvars.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASDisplayNodeExtraIvars.h; sourceTree = "<group>"; };
|
058D0A45195D058D00B7D73C /* ASDisplayNodeExtraIvars.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASDisplayNodeExtraIvars.h; sourceTree = "<group>"; };
|
||||||
05A6D05819D0EB64002DD95E /* ASDealloc2MainObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASDealloc2MainObject.h; path = ../Details/ASDealloc2MainObject.h; sourceTree = "<group>"; };
|
05A6D05819D0EB64002DD95E /* ASDealloc2MainObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASDealloc2MainObject.h; path = ../Details/ASDealloc2MainObject.h; sourceTree = "<group>"; };
|
||||||
05A6D05919D0EB64002DD95E /* ASDealloc2MainObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASDealloc2MainObject.m; path = ../Details/ASDealloc2MainObject.m; sourceTree = "<group>"; };
|
05A6D05919D0EB64002DD95E /* ASDealloc2MainObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASDealloc2MainObject.m; path = ../Details/ASDealloc2MainObject.m; sourceTree = "<group>"; };
|
||||||
|
3C9C128419E616EF00E942A0 /* ASTableViewTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTableViewTests.m; sourceTree = "<group>"; };
|
||||||
6BDC61F51978FEA400E50D21 /* AsyncDisplayKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AsyncDisplayKit.h; sourceTree = "<group>"; };
|
6BDC61F51978FEA400E50D21 /* AsyncDisplayKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AsyncDisplayKit.h; sourceTree = "<group>"; };
|
||||||
EFA731F0396842FF8AB635EE /* libPods-AsyncDisplayKitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AsyncDisplayKitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
EFA731F0396842FF8AB635EE /* libPods-AsyncDisplayKitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AsyncDisplayKitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
FAD7085290B84183BD13BA1A /* Pods-AsyncDisplayKitTests.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AsyncDisplayKitTests.xcconfig"; path = "Pods/Pods-AsyncDisplayKitTests.xcconfig"; sourceTree = "<group>"; };
|
FAD7085290B84183BD13BA1A /* Pods-AsyncDisplayKitTests.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AsyncDisplayKitTests.xcconfig"; path = "Pods/Pods-AsyncDisplayKitTests.xcconfig"; sourceTree = "<group>"; };
|
||||||
@ -344,6 +346,7 @@
|
|||||||
058D0A30195D057000B7D73C /* ASDisplayNodeTestsHelper.h */,
|
058D0A30195D057000B7D73C /* ASDisplayNodeTestsHelper.h */,
|
||||||
058D0A31195D057000B7D73C /* ASDisplayNodeTestsHelper.m */,
|
058D0A31195D057000B7D73C /* ASDisplayNodeTestsHelper.m */,
|
||||||
058D0A32195D057000B7D73C /* ASMutableAttributedStringBuilderTests.m */,
|
058D0A32195D057000B7D73C /* ASMutableAttributedStringBuilderTests.m */,
|
||||||
|
3C9C128419E616EF00E942A0 /* ASTableViewTests.m */,
|
||||||
058D0A33195D057000B7D73C /* ASTextNodeCoreTextAdditionsTests.m */,
|
058D0A33195D057000B7D73C /* ASTextNodeCoreTextAdditionsTests.m */,
|
||||||
058D0A34195D057000B7D73C /* ASTextNodeRendererTests.m */,
|
058D0A34195D057000B7D73C /* ASTextNodeRendererTests.m */,
|
||||||
058D0A35195D057000B7D73C /* ASTextNodeShadowerTests.m */,
|
058D0A35195D057000B7D73C /* ASTextNodeShadowerTests.m */,
|
||||||
@ -688,6 +691,7 @@
|
|||||||
058D0A39195D057000B7D73C /* ASDisplayNodeAppearanceTests.m in Sources */,
|
058D0A39195D057000B7D73C /* ASDisplayNodeAppearanceTests.m in Sources */,
|
||||||
058D0A41195D057000B7D73C /* ASTextNodeWordKernerTests.mm in Sources */,
|
058D0A41195D057000B7D73C /* ASTextNodeWordKernerTests.mm in Sources */,
|
||||||
058D0A40195D057000B7D73C /* ASTextNodeTests.m in Sources */,
|
058D0A40195D057000B7D73C /* ASTextNodeTests.m in Sources */,
|
||||||
|
3C9C128519E616EF00E942A0 /* ASTableViewTests.m in Sources */,
|
||||||
058D0A38195D057000B7D73C /* ASDisplayLayerTests.m in Sources */,
|
058D0A38195D057000B7D73C /* ASDisplayLayerTests.m in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
|||||||
@ -236,7 +236,7 @@
|
|||||||
/**
|
/**
|
||||||
* @abstract The receiver's supernode.
|
* @abstract The receiver's supernode.
|
||||||
*/
|
*/
|
||||||
@property (nonatomic, readonly, assign) ASDisplayNode *supernode;
|
@property (nonatomic, readonly, weak) ASDisplayNode *supernode;
|
||||||
|
|
||||||
|
|
||||||
/** @name Drawing and Updating the View */
|
/** @name Drawing and Updating the View */
|
||||||
|
|||||||
@ -47,8 +47,8 @@ static BOOL _isInterceptedSelector(SEL sel)
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation _ASTableViewProxy {
|
@implementation _ASTableViewProxy {
|
||||||
id<NSObject> _target;
|
id<NSObject> __weak _target;
|
||||||
ASTableView *_interceptor;
|
ASTableView * __weak _interceptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithTarget:(id<NSObject>)target interceptor:(ASTableView *)interceptor
|
- (instancetype)initWithTarget:(id<NSObject>)target interceptor:(ASTableView *)interceptor
|
||||||
@ -140,7 +140,8 @@ static BOOL _isInterceptedSelector(SEL sel)
|
|||||||
|
|
||||||
- (void)setDelegate:(id<UITableViewDelegate>)delegate
|
- (void)setDelegate:(id<UITableViewDelegate>)delegate
|
||||||
{
|
{
|
||||||
ASDisplayNodeAssert(NO, @"ASTableView uses asyncDelegate, not UITableView's delegate property.");
|
// Our UIScrollView superclass sets its delegate to nil on dealloc. Only assert if we get a non-nil value here.
|
||||||
|
ASDisplayNodeAssert(delegate == nil, @"ASTableView uses asyncDelegate, not UITableView's delegate property.");
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setAsyncDataSource:(id<ASTableViewDataSource>)asyncDataSource
|
- (void)setAsyncDataSource:(id<ASTableViewDataSource>)asyncDataSource
|
||||||
|
|||||||
@ -32,7 +32,7 @@ BOOL ASDisplayNodeSubclassOverridesSelector(Class subclass, SEL selector);
|
|||||||
@protected
|
@protected
|
||||||
ASDN::RecursiveMutex _propertyLock; // Protects access to the _view, _pendingViewState, _subnodes, _supernode, _renderingSubnodes, and other properties which are accessed from multiple threads.
|
ASDN::RecursiveMutex _propertyLock; // Protects access to the _view, _pendingViewState, _subnodes, _supernode, _renderingSubnodes, and other properties which are accessed from multiple threads.
|
||||||
|
|
||||||
ASDisplayNode *_supernode;
|
ASDisplayNode * __weak _supernode;
|
||||||
|
|
||||||
ASSentinel *_displaySentinel;
|
ASSentinel *_displaySentinel;
|
||||||
ASSentinel *_replaceAsyncSentinel;
|
ASSentinel *_replaceAsyncSentinel;
|
||||||
|
|||||||
@ -783,6 +783,32 @@ static inline BOOL _CGPointEqualToPointWithEpsilon(CGPoint point1, CGPoint point
|
|||||||
[v release];
|
[v release];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)testAddingSubnodeDoesNotCreateRetainCycle
|
||||||
|
{
|
||||||
|
ASTestDisplayNode *node = [[ASTestDisplayNode alloc] init];
|
||||||
|
|
||||||
|
__block BOOL didDealloc = NO;
|
||||||
|
node.willDeallocBlock = ^(ASDisplayNode *n){
|
||||||
|
didDealloc = YES;
|
||||||
|
};
|
||||||
|
|
||||||
|
ASDisplayNode *subnode = [[ASDisplayNode alloc] init];
|
||||||
|
|
||||||
|
// verify initial
|
||||||
|
XCTAssertTrue(1 == node.retainCount, @"unexpected retain count:%tu", node.retainCount);
|
||||||
|
XCTAssertTrue(1 == subnode.retainCount, @"unexpected retain count:%tu", subnode.retainCount);
|
||||||
|
|
||||||
|
[node addSubnode:subnode];
|
||||||
|
XCTAssertTrue(2 == subnode.retainCount, @"node should retain subnode when added. retain count:%tu", node.retainCount);
|
||||||
|
XCTAssertTrue(1 == node.retainCount, @"subnode should not retain node when added. retain count:%tu", node.retainCount);
|
||||||
|
|
||||||
|
[subnode release];
|
||||||
|
XCTAssertTrue(1 == subnode.retainCount, @"subnode should be retained by node. retain count:%tu", subnode.retainCount);
|
||||||
|
|
||||||
|
[node release];
|
||||||
|
XCTAssertTrue(didDealloc, @"unexpected node lifetime:%@", node);
|
||||||
|
}
|
||||||
|
|
||||||
- (void)testMainThreadDealloc
|
- (void)testMainThreadDealloc
|
||||||
{
|
{
|
||||||
__block BOOL didDealloc = NO;
|
__block BOOL didDealloc = NO;
|
||||||
|
|||||||
86
AsyncDisplayKitTests/ASTableViewTests.m
Normal file
86
AsyncDisplayKitTests/ASTableViewTests.m
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/* Copyright (c) 2014-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <XCTest/XCTest.h>
|
||||||
|
|
||||||
|
#import "ASTableView.h"
|
||||||
|
|
||||||
|
@interface ASTestTableView : ASTableView
|
||||||
|
@property (atomic, copy) void (^willDeallocBlock)(ASTableView *tableView);
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation ASTestTableView
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
if (_willDeallocBlock) {
|
||||||
|
_willDeallocBlock(self);
|
||||||
|
}
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface ASTableViewTestDelegate : NSObject <ASTableViewDataSource, ASTableViewDelegate>
|
||||||
|
@property (atomic, copy) void (^willDeallocBlock)(ASTableViewTestDelegate *delegate);
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation ASTableViewTestDelegate
|
||||||
|
|
||||||
|
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (ASCellNode *)tableView:(ASTableView *)tableView nodeForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||||
|
{
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
if (_willDeallocBlock) {
|
||||||
|
_willDeallocBlock(self);
|
||||||
|
}
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface ASTableViewTests : XCTestCase
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation ASTableViewTests
|
||||||
|
|
||||||
|
- (void)testTableViewDoesNotRetainItselfAndDelegate
|
||||||
|
{
|
||||||
|
ASTestTableView *tableView = [[ASTestTableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
|
||||||
|
|
||||||
|
__block BOOL tableViewDidDealloc = NO;
|
||||||
|
tableView.willDeallocBlock = ^(ASTableView *v){
|
||||||
|
tableViewDidDealloc = YES;
|
||||||
|
};
|
||||||
|
|
||||||
|
ASTableViewTestDelegate *delegate = [[ASTableViewTestDelegate alloc] init];
|
||||||
|
|
||||||
|
__block BOOL delegateDidDealloc = NO;
|
||||||
|
delegate.willDeallocBlock = ^(ASTableViewTestDelegate *d){
|
||||||
|
delegateDidDealloc = YES;
|
||||||
|
};
|
||||||
|
|
||||||
|
tableView.asyncDataSource = delegate;
|
||||||
|
tableView.asyncDelegate = delegate;
|
||||||
|
|
||||||
|
[delegate release];
|
||||||
|
XCTAssertTrue(delegateDidDealloc, @"unexpected delegate lifetime:%@", delegate);
|
||||||
|
|
||||||
|
XCTAssertNoThrow([tableView release], @"unexpected exception when deallocating table view:%@", tableView);
|
||||||
|
XCTAssertTrue(tableViewDidDealloc, @"unexpected table view lifetime:%@", tableView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
Loading…
x
Reference in New Issue
Block a user