diff --git a/AsyncDisplayKit.podspec b/AsyncDisplayKit.podspec index e8ff2359cf..97001a9397 100644 --- a/AsyncDisplayKit.podspec +++ b/AsyncDisplayKit.podspec @@ -7,28 +7,27 @@ Pod::Spec.new do |spec| spec.summary = 'Smooth asynchronous user interfaces for iOS apps.' spec.source = { :git => 'https://github.com/facebook/AsyncDisplayKit.git', :tag => '1.0beta' } - # these files mustn't be compiled with ARC enabled - mrr_source_files = [ - 'AsyncDisplayKit/ASDisplayNode.mm', - 'AsyncDisplayKit/ASControlNode.m', - 'AsyncDisplayKit/ASImageNode.mm', - 'AsyncDisplayKit/Details/_ASDisplayView.mm', - 'AsyncDisplayKit/Private/_ASPendingState.m', - ] - spec.public_header_files = [ 'AsyncDisplayKit/*.h', 'AsyncDisplayKit/Details/**/*.h', 'Base/*.h' ] - spec.source_files = ['AsyncDisplayKit/**/*.{h,m,mm}', 'Base/*.{h,m}'] - spec.exclude_files = mrr_source_files + spec.source_files = [ + 'AsyncDisplayKit/**/*.{h,m,mm}', + 'Base/*.{h,m}' + ] + # ASDealloc2MainObject must be compiled with MRR spec.requires_arc = true - spec.subspec 'no-arc' do |mrr| + spec.exclude_files = ['AsyncDisplayKit/Details/ASDealloc2MainObject.m'] + spec.subspec 'ASDealloc2MainObject' do |mrr| mrr.requires_arc = false - mrr.source_files = mrr_source_files + mrr.source_files = [ + 'AsyncDisplayKit/Private/_AS-objc-internal.h', + 'AsyncDisplayKit/Details/ASDealloc2MainObject.h', + 'AsyncDisplayKit/Details/ASDealloc2MainObject.m', + ] end spec.social_media_url = 'https://twitter.com/fbOpenSource' diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index 7cfbfe4006..4b7010edc5 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -20,13 +20,13 @@ 058D09C1195D04C000B7D73C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 058D09C0195D04C000B7D73C /* UIKit.framework */; }; 058D09C4195D04C000B7D73C /* libAsyncDisplayKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 058D09AC195D04C000B7D73C /* libAsyncDisplayKit.a */; }; 058D09CA195D04C000B7D73C /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 058D09C8195D04C000B7D73C /* InfoPlist.strings */; }; - 058D0A13195D050800B7D73C /* ASControlNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 058D09D6195D050800B7D73C /* ASControlNode.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 058D0A14195D050800B7D73C /* ASDisplayNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D09D9195D050800B7D73C /* ASDisplayNode.mm */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 058D0A13195D050800B7D73C /* ASControlNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 058D09D6195D050800B7D73C /* ASControlNode.m */; }; + 058D0A14195D050800B7D73C /* ASDisplayNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D09D9195D050800B7D73C /* ASDisplayNode.mm */; }; 058D0A15195D050800B7D73C /* ASDisplayNodeExtras.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D09DC195D050800B7D73C /* ASDisplayNodeExtras.mm */; }; - 058D0A16195D050800B7D73C /* ASImageNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D09DE195D050800B7D73C /* ASImageNode.mm */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 058D0A16195D050800B7D73C /* ASImageNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D09DE195D050800B7D73C /* ASImageNode.mm */; }; 058D0A17195D050800B7D73C /* ASTextNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D09E0195D050800B7D73C /* ASTextNode.mm */; }; 058D0A18195D050800B7D73C /* _ASDisplayLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D09E3195D050800B7D73C /* _ASDisplayLayer.mm */; }; - 058D0A19195D050800B7D73C /* _ASDisplayView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D09E5195D050800B7D73C /* _ASDisplayView.mm */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 058D0A19195D050800B7D73C /* _ASDisplayView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D09E5195D050800B7D73C /* _ASDisplayView.mm */; }; 058D0A1A195D050800B7D73C /* ASHighlightOverlayLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 058D09E7195D050800B7D73C /* ASHighlightOverlayLayer.m */; }; 058D0A1B195D050800B7D73C /* ASMutableAttributedStringBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 058D09E9195D050800B7D73C /* ASMutableAttributedStringBuilder.m */; }; 058D0A1C195D050800B7D73C /* ASTextNodeCoreTextAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 058D09EB195D050800B7D73C /* ASTextNodeCoreTextAdditions.m */; }; @@ -40,7 +40,7 @@ 058D0A24195D050800B7D73C /* _ASAsyncTransactionGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = 058D09FE195D050800B7D73C /* _ASAsyncTransactionGroup.m */; }; 058D0A25195D050800B7D73C /* UIView+ASConvenience.m in Sources */ = {isa = PBXBuildFile; fileRef = 058D0A00195D050800B7D73C /* UIView+ASConvenience.m */; }; 058D0A26195D050800B7D73C /* _ASCoreAnimationExtras.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D0A04195D050800B7D73C /* _ASCoreAnimationExtras.mm */; }; - 058D0A27195D050800B7D73C /* _ASPendingState.m in Sources */ = {isa = PBXBuildFile; fileRef = 058D0A06195D050800B7D73C /* _ASPendingState.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 058D0A27195D050800B7D73C /* _ASPendingState.m in Sources */ = {isa = PBXBuildFile; fileRef = 058D0A06195D050800B7D73C /* _ASPendingState.m */; }; 058D0A28195D050800B7D73C /* ASDisplayNode+AsyncDisplay.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D0A08195D050800B7D73C /* ASDisplayNode+AsyncDisplay.mm */; }; 058D0A29195D050800B7D73C /* ASDisplayNode+DebugTiming.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D0A0A195D050800B7D73C /* ASDisplayNode+DebugTiming.mm */; }; 058D0A2A195D050800B7D73C /* ASDisplayNode+UIViewBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D0A0B195D050800B7D73C /* ASDisplayNode+UIViewBridge.mm */; }; @@ -118,6 +118,8 @@ 058D0A82195D060300B7D73C /* ASAssert.h in Headers */ = {isa = PBXBuildFile; fileRef = 058D0A43195D058D00B7D73C /* ASAssert.h */; settings = {ATTRIBUTES = (Public, ); }; }; 058D0A83195D060300B7D73C /* ASBaseDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 058D0A44195D058D00B7D73C /* ASBaseDefines.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 */; }; + 05A6D05B19D0EB64002DD95E /* ASDealloc2MainObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 05A6D05919D0EB64002DD95E /* ASDealloc2MainObject.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 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 */; }; /* End PBXBuildFile section */ @@ -234,6 +236,8 @@ 058D0A43195D058D00B7D73C /* ASAssert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASAssert.h; sourceTree = ""; }; 058D0A44195D058D00B7D73C /* ASBaseDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASBaseDefines.h; sourceTree = ""; }; 058D0A45195D058D00B7D73C /* ASDisplayNodeExtraIvars.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASDisplayNodeExtraIvars.h; sourceTree = ""; }; + 05A6D05819D0EB64002DD95E /* ASDealloc2MainObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASDealloc2MainObject.h; path = ../Details/ASDealloc2MainObject.h; sourceTree = ""; }; + 05A6D05919D0EB64002DD95E /* ASDealloc2MainObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASDealloc2MainObject.m; path = ../Details/ASDealloc2MainObject.m; sourceTree = ""; }; 6BDC61F51978FEA400E50D21 /* AsyncDisplayKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AsyncDisplayKit.h; sourceTree = ""; }; 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 = ""; }; @@ -389,6 +393,8 @@ 058D09F7195D050800B7D73C /* Transactions */, 058D09FF195D050800B7D73C /* UIView+ASConvenience.h */, 058D0A00195D050800B7D73C /* UIView+ASConvenience.m */, + 05A6D05819D0EB64002DD95E /* ASDealloc2MainObject.h */, + 05A6D05919D0EB64002DD95E /* ASDealloc2MainObject.m */, ); path = Details; sourceTree = ""; @@ -458,6 +464,7 @@ 058D0A4E195D05CB00B7D73C /* ASDisplayNodeExtras.mm in Headers */, 058D0A4F195D05CB00B7D73C /* ASImageNode.h in Headers */, 058D0A50195D05CB00B7D73C /* ASImageNode.mm in Headers */, + 05A6D05A19D0EB64002DD95E /* ASDealloc2MainObject.h in Headers */, 058D0A51195D05CB00B7D73C /* ASTextNode.h in Headers */, 058D0A52195D05CB00B7D73C /* ASTextNode.mm in Headers */, 055F1A3819ABD413004DAFF1 /* ASRangeController.h in Headers */, @@ -658,6 +665,7 @@ 058D0A1C195D050800B7D73C /* ASTextNodeCoreTextAdditions.m in Sources */, 058D0A13195D050800B7D73C /* ASControlNode.m in Sources */, 058D0A19195D050800B7D73C /* _ASDisplayView.mm in Sources */, + 05A6D05B19D0EB64002DD95E /* ASDealloc2MainObject.m in Sources */, 058D0A17195D050800B7D73C /* ASTextNode.mm in Sources */, 058D0A27195D050800B7D73C /* _ASPendingState.m in Sources */, 058D0A16195D050800B7D73C /* ASImageNode.mm in Sources */, diff --git a/AsyncDisplayKit/ASControlNode.m b/AsyncDisplayKit/ASControlNode.m index 9d28232dc9..552366dc3b 100644 --- a/AsyncDisplayKit/ASControlNode.m +++ b/AsyncDisplayKit/ASControlNode.m @@ -104,12 +104,6 @@ void _ASEnumerateControlEventsIncludedInMaskWithBlock(ASControlNodeEvent mask, v return self; } -- (void)dealloc -{ - [_controlEventDispatchTable release]; - [super dealloc]; -} - #pragma mark - ASDisplayNode Overrides - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { @@ -251,7 +245,6 @@ void _ASEnumerateControlEventsIncludedInMaskWithBlock(ASControlNodeEvent mask, v // Create the dispatch table for this event. eventDispatchTable = [[NSMutableDictionary alloc] initWithCapacity:kASControlNodeTargetDispatchTableInitialCapacity]; // enough to handle common types without re-hashing the dictionary when adding entries [_controlEventDispatchTable setObject:eventDispatchTable forKey:eventKey]; - [eventDispatchTable release]; } // Have we seen this target before for this event? @@ -262,7 +255,6 @@ void _ASEnumerateControlEventsIncludedInMaskWithBlock(ASControlNodeEvent mask, v // Nope. Create an actions array for it. targetActions = [[NSMutableArray alloc] initWithCapacity:kASControlNodeActionDispatchTableInitialCapacity]; // enough to handle common types without re-hashing the dictionary when adding entries. [eventDispatchTable setObject:targetActions forKey:targetKey]; - [targetActions release]; } // Add the action message. @@ -299,7 +291,7 @@ void _ASEnumerateControlEventsIncludedInMaskWithBlock(ASControlNodeEvent mask, v [targets addObject:_ASControlNodeTargetForTargetKey(targetKey)]; } - return [targets autorelease]; + return targets; } - (void)removeTarget:(id)target action:(SEL)action forControlEvents:(ASControlNodeEvent)controlEventMask @@ -397,7 +389,7 @@ id _ASControlNodeEventKeyForControlEvent(ASControlNodeEvent controlEv id _ASControlNodeTargetKeyForTarget(id target) { - return (target ? [NSValue valueWithPointer:target] : [NSNull null]); + return (target ? [NSValue valueWithPointer:(__bridge const void *)(target)] : [NSNull null]); } id _ASControlNodeTargetForTargetKey(id targetKey) diff --git a/AsyncDisplayKit/ASDisplayNode.h b/AsyncDisplayKit/ASDisplayNode.h index b4d02aaeec..eb23732cb7 100644 --- a/AsyncDisplayKit/ASDisplayNode.h +++ b/AsyncDisplayKit/ASDisplayNode.h @@ -10,6 +10,7 @@ #import "_ASAsyncTransactionContainer.h" #import "ASBaseDefines.h" +#import "ASDealloc2MainObject.h" /** @@ -28,7 +29,7 @@ * */ -@interface ASDisplayNode : NSObject +@interface ASDisplayNode : ASDealloc2MainObject /** @name Initializing a node object */ diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index bae3e1f2c2..8b5565ba40 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -81,7 +81,7 @@ BOOL ASDisplayNodeSubclassOverridesSelector(Class subclass, SEL selector) return nil; ASDisplayNodeAssert([viewClass isSubclassOfClass:[UIView class]], @"should initialize with a subclass of UIView"); - _viewClass = [viewClass retain]; + _viewClass = viewClass; _flags.isSynchronous = ![viewClass isSubclassOfClass:[_ASDisplayView class]]; return self; @@ -94,7 +94,7 @@ BOOL ASDisplayNodeSubclassOverridesSelector(Class subclass, SEL selector) ASDisplayNodeAssert([layerClass isSubclassOfClass:[CALayer class]], @"should initialize with a subclass of CALayer"); - _layerClass = [layerClass retain]; + _layerClass = layerClass; _flags.isSynchronous = ![layerClass isSubclassOfClass:[_ASDisplayLayer class]]; _flags.isLayerBacked = YES; @@ -123,14 +123,6 @@ BOOL ASDisplayNodeSubclassOverridesSelector(Class subclass, SEL selector) return self; } -#if __has_feature(objc_arc) -#warning This file must be compiled without ARC. Use -fno-objc-arc (or convert project to MRR). -#endif - -#if !__has_feature(objc_arc) -_OBJC_SUPPORTED_INLINE_REFCNT_WITH_DEALLOC2MAIN(_retainCount); -#endif - - (void)dealloc { ASDisplayNodeAssertMainThread(); @@ -147,28 +139,18 @@ _OBJC_SUPPORTED_INLINE_REFCNT_WITH_DEALLOC2MAIN(_retainCount); for (ASDisplayNode *subnode in _subnodes) [subnode __setSupernode:nil]; - [_viewClass release]; - [_subnodes release]; - - [_view release]; _view = nil; _subnodes = nil; if (_flags.isLayerBacked) { _layer.delegate = nil; } - [_layer release]; _layer = nil; [self __setSupernode:nil]; - [_pendingViewState release]; _pendingViewState = nil; - [_replaceAsyncSentinel release]; _replaceAsyncSentinel = nil; - [_displaySentinel release]; _displaySentinel = nil; - - [super dealloc]; } #pragma mark - UIResponder overrides @@ -230,7 +212,7 @@ _OBJC_SUPPORTED_INLINE_REFCNT_WITH_DEALLOC2MAIN(_retainCount); } _view = [[_viewClass alloc] init]; _view.asyncdisplaykit_node = self; - _layer = [_view.layer retain]; + _layer = _view.layer; } _layer.asyncdisplaykit_node = self; #if DEBUG @@ -671,8 +653,6 @@ static bool disableNotificationsForMovingBetweenParents(ASDisplayNode *from, ASD if (subnodeIndex == NSNotFound) return; - [subnode retain]; - ASDisplayNode *oldParent = [subnode _deallocSafeSupernode]; // Disable appearance methods during move between supernodes, but make sure we restore their state after we do our thing BOOL isMovingEquivalentParents = disableNotificationsForMovingBetweenParents(oldParent, self); @@ -715,7 +695,6 @@ static bool disableNotificationsForMovingBetweenParents(ASDisplayNode *from, ASD } [subnode __setSupernode:self]; - [subnode release]; } - (void)replaceSubnode:(ASDisplayNode *)oldSubnode withSubnode:(ASDisplayNode *)replacementSubnode @@ -882,7 +861,7 @@ static NSInteger incrementIfFound(NSInteger i) { { ASDisplayNodeAssertMainThread(); - for (ASDisplayNode *node in [[_subnodes copy] autorelease]) { + for (ASDisplayNode *node in [_subnodes copy]) { [self _addSubnodeSubviewOrSublayer:node]; } } @@ -1040,14 +1019,14 @@ static NSInteger incrementIfFound(NSInteger i) { { ASDisplayNodeAssertThreadAffinity(self); ASDN::MutexLocker l(_propertyLock); - return [[_subnodes copy] autorelease]; + return [_subnodes copy]; } - (ASDisplayNode *)supernode { ASDisplayNodeAssertThreadAffinity(self); ASDN::MutexLocker l(_propertyLock); - return [[_supernode retain] autorelease]; + return _supernode; } // This is a thread-method to return the supernode without causing it to be retained autoreleased. See -_removeSubnode: for details. @@ -1255,7 +1234,6 @@ static NSInteger incrementIfFound(NSInteger i) { [_pendingViewState applyToView:_view]; } - [_pendingViewState release]; _pendingViewState = nil; // TODO: move this into real pending state @@ -1393,7 +1371,7 @@ static void _recursiveSetPreventOrCancelDisplay(ASDisplayNode *node, CALayer *la if (!_replaceAsyncSentinel) { _replaceAsyncSentinel = [[ASSentinel alloc] init]; } - return [[_replaceAsyncSentinel retain] autorelease]; + return _replaceAsyncSentinel; } // Calls completion with nil to indicated cancellation @@ -1505,7 +1483,7 @@ static void _recursiveSetPreventOrCancelDisplay(ASDisplayNode *node, CALayer *la } }]; - return [placeholder autorelease]; + return placeholder; } @end @@ -1560,7 +1538,7 @@ static void _recursiveSetPreventOrCancelDisplay(ASDisplayNode *node, CALayer *la - (NSString *)_recursiveDescriptionHelperWithIndent:(NSString *)indent { - NSMutableString *subtree = [[[[indent stringByAppendingString: self.descriptionForRecursiveDescription] stringByAppendingString:@"\n"] mutableCopy] autorelease]; + NSMutableString *subtree = [[[indent stringByAppendingString: self.descriptionForRecursiveDescription] stringByAppendingString:@"\n"] mutableCopy]; for (ASDisplayNode *n in self.subnodes) { [subtree appendString:[n _recursiveDescriptionHelperWithIndent:[indent stringByAppendingString:@" | "]]]; } diff --git a/AsyncDisplayKit/ASImageNode.mm b/AsyncDisplayKit/ASImageNode.mm index 71407a3191..9c7c39fbca 100644 --- a/AsyncDisplayKit/ASImageNode.mm +++ b/AsyncDisplayKit/ASImageNode.mm @@ -40,10 +40,10 @@ _cropEnabled = cropEnabled; _opaque = opaque; - _image = [image retain]; + _image = image; _bounds = bounds; _contentsScale = contentsScale; - _backgroundColor = [backgroundColor retain]; + _backgroundColor = backgroundColor; _tint = tint; _contentMode = contentMode; _cropRect = cropRect; @@ -52,14 +52,6 @@ return self; } -- (void)dealloc -{ - [_image release]; - [_backgroundColor release]; - [_imageModificationBlock release]; - [super dealloc]; -} - - (NSString *)description { return [NSString stringWithFormat:@"<%@ : %p image:%@ cropEnabled:%@ opaque:%@ bounds:%@ contentsScale:%.2f backgroundColor:%@ tint:%zd contentMode:%@ cropRect:%@>", [self class], self, self.image, @(self.cropEnabled), @(self.opaque), NSStringFromCGRect(self.bounds), self.contentsScale, self.backgroundColor, self.tint, ASDisplayNodeNSStringFromUIContentMode(self.contentMode), NSStringFromCGRect(self.cropRect)]; @@ -102,14 +94,6 @@ return self; } -- (void)dealloc -{ - [_displayCompletionBlock release]; - [_image release]; - [_imageModificationBlock release]; - [super dealloc]; -} - - (CGSize)calculateSizeThatFits:(CGSize)constrainedSize { ASDN::MutexLocker l(_imageLock); @@ -124,8 +108,7 @@ ASDisplayNodeAssertThreadAffinity(self); ASDN::MutexLocker l(_imageLock); if (_image != image) { - [_image release]; - _image = [image retain]; + _image = image; [self invalidateCalculatedSize]; [self setNeedsDisplay]; } @@ -135,7 +118,7 @@ { ASDisplayNodeAssertThreadAffinity(self); ASDN::MutexLocker l(_imageLock); - return [[_image retain] autorelease]; + return _image; } - (void)setTint:(ASImageNodeTint)tint @@ -159,17 +142,16 @@ { BOOL hasValidCropBounds = _cropEnabled && !CGRectIsNull(_cropDisplayBounds) && !CGRectIsEmpty(_cropDisplayBounds); - return [[[_ASImageNodeDrawParameters alloc] initWithCrop:_cropEnabled - opaque:self.opaque - image:self.image - bounds:(hasValidCropBounds ? _cropDisplayBounds : self.bounds) - contentsScale:self.contentsScaleForDisplay - backgroundColor:self.backgroundColor - tint:self.tint - contentMode:self.contentMode - cropRect:self.cropRect - imageModificationBlock:self.imageModificationBlock - ] autorelease]; + return [[_ASImageNodeDrawParameters alloc] initWithCrop:_cropEnabled + opaque:self.opaque + image:self.image + bounds:(hasValidCropBounds ? _cropDisplayBounds : self.bounds) + contentsScale:self.contentsScaleForDisplay + backgroundColor:self.backgroundColor + tint:self.tint + contentMode:self.contentMode + cropRect:self.cropRect + imageModificationBlock:self.imageModificationBlock]; } + (UIImage *)displayWithParameters:(_ASImageNodeDrawParameters *)parameters isCancelled:(asdisplaynode_iscancelled_block_t)isCancelled @@ -287,7 +269,6 @@ // FIXME: _displayCompletionBlock is not protected by lock _displayCompletionBlock(NO); - [_displayCompletionBlock release]; _displayCompletionBlock = nil; } } @@ -304,7 +285,6 @@ // Stash the block and call-site queue. We'll invoke it in -displayDidFinish. // FIXME: _displayCompletionBlock not protected by lock if (_displayCompletionBlock != displayCompletionBlock) { - [_displayCompletionBlock release]; _displayCompletionBlock = [displayCompletionBlock copy]; } diff --git a/AsyncDisplayKit/Details/ASDealloc2MainObject.h b/AsyncDisplayKit/Details/ASDealloc2MainObject.h new file mode 100644 index 0000000000..0bedeaa9d6 --- /dev/null +++ b/AsyncDisplayKit/Details/ASDealloc2MainObject.h @@ -0,0 +1,20 @@ +/* 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 + +/** + * _OBJC_SUPPORTED_INLINE_REFCNT_WITH_DEALLOC2MAIN permits classes to implement their own reference counting and enforce + * deallocation on the main thread, but requires manual reference counting. This superclass exposes such functionality + * to ARC-enabled classes. + */ +@interface ASDealloc2MainObject : NSObject + +- (BOOL)_isDeallocating; + +@end diff --git a/AsyncDisplayKit/Details/ASDealloc2MainObject.m b/AsyncDisplayKit/Details/ASDealloc2MainObject.m new file mode 100644 index 0000000000..4b734f70c7 --- /dev/null +++ b/AsyncDisplayKit/Details/ASDealloc2MainObject.m @@ -0,0 +1,32 @@ +/* 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 "ASDealloc2MainObject.h" + +#import + +#import "_AS-objc-internal.h" + +#if __has_feature(objc_arc) +#error This file must be compiled without ARC. Use -fno-objc-arc. +#endif + +@interface ASDealloc2MainObject () +{ + @private + int _retainCount; +} +@end + +@implementation ASDealloc2MainObject + +#if !__has_feature(objc_arc) +_OBJC_SUPPORTED_INLINE_REFCNT_WITH_DEALLOC2MAIN(_retainCount); +#endif + +@end diff --git a/AsyncDisplayKit/Details/_ASDisplayView.mm b/AsyncDisplayKit/Details/_ASDisplayView.mm index 4314cc694b..aacece0553 100644 --- a/AsyncDisplayKit/Details/_ASDisplayView.mm +++ b/AsyncDisplayKit/Details/_ASDisplayView.mm @@ -19,11 +19,15 @@ @interface _ASDisplayView () @property (nonatomic, assign, readwrite) ASDisplayNode *asyncdisplaykit_node; + +// Keep the node alive while its view is active. If you create a view, add its layer to a layer hierarchy, then release +// the view, the layer retains the view to prevent a crash. This replicates this behaviour for the node abstraction. +@property (nonatomic, retain, readwrite) ASDisplayNode *keepalive_node; @end @implementation _ASDisplayView { - ASDisplayNode *_node; // Though UIView has a .node property added via category, since we can add an ivar to a subclass, use that for performance. + __unsafe_unretained ASDisplayNode *_node; // Though UIView has a .node property added via category, since we can add an ivar to a subclass, use that for performance. BOOL _inHitTest; BOOL _inPointInside; } @@ -66,10 +70,10 @@ // view). UIView *currentSuperview = self.superview; if (!currentSuperview && newSuperview) { - [_node retain]; + self.keepalive_node = _node; } else if (currentSuperview && !newSuperview) { - [_node release]; + self.keepalive_node = nil; } } diff --git a/AsyncDisplayKit/Private/ASDisplayNodeInternal.h b/AsyncDisplayKit/Private/ASDisplayNodeInternal.h index ed72f0986c..24c4ceeb54 100644 --- a/AsyncDisplayKit/Private/ASDisplayNodeInternal.h +++ b/AsyncDisplayKit/Private/ASDisplayNodeInternal.h @@ -30,7 +30,6 @@ BOOL ASDisplayNodeSubclassOverridesSelector(Class subclass, SEL selector); @interface ASDisplayNode () <_ASDisplayLayerDelegate> { @protected - int _retainCount; ASDN::RecursiveMutex _propertyLock; // Protects access to the _view, _pendingViewState, _subnodes, _supernode, _renderingSubnodes, and other properties which are accessed from multiple threads. ASDisplayNode *_supernode; diff --git a/AsyncDisplayKit/Private/_ASPendingState.m b/AsyncDisplayKit/Private/_ASPendingState.m index 1535e51ce0..94312fad6c 100644 --- a/AsyncDisplayKit/Private/_ASPendingState.m +++ b/AsyncDisplayKit/Private/_ASPendingState.m @@ -185,23 +185,6 @@ return self; } -- (void)dealloc -{ - [contents release]; - [name release]; - if (NULL != shadowColor) - CFRelease(shadowColor); - if (NULL != borderColor) - CFRelease(borderColor); - if (NULL != backgroundColor) - CFRelease(backgroundColor); - [accessibilityLabel release]; - [accessibilityHint release]; - [accessibilityValue release]; - [accessibilityLanguage release]; - [super dealloc]; -} - - (CALayer *)layer { ASDisplayNodeAssert(NO, @"One shouldn't call node.layer when the view isn't loaded, but we're returning nil to not crash if someone is still doing this"); @@ -288,8 +271,7 @@ return; } - [contents release]; - contents = [newContents retain]; + contents = newContents; _flags.setContents = YES; } @@ -420,14 +402,13 @@ { _flags.setName = YES; if (name != newName) { - [name release]; name = [newName copy]; } } - (NSString *)asyncdisplaykit_name { - return [[name retain] autorelease]; + return name; } - (BOOL)isAccessibilityElement @@ -443,39 +424,36 @@ - (NSString *)accessibilityLabel { - return [[accessibilityLabel retain] autorelease]; + return accessibilityLabel; } - (void)setAccessibilityLabel:(NSString *)newAccessibilityLabel { _flags.setAccessibilityLabel = YES; if (accessibilityLabel != newAccessibilityLabel) { - [accessibilityLabel release]; accessibilityLabel = [newAccessibilityLabel copy]; } } - (NSString *)accessibilityHint { - return [[accessibilityHint retain] autorelease]; + return accessibilityHint; } - (void)setAccessibilityHint:(NSString *)newAccessibilityHint { _flags.setAccessibilityHint = YES; - [accessibilityHint release]; accessibilityHint = [newAccessibilityHint copy]; } - (NSString *)accessibilityValue { - return [[accessibilityValue retain] autorelease]; + return accessibilityValue; } - (void)setAccessibilityValue:(NSString *)newAccessibilityValue { _flags.setAccessibilityValue = YES; - [accessibilityValue release]; accessibilityValue = [newAccessibilityValue copy]; } @@ -503,16 +481,13 @@ - (NSString *)accessibilityLanguage { - return [[accessibilityLanguage retain] autorelease]; + return accessibilityLanguage; } - (void)setAccessibilityLanguage:(NSString *)newAccessibilityLanguage { _flags.setAccessibilityLanguage = YES; - if(accessibilityLanguage != newAccessibilityLanguage) { - [accessibilityLanguage release]; - accessibilityLanguage = [newAccessibilityLanguage retain]; - } + accessibilityLanguage = newAccessibilityLanguage; } - (BOOL)accessibilityElementsHidden