* [ios] support view compositing
Project: http://git-wip-us.apache.org/repos/asf/incubator-weex/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-weex/commit/c6d980d3 Tree: http://git-wip-us.apache.org/repos/asf/incubator-weex/tree/c6d980d3 Diff: http://git-wip-us.apache.org/repos/asf/incubator-weex/diff/c6d980d3 Branch: refs/heads/0.12-dev Commit: c6d980d30001fa50c25b6c91434cbbb85b24021f Parents: dbe2f32 Author: éé£ <cxf...@apache.org> Authored: Wed Apr 5 19:48:08 2017 +0800 Committer: éé£ <cxf...@apache.org> Committed: Wed Apr 5 19:48:08 2017 +0800 ---------------------------------------------------------------------- .../Sources/Component/WXComponent_internal.h | 8 +- .../Sources/Component/WXImageComponent.m | 50 ++--- .../WeexSDK/Sources/Component/WXTextComponent.m | 89 ++++----- .../Sources/Display/WXComponent+Display.m | 191 ++++++++++++------- ios/sdk/WeexSDK/Sources/Display/WXRoundedRect.h | 2 + .../WeexSDK/Sources/Display/WXRoundedRect.mm | 5 + ios/sdk/WeexSDK/Sources/Model/WXComponent.h | 55 +++++- ios/sdk/WeexSDK/Sources/Model/WXComponent.m | 7 +- ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m | 6 +- 9 files changed, 248 insertions(+), 165 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/c6d980d3/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h index 28f9d2e..00f0ef4 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h +++ b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h @@ -81,8 +81,8 @@ * Display */ CALayer *_layer; - BOOL _composite; - BOOL _compositingChild; + BOOL _useCompositing; + BOOL _isCompositingChild; WXThreadSafeCounter *_displayCounter; UIColor *_borderTopColor; @@ -185,6 +185,10 @@ - (void)_setupNavBarWithStyles:(NSMutableDictionary *)styles attributes:(NSMutableDictionary *)attributes; +- (void)_initCompositingAttribute:(NSDictionary *)attributes; + +- (BOOL)_bitmapOpaqueWithSize:(CGSize)size; + - (void)_updateNavBarAttributes:(NSDictionary *)attributes; - (void)_handleFirstScreenTime; http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/c6d980d3/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m index d5d9ca6..1e2594c 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m @@ -158,38 +158,21 @@ static dispatch_queue_t WXImageUpdateQueue; } -- (WXDisplayBlock)displayBlock +- (BOOL)needsDrawRect { - if ([self isViewLoaded]) { - // if has a image view, image is setted by image view, displayBlock is not needed - return nil; + if (_isCompositingChild) { + return YES; + } else { + return NO; } - - __weak typeof(self) weakSelf = self; - return ^UIImage *(CGRect bounds, BOOL(^isCancelled)(void)) { - if (isCancelled()) { - return nil; - } - - if (!weakSelf.image) { - [weakSelf updateImage]; - return nil; - } - - if (isCancelled && isCancelled()) { - return nil; - } - - UIGraphicsBeginImageContextWithOptions(bounds.size, self.layer.opaque, 1.0); - - [weakSelf.image drawInRect:bounds]; - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - - UIGraphicsEndImageContext(); - - return image; - }; +} + +- (UIImage *)drawRect:(CGRect)rect +{ + if (!self.image) { + [self updateImage]; + } + return self.image; } - (void)viewWillUnload @@ -262,6 +245,9 @@ static dispatch_queue_t WXImageUpdateQueue; ((UIImageView *)strongSelf.view).image = image; weakSelf.imageDownloadFinish = YES; [self readyToRender]; + } else if (strongSelf->_isCompositingChild) { + strongSelf->_image = image; + weakSelf.imageDownloadFinish = YES; } }); }]; @@ -302,6 +288,10 @@ static dispatch_queue_t WXImageUpdateQueue; strongSelf.imageDownloadFinish = YES; ((UIImageView *)strongSelf.view).image = image; [strongSelf readyToRender]; + } else if (strongSelf->_isCompositingChild) { + strongSelf.imageDownloadFinish = YES; + strongSelf->_image = image; + [strongSelf setNeedsDisplay]; } }); }]; http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/c6d980d3/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m index 77e7ce2..4ee3860 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m @@ -42,37 +42,6 @@ return [WXLayer class]; } -- (UIImage *)drawTextWithBounds:(CGRect)bounds padding:(UIEdgeInsets)padding -{ - if (bounds.size.width <=0 || bounds.size.height <= 0) { - return nil; - } - UIGraphicsBeginImageContextWithOptions(bounds.size, self.layer.opaque, WXScreenScale()); - CGContextRef context = UIGraphicsGetCurrentContext(); - - if ([self.wx_component _needsDrawBorder]) { - [self.wx_component _drawBorderWithContext:context size:bounds.size]; - } else { - WXPerformBlockOnMainThread(^{ - [self.wx_component _resetNativeBorderRadius]; - }); - } - NSLayoutManager *layoutManager = _textStorage.layoutManagers.firstObject; - NSTextContainer *textContainer = layoutManager.textContainers.firstObject; - - CGRect textFrame = UIEdgeInsetsInsetRect(bounds, padding); - NSRange glyphRange = [layoutManager glyphRangeForTextContainer:textContainer]; - - [layoutManager drawBackgroundForGlyphRange:glyphRange atPoint:textFrame.origin]; - [layoutManager drawGlyphsForGlyphRange:glyphRange atPoint:textFrame.origin]; - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - - UIGraphicsEndImageContext(); - - return image; -} - - (void)setTextStorage:(NSTextStorage *)textStorage { if (_textStorage != textStorage) { @@ -227,25 +196,21 @@ do {\ return [[WXText alloc] init]; } -- (WXDisplayBlock)displayBlock +- (BOOL)needsDrawRect { - WXText *textView = ((WXText *)self.view); - return ^UIImage *(CGRect bounds, BOOL(^isCancelled)(void)) { - if (isCancelled()) { - return nil; - } - if (_isUsingTextStorageLock) { - pthread_mutex_lock(&_textStorageMutex); - } - - UIImage *image = [textView drawTextWithBounds:bounds padding:_padding]; - - if (_isUsingTextStorageLock) { - pthread_mutex_unlock(&_textStorageMutex); - } - - return image; - }; + return YES; +} + +- (UIImage *)drawRect:(CGRect)rect +{ + if (_isCompositingChild) { + [self drawTextWithBounds:rect padding:_padding view:nil]; + } else { + WXText *textView = ((WXText *)self.view); + [self drawTextWithBounds:rect padding:_padding view:textView]; + } + + return nil; } - (CGSize (^)(CGSize))measureBlock @@ -287,6 +252,7 @@ do {\ } #pragma mark Text Building + - (NSString *)text { return _text; @@ -447,6 +413,31 @@ do {\ [self syncTextStorageForView]; } +- (void)drawTextWithBounds:(CGRect)bounds padding:(UIEdgeInsets)padding view:(WXText *)view +{ + if (bounds.size.width <=0 || bounds.size.height <= 0) { + return; + } + + CGContextRef context = UIGraphicsGetCurrentContext(); + + if ([self _needsDrawBorder]) { + [self _drawBorderWithContext:context size:bounds.size]; + } else { + WXPerformBlockOnMainThread(^{ + [self _resetNativeBorderRadius]; + }); + } + NSLayoutManager *layoutManager = (view ? view.textStorage : _textStorage).layoutManagers.firstObject; + NSTextContainer *textContainer = layoutManager.textContainers.firstObject; + + CGRect textFrame = UIEdgeInsetsInsetRect(bounds, padding); + NSRange glyphRange = [layoutManager glyphRangeForTextContainer:textContainer]; + + [layoutManager drawBackgroundForGlyphRange:glyphRange atPoint:textFrame.origin]; + [layoutManager drawGlyphsForGlyphRange:glyphRange atPoint:textFrame.origin]; +} + #ifdef UITEST - (NSString *)description { http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/c6d980d3/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m b/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m index 2231d46..fdd02a1 100644 --- a/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m +++ b/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m @@ -28,10 +28,10 @@ { WXAssertMainThread(); - if (_compositingChild) { + if (_isCompositingChild) { WXComponent *supercomponent = self.supercomponent; while (supercomponent) { - if (supercomponent->_composite) { + if (supercomponent->_useCompositing) { break; } supercomponent = supercomponent.supercomponent; @@ -44,54 +44,82 @@ } } -- (WXDisplayBlock)displayBlock +- (BOOL)needsDrawRect +{ + if (![self _needsDrawBorder]) { + WXLogDebug(@"No need to draw border for %@", self.ref); + WXPerformBlockOnMainThread(^{ + [self _resetNativeBorderRadius]; + }); + + return NO; + } + + return YES; +} + +- (UIImage *)drawRect:(CGRect)rect +{ + CGSize size = rect.size; + if (size.width <= 0 || size.height <= 0) { + WXLogDebug(@"No need to draw border for %@, because width or height is zero", self.ref); + return nil; + } + + CGContextRef context = UIGraphicsGetCurrentContext(); + [self _drawBorderWithContext:context size:size]; + + return nil; +} + +- (WXDisplayBlock)_displayBlock { WXDisplayBlock displayBlock = ^UIImage *(CGRect bounds, BOOL(^isCancelled)(void)) { if (isCancelled()) { return nil; } - - if (![self _needsDrawBorder]) { - WXLogDebug(@"No need to draw border for %@", self.ref); - WXPerformBlockOnMainThread(^{ - [self _resetNativeBorderRadius]; - }); - return nil; + + UIGraphicsBeginImageContextWithOptions(bounds.size, [self _bitmapOpaqueWithSize:bounds.size] , 0.0); + UIImage *image = [self drawRect:bounds]; + if (!image) { + image = UIGraphicsGetImageFromCurrentImageContext(); } + UIGraphicsEndImageContext(); - return [self _borderImage]; + return image; }; return displayBlock; } -- (WXDisplayCompletionBlock)displayCompletionBlock +#pragma mark Private + +- (void)_initCompositingAttribute:(NSDictionary *)attributes { - return nil; + _useCompositing = attributes[@"compositing"] ? [WXConvert BOOL:attributes[@"compositing"]] : NO; } -#pragma mark Private - - (void)_willDisplayLayer:(CALayer *)layer { WXAssertMainThread(); - if (_compositingChild) { - // compsiting children need not draw layer + if (_isCompositingChild) { + // compsiting children do not have own layers, so return here. return; } CGRect displayBounds = CGRectMake(0, 0, self.calculatedFrame.size.width, self.calculatedFrame.size.height); + BOOL needsDrawRect = [self needsDrawRect]; WXDisplayBlock displayBlock; - if (_composite) { + if (_useCompositing) { displayBlock = [self _compositeDisplayBlock]; } else { - displayBlock = [self displayBlock]; + displayBlock = [self _displayBlock]; } WXDisplayCompletionBlock completionBlock = [self displayCompletionBlock]; - if (!displayBlock) { + if (!displayBlock || !needsDrawRect) { if (completionBlock) { completionBlock(layer, NO); } @@ -146,6 +174,22 @@ } } +- (CGContextRef)beginDrawContext:(CGRect)bounds +{ + UIGraphicsBeginImageContextWithOptions(bounds.size, [self _bitmapOpaqueWithSize:bounds.size], 0.0); + CGContextRef context = UIGraphicsGetCurrentContext(); + + return context; +} + +- (UIImage *)endDrawContext +{ + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return image; +} + - (WXDisplayBlock)_compositeDisplayBlock { return ^UIImage* (CGRect bounds, BOOL(^isCancelled)(void)) { @@ -153,11 +197,20 @@ return nil; } NSMutableArray *displayBlocks = [NSMutableArray array]; - [self _collectDisplayBlocks:displayBlocks isCancelled:isCancelled]; - BOOL opaque = _layer.opaque && CGColorGetAlpha(_backgroundColor.CGColor) == 1.0f; + CGContextRef context = [self beginDrawContext:bounds]; + +// float scaleFactor = [[UIScreen mainScreen] scale]; +// CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); +// CGContextRef context = CGBitmapContextCreate(NULL, bounds.size.width * scaleFactor, bounds.size.height * scaleFactor, 8, 4 * bounds.size.width * scaleFactor, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); +// CGContextScaleCTM(context, scaleFactor, scaleFactor); +// +// // Adjusts position and invert the image. +// // The OpenGL uses the image data upside-down compared commom image files. +// CGContextTranslateCTM(context, 0, bounds.size.height); +// CGContextScaleCTM(context, 1.0, -1.0); - UIGraphicsBeginImageContextWithOptions(bounds.size, opaque, 0.0); + [self _collectCompositingDisplayBlocks:displayBlocks context:context isCancelled:isCancelled]; for (dispatch_block_t block in displayBlocks) { if (isCancelled()) { @@ -167,36 +220,32 @@ block(); } - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); +// CGImageRef imageRef= CGBitmapContextCreateImage(context); +// UIImage *image = [[UIImage alloc] initWithCGImage:imageRef]; +// CGColorSpaceRelease(colorSpace); +// CGContextRelease(context); + + UIImage *image = [self endDrawContext]; return image; }; } -- (void)_collectDisplayBlocks:(NSMutableArray *)displayBlocks isCancelled:(BOOL(^)(void))isCancelled +- (void)_collectCompositingDisplayBlocks:(NSMutableArray *)displayBlocks context:(CGContextRef)context isCancelled:(BOOL(^)(void))isCancelled { - // compositingChild has no chance to applyPropertiesToView, so force updateNode - // if (_compositingChild) { - // if (_data) { - // dispatch_async(dispatch_get_main_queue(), ^{ - // [self updateNode:_data]; - // }); - // } - // } - + // TODO: compositingChild has no chance to applyPropertiesToView, need update here? UIColor *backgroundColor = _backgroundColor; BOOL clipsToBounds = _clipToBounds; CGRect frame = self.calculatedFrame; CGRect bounds = CGRectMake(0, 0, frame.size.width, frame.size.height); - if (_composite) { + if (_useCompositing) { frame.origin = CGPointMake(0, 0); } - WXDisplayBlock displayBlock = [self displayBlock]; + BOOL needsDrawRect = [self needsDrawRect]; - BOOL shouldDisplay = displayBlock || backgroundColor || CGPointEqualToPoint(CGPointZero, frame.origin) == NO || clipsToBounds; + BOOL shouldDisplay = needsDrawRect && (backgroundColor || CGPointEqualToPoint(CGPointZero, frame.origin) == NO || clipsToBounds); if (shouldDisplay) { dispatch_block_t displayBlockToPush = ^{ @@ -204,21 +253,17 @@ CGContextSaveGState(context); CGContextTranslateCTM(context, frame.origin.x, frame.origin.y); - if (_compositingChild && clipsToBounds) { - [[UIBezierPath bezierPathWithRect:bounds] addClip]; + if (isCancelled && isCancelled()) { + return ; } - CGColorRef backgroundCGColor = backgroundColor.CGColor; - if (backgroundColor && CGColorGetAlpha(backgroundCGColor) > 0.0) { - CGContextSetFillColorWithColor(context, backgroundCGColor); - CGContextFillRect(context, bounds); + if (_isCompositingChild && clipsToBounds) { + [[UIBezierPath bezierPathWithRect:bounds] addClip]; } - if (displayBlock) { - UIImage *image = displayBlock(bounds, isCancelled); - if (image) { - [image drawInRect:bounds]; - } + UIImage *image = [self drawRect:bounds]; + if (image) { + [image drawInRect:bounds]; } }; [displayBlocks addObject:[displayBlockToPush copy]]; @@ -226,13 +271,12 @@ for (WXComponent *component in self.subcomponents) { if (!isCancelled()) { - [component _collectDisplayBlocks:displayBlocks isCancelled:isCancelled]; + [component _collectCompositingDisplayBlocks:displayBlocks context:context isCancelled:isCancelled]; } } if (shouldDisplay) { dispatch_block_t blockToPop = ^{ - CGContextRef context = UIGraphicsGetCurrentContext(); CGContextRestoreGState(context); }; [displayBlocks addObject:[blockToPop copy]]; @@ -241,26 +285,6 @@ #pragma mark Border Drawing -- (UIImage *)_borderImage -{ - CGSize size = self.calculatedFrame.size; - if (size.width <= 0 || size.height <= 0) { - WXLogDebug(@"No need to draw border for %@, because width or height is zero", self.ref); - return nil; - } - - WXLogDebug(@"Begin to draw border for %@", self.ref); - UIGraphicsBeginImageContextWithOptions(size, NO, 0.0); - CGContextRef context = UIGraphicsGetCurrentContext(); - - [self _drawBorderWithContext:context size:size]; - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - return image; -} - - (void)_drawBorderWithContext:(CGContextRef)context size:(CGSize)size { CGRect rect = CGRectMake(0, 0, size.width, size.height); @@ -353,6 +377,10 @@ - (BOOL)_needsDrawBorder { + if (_isCompositingChild) { + return YES; + } + if (![_layer isKindOfClass:[WXLayer class]]) { // Only support WXLayer return NO; @@ -491,4 +519,25 @@ do {\ } } +- (BOOL)_bitmapOpaqueWithSize:(CGSize)size +{ + CGRect rect = CGRectMake(0, 0, size.width, size.height); + WXRoundedRect *borderRect = [[WXRoundedRect alloc] initWithRect:rect topLeft:_borderTopLeftRadius topRight:_borderTopRightRadius bottomLeft:_borderBottomLeftRadius bottomRight:_borderBottomRightRadius]; + WXRadii *radii = borderRect.radii; + BOOL hasBorderRadius = [radii hasBorderRadius]; + return (!hasBorderRadius) && CGColorGetAlpha(_backgroundColor.CGColor) == 1.0; +} + +#pragma mark - Deprecated + +- (WXDisplayBlock)displayBlock +{ + return [self _displayBlock]; +} + +- (WXDisplayCompletionBlock)displayCompletionBlock +{ + return nil; +} + @end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/c6d980d3/ios/sdk/WeexSDK/Sources/Display/WXRoundedRect.h ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Display/WXRoundedRect.h b/ios/sdk/WeexSDK/Sources/Display/WXRoundedRect.h index 9cabf8e..4cde88a 100644 --- a/ios/sdk/WeexSDK/Sources/Display/WXRoundedRect.h +++ b/ios/sdk/WeexSDK/Sources/Display/WXRoundedRect.h @@ -17,6 +17,8 @@ @property (nonatomic, assign) CGFloat bottomLeft; @property (nonatomic, assign) CGFloat bottomRight; +- (BOOL)hasBorderRadius; + @end @interface WXRoundedRect : NSObject http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/c6d980d3/ios/sdk/WeexSDK/Sources/Display/WXRoundedRect.mm ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Display/WXRoundedRect.mm b/ios/sdk/WeexSDK/Sources/Display/WXRoundedRect.mm index ae535dd..fb62465 100644 --- a/ios/sdk/WeexSDK/Sources/Display/WXRoundedRect.mm +++ b/ios/sdk/WeexSDK/Sources/Display/WXRoundedRect.mm @@ -26,6 +26,11 @@ return self; } +- (BOOL)hasBorderRadius +{ + return _topLeft > 0.001 || _topRight > 0.001 || _bottomLeft > 0.001 || _bottomRight > 0.001; +} + - (void)scale:(float)factor { if (factor == 1) { http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/c6d980d3/ios/sdk/WeexSDK/Sources/Model/WXComponent.h ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent.h b/ios/sdk/WeexSDK/Sources/Model/WXComponent.h index a2f75d7..6bd7cd3 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXComponent.h +++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.h @@ -324,34 +324,69 @@ NS_ASSUME_NONNULL_BEGIN /// @name Display ///-------------------------------------- -typedef UIImage * _Nonnull(^WXDisplayBlock)(CGRect bounds, BOOL(^isCancelled)(void)); -typedef void(^WXDisplayCompletionBlock)(CALayer *layer, BOOL finished); - /** * @abstract Marks the view as needing display. The method should be called on the main thread. + * @discussion You can use this method to notify the system that your component's contents need to be redrawn. This method makes a note of the request and returns immediately. The component is not actually redrawn until the next drawing cycle, at which point all invalidated components are updated. + * */ - (void)setNeedsDisplay; +- (CGContextRef)beginDrawContext:(CGRect)bounds; + +- (UIImage *)endDrawContext; + /** - * @abstract Return a block to be called to draw layer. - * - * @discussion The block returned will be called on any thread. - * + * @abstract Returns a Boolean indicating whether the component needs to be drawn by `drawRect:` + */ +- (BOOL)needsDrawRect; + +/** + * @abstract Draws the componentâs image within the passed-in rectangle. + * @parameter rect The rectangle which is the entire visible bounds of your component. + * @return A UIImage containing the contents of the current bitmap graphics context. + * @discussion + * Subclasses that use technologies such as Core Graphics and UIKit to draw their own componentâs content should override this method and implement their drawing code there. You do not need to override this method if your component sets its content in superclass's way. + * By the time this method is called, UIKit has configured the drawing environment appropriately for your view and you can simply call whatever drawing methods and functions you need to render your content. Specifically, Weex creates and configures a graphics context for drawing and adjusts the transform of that context so that its origin matches the origin of your componentsâs bounds rectangle. You can get a reference to the graphics context using the `UIGraphicsGetCurrentContext` function, but do not establish a strong reference to the graphics context because it can change between calls to the drawRect: method. + * If you already have an image that represents the content of the component, then you should just return the image and do no drawing, otherwise you should draw your content in the current context and return nil. + * You should never call this method directly yourself. To invalidate part of your component's content, and thus cause that portion to be redrawn, call the `setNeedsDisplay` method instead. + */ +- (UIImage *)drawRect:(CGRect)rect; + +/** + * @abstract Called when a component finishes rendering its content. + * @discussion Do not call this method directly. Weex calls this method at appropriate times to finish updating the component's content. + * Subclasses can override this method to perform additional work on components that were rendered. */ -- (WXDisplayBlock)displayBlock; +- (void)displayDidFinished:(BOOL)success; /** - * readyToRender + * readyToRender, do not use it, will be deprecated soon */ - (void)readyToRender; +@end + +@interface WXComponent (Deprecated) + +typedef UIImage * _Nonnull(^WXDisplayBlock)(CGRect bounds, BOOL(^isCancelled)(void)); +typedef void(^WXDisplayCompletionBlock)(CALayer *layer, BOOL finished); + +/** + * @abstract Return a block to be called to draw layer. + * + * @discussion The block returned will be called on any thread. + * + */ +- (WXDisplayBlock)displayBlock DEPRECATED_MSG_ATTRIBUTE("use drawRect method instead."); + /** * @abstract Return a block to be called while drawing is finished. * * @discussion The block returned will be called on main thread. * */ -- (WXDisplayCompletionBlock)displayCompletionBlock; +- (WXDisplayCompletionBlock)displayCompletionBlock DEPRECATED_MSG_ATTRIBUTE("use displayDidFinished method instead."); + @end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/c6d980d3/ios/sdk/WeexSDK/Sources/Model/WXComponent.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m index cecc708..08a1bcc 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m +++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m @@ -95,6 +95,7 @@ [self _setupNavBarWithStyles:_styles attributes:_attributes]; [self _initCSSNodeWithStyles:_styles]; [self _initViewPropertyWithStyles:_styles]; + [self _initCompositingAttribute:_attributes]; [self _handleBorders:styles isUpdating:NO]; } @@ -180,7 +181,7 @@ WXAssertMainThread(); // compositing child will be drew by its composited ancestor - if (_compositingChild) { + if (_isCompositingChild) { return nil; } @@ -332,6 +333,10 @@ subcomponent->_isNeedJoinLayoutSystem = NO; } + if (_useCompositing || _isCompositingChild) { + subcomponent->_isCompositingChild = YES; + } + [self _recomputeCSSNodeChildren]; [self setNeedsLayout]; } http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/c6d980d3/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m index 83bcd7d..66985a9 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m +++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m @@ -292,8 +292,10 @@ typedef enum : NSUInteger { } [[WXSDKManager bridgeMgr] destroyInstance:self.instanceId]; - - [self.componentManager invalidate]; + + if (_componentManager) { + [_componentManager invalidate]; + } __weak typeof(self) weakSelf = self; WXPerformBlockOnComponentThread(^{ __strong typeof(self) strongSelf = weakSelf;