diff --git a/framework/examples/ios-demo/HippyDemo/PageManager/HippyPageCache.h b/framework/examples/ios-demo/HippyDemo/PageManager/HippyPageCache.h index 58b1c7ad776..3aa05d6be61 100644 --- a/framework/examples/ios-demo/HippyDemo/PageManager/HippyPageCache.h +++ b/framework/examples/ios-demo/HippyDemo/PageManager/HippyPageCache.h @@ -34,7 +34,7 @@ typedef NS_ENUM(NSUInteger, RenderType) { RenderTypeNative, }; -@class HippyBridge; +@class HippyBridge, HippyRootView; @class HippyPageCacheManager, HippyPageCache; @protocol HippyPageCacheManagerObserverProtocol @@ -56,7 +56,7 @@ typedef NS_ENUM(NSUInteger, RenderType) { @interface HippyPageCache : NSObject @property(nonatomic, strong) HippyBridge *hippyBridge; -@property(nonatomic, strong) UIView *rootView; +@property(nonatomic, strong) HippyRootView *rootView; @property(nonatomic, strong, nullable) UIImage *snapshot; @property(nonatomic, assign) DriverType driverType; diff --git a/framework/examples/ios-demo/HippyDemo/PageManager/HippyPageCache.m b/framework/examples/ios-demo/HippyDemo/PageManager/HippyPageCache.m index 71443b975c1..ab32189dbf7 100644 --- a/framework/examples/ios-demo/HippyDemo/PageManager/HippyPageCache.m +++ b/framework/examples/ios-demo/HippyDemo/PageManager/HippyPageCache.m @@ -21,6 +21,7 @@ */ #import "HippyPageCache.h" +#import @implementation HippyPageCache diff --git a/framework/examples/ios-demo/HippyDemo/RenderPage/HippyDemoViewController.mm b/framework/examples/ios-demo/HippyDemo/RenderPage/HippyDemoViewController.mm index dbaf8fcf2fb..d4a82cc453c 100644 --- a/framework/examples/ios-demo/HippyDemo/RenderPage/HippyDemoViewController.mm +++ b/framework/examples/ios-demo/HippyDemo/RenderPage/HippyDemoViewController.mm @@ -42,7 +42,7 @@ @interface HippyDemoViewController () +/// The bridge delegate @property (nonatomic, weak, readonly) id delegate; +/// SDK launch config +/// TODO: 优化 launchOptions 参数 @property (nonatomic, copy, readonly) NSDictionary *launchOptions; - /// Create A HippyBridge instance, without load/execute any js bundle. /// /// @param delegate bridge delegate @@ -159,6 +161,7 @@ HIPPY_EXTERN NSString *HippyBridgeModuleNameForClass(Class bridgeModuleClass); - (void)loadBundleURL:(NSURL *)bundleURL completion:(void (^_Nullable)(NSURL * _Nullable, NSError * _Nullable))completion; + @property(nonatomic, assign)std::weak_ptr VFSUriLoader; /** @@ -213,11 +216,13 @@ HIPPY_EXTERN NSString *HippyBridgeModuleNameForClass(Class bridgeModuleClass); - (void)handleBuffer:(id _Nullable)buffer batchEnded:(BOOL)batchEnded; + +/// <#Description#> +/// - Parameter isInspectable: <#isInspectable description#> - (void)setInspectable:(BOOL)isInspectable; -/** - * All registered bridge module classes. - */ + +/// All registered bridge module classes. @property (nonatomic, copy, readonly) NSArray *moduleClasses; - (NSString *)moduleConfig; @@ -302,7 +307,7 @@ HIPPY_EXTERN NSString *HippyBridgeModuleNameForClass(Class bridgeModuleClass); -- (void)setRootView:(HippyRootView *)rootView; +- (void)setRootView:(UIView *)rootView; - (void)resetRootSize:(CGSize)size; @@ -322,18 +327,6 @@ HIPPY_EXTERN NSString *HippyBridgeModuleNameForClass(Class bridgeModuleClass); @end -@interface HippyBridge (RedBoxDebug) - -/// The last current active bridge instance. -+ (instancetype)currentBridge; - -/// Record the last active bridge instance. -/// - Parameter currentBridge: bridge instance, pass nil to reset. -+ (void)setCurrentBridge:(nullable HippyBridge *)currentBridge; - -@end - - HIPPY_EXTERN void HippyBridgeFatal(NSError *, HippyBridge *); HIPPY_EXTERN void HippyBridgeHandleException(NSException *exception, HippyBridge *bridge); diff --git a/framework/ios/base/bridge/HippyBridge.mm b/framework/ios/base/bridge/HippyBridge.mm index e40759488a2..eaa4c2433bc 100644 --- a/framework/ios/base/bridge/HippyBridge.mm +++ b/framework/ios/base/bridge/HippyBridge.mm @@ -937,9 +937,6 @@ - (void)invalidate { _startTime = footstone::TimePoint::SystemNow(); self.moduleSemaphore = nil; - if ([HippyBridge currentBridge] == self) { - [HippyBridge setCurrentBridge:nil]; - } dispatch_group_notify(group, dispatch_get_main_queue(), ^{ [jsExecutor executeBlockOnJavaScriptQueue:^{ @autoreleasepool { @@ -1142,7 +1139,7 @@ - (void)setSnapShotData:(NSData *)data { //FIXME: 调整优化 -- (void)setRootView:(HippyRootView *)rootView { +- (void)setRootView:(UIView *)rootView { auto engineResource = [[HippyJSEnginesMapper defaultInstance] JSEngineResourceForKey:self.engineKey]; auto domManager = engineResource->GetDomManager(); NSNumber *rootTag = [rootView hippyTag]; @@ -1205,25 +1202,3 @@ void HippyBridgeHandleException(NSException *exception, HippyBridge *bridge) { HippyHandleException(exception); } - -#pragma mark - - -@implementation HippyBridge (RedBoxDebug) - -static HippyBridge *HippyCurrentBridgeInstance = nil; - -/** - * The last current active bridge instance. This is set automatically whenever - * the bridge is accessed. It can be useful for static functions or singletons - * that need to access the bridge for purposes such as logging, but should not - * be relied upon to return any particular instance, due to race conditions. - */ -+ (instancetype)currentBridge { - return HippyCurrentBridgeInstance; -} - -+ (void)setCurrentBridge:(nullable HippyBridge *)currentBridge { - HippyCurrentBridgeInstance = currentBridge; -} - -@end diff --git a/framework/ios/module/dev/HippyRedBox.h b/framework/ios/module/dev/HippyRedBox.h index f72091915ce..87f0e397950 100644 --- a/framework/ios/module/dev/HippyRedBox.h +++ b/framework/ios/module/dev/HippyRedBox.h @@ -50,4 +50,13 @@ @property (nonatomic, readonly) HippyRedBox *redBox; +/// The last current active bridge instance. ++ (nullable id)currentBridge; + +/// Record the last active bridge instance. +/// - Parameter currentBridge: bridge instance, pass nil to reset. ++ (void)setCurrentBridge:(nullable HippyBridge *)currentBridge; + @end + + diff --git a/framework/ios/module/dev/HippyRedBox.mm b/framework/ios/module/dev/HippyRedBox.mm index 3025f2c8fa2..f90215a110e 100644 --- a/framework/ios/module/dev/HippyRedBox.mm +++ b/framework/ios/module/dev/HippyRedBox.mm @@ -24,7 +24,7 @@ #import "HippyErrorInfo.h" #import "HippyRedBox.h" #import "HippyUtils.h" - +#import "HippyWeakProxy.h" #import "HippyAsserts.h" #import "HippyConvert.h" #import "HippyJSStackFrame.h" @@ -428,14 +428,36 @@ - (void)reloadFromRedBoxWindow:(__unused HippyRedBoxWindow *)redBoxWindow { @end + +#pragma mark - + + @implementation HippyBridge (HippyRedBox) - (HippyRedBox *)redBox { return [self moduleForClass:[HippyRedBox class]]; } +static HippyWeakProxy *HippyCurrentBridgeInstance = nil; + +/** + * The last current active bridge instance. This is set automatically whenever + * the bridge is accessed. It can be useful for static functions or singletons + * that need to access the bridge for purposes such as logging, but should not + * be relied upon to return any particular instance, due to race conditions. + */ ++ (instancetype)currentBridge { + return (id)HippyCurrentBridgeInstance; +} + ++ (void)setCurrentBridge:(nullable HippyBridge *)currentBridge { + HippyCurrentBridgeInstance = [HippyWeakProxy weakProxyForObject:currentBridge]; +} + + @end + #else // Disabled @implementation HippyRedBox diff --git a/framework/ios/utils/HippyWeakProxy.h b/framework/ios/utils/HippyWeakProxy.h new file mode 100644 index 00000000000..05e66b4624a --- /dev/null +++ b/framework/ios/utils/HippyWeakProxy.h @@ -0,0 +1,33 @@ +/*! + * iOS SDK + * + * Tencent is pleased to support the open source community by making + * Hippy available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface HippyWeakProxy : NSProxy + ++ (instancetype)weakProxyForObject:(id)target; + +@end + +NS_ASSUME_NONNULL_END diff --git a/framework/ios/utils/HippyWeakProxy.m b/framework/ios/utils/HippyWeakProxy.m new file mode 100644 index 00000000000..597bd8cc8b1 --- /dev/null +++ b/framework/ios/utils/HippyWeakProxy.m @@ -0,0 +1,67 @@ +/*! + * iOS SDK + * + * Tencent is pleased to support the open source community by making + * Hippy available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "HippyWeakProxy.h" + +@interface HippyWeakProxy () + +@property (nonatomic, weak) id target; + +@end + +@implementation HippyWeakProxy + ++ (instancetype)weakProxyForObject:(id)target { + HippyWeakProxy *proxy = [HippyWeakProxy alloc]; + proxy.target = target; + return proxy; +} + +- (id)forwardingTargetForSelector:(SEL)aSelector { + return _target; +} + +- (BOOL)respondsToSelector:(SEL)aSelector { + return [_target respondsToSelector:aSelector]; +} + +#pragma mark Handling Unimplemented Methods + +- (void)forwardInvocation:(NSInvocation *)invocation { + // Fallback for when target is nil. Don't do anything, just return 0/NULL/nil. + // The method signature we've received to get here is just a dummy to keep `doesNotRecognizeSelector:` from firing. + // We can't really handle struct return types here because we don't know the length. + void *nullPointer = NULL; + [invocation setReturnValue:&nullPointer]; +} + +- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector { + // We only get here if `forwardingTargetForSelector:` returns nil. + // In that case, our weak target has been reclaimed. Return a dummy method signature to keep `doesNotRecognizeSelector:` from firing. + // We'll emulate the Obj-c messaging nil behavior by setting the return value to nil in `forwardInvocation:`, but we'll assume that the return + // value is `sizeof(void *)`. Other libraries handle this situation by making use of a global method signature cache, but that seems heavier than + // necessary and has issues as well. See https://www.mikeash.com/pyblog/friday-qa-2010-02-26-futures.html and + // https://github.com/steipete/PSTDelegateProxy/issues/1 for examples of using a method signature cache. + return [NSObject instanceMethodSignatureForSelector:@selector(init)]; +} + +@end diff --git a/modules/ios/base/HippyLog.mm b/modules/ios/base/HippyLog.mm index 55e3d3f57b1..c2881036d49 100644 --- a/modules/ios/base/HippyLog.mm +++ b/modules/ios/base/HippyLog.mm @@ -187,7 +187,7 @@ void HippyLogNativeInternal(HippyLogLevel level, const char *fileName, int lineN dispatch_async(dispatch_get_main_queue(), ^{ // red box is thread safe, but by deferring to main queue we avoid a startup // race condition that causes the module to be accessed before it has loaded - [[HippyBridge currentBridge].redBox showErrorMessage:message withStack:stack]; + [((HippyBridge *)[HippyBridge currentBridge]).redBox showErrorMessage:message withStack:stack]; }); } #endif diff --git a/renderer/native/ios/renderer/HippyComponentMap.mm b/renderer/native/ios/renderer/HippyComponentMap.mm index 3db72828818..c3b70e2c6d6 100644 --- a/renderer/native/ios/renderer/HippyComponentMap.mm +++ b/renderer/native/ios/renderer/HippyComponentMap.mm @@ -27,8 +27,8 @@ using RootNode = hippy::RootNode; @interface HippyComponentMap () { + NSMapTable> *_rootComponentsMap; NSMutableDictionary> *> *_componentsMap; - NSMutableDictionary> *_rootComponentsMap; std::unordered_map> _rootNodesMap; } @@ -39,8 +39,8 @@ @implementation HippyComponentMap - (instancetype)init { self = [super init]; if (self) { - _componentsMap = [NSMutableDictionary dictionaryWithCapacity:256]; - _rootComponentsMap = [NSMutableDictionary dictionaryWithCapacity:8]; + _rootComponentsMap = [NSMapTable strongToWeakObjectsMapTable]; + _componentsMap = [NSMutableDictionary dictionary]; _rootNodesMap.reserve(8); } return self; @@ -56,7 +56,7 @@ - (void)addRootComponent:(id)component NSAssert(component && tag, @"component &&tag must not be null in method %@", NSStringFromSelector(_cmd)); NSAssert([self threadCheck], @"%@ method needs run in main thread", NSStringFromSelector(_cmd)); if (component && tag && ![_componentsMap objectForKey:tag]) { - NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithCapacity:256]; + NSMutableDictionary *dic = [NSMutableDictionary dictionary]; [dic setObject:component forKey:tag]; [_componentsMap setObject:dic forKey:tag]; [_rootComponentsMap setObject:component forKey:tag]; @@ -79,7 +79,7 @@ - (BOOL)containRootComponentWithTag:(NSNumber *)tag { } - (NSArray> *)rootComponents { - return [_rootComponentsMap allValues]; + return [[_rootComponentsMap objectEnumerator] allObjects]; } - (__kindof id)rootComponentForTag:(NSNumber *)tag { diff --git a/renderer/native/ios/renderer/HippyRootView.h b/renderer/native/ios/renderer/HippyRootView.h index f9d5cf55fdf..b7ad9746ca3 100644 --- a/renderer/native/ios/renderer/HippyRootView.h +++ b/renderer/native/ios/renderer/HippyRootView.h @@ -25,6 +25,20 @@ @class HippyBridge; +/** + * This enum is used to define size flexibility type of the root view. + * If a dimension is flexible, the view will recalculate that dimension + * so the content fits. Recalculations are performed when the root's frame, + * size flexibility mode or content size changes. After a recalculation, + * rootViewDidChangeIntrinsicSize method of the HippyRootViewDelegate will be called. + */ +typedef NS_ENUM(NSInteger, HippyRootViewSizeFlexibility) { + HippyRootViewSizeFlexibilityNone = 0, + HippyRootViewSizeFlexibilityWidth, + HippyRootViewSizeFlexibilityHeight, + HippyRootViewSizeFlexibilityWidthAndHeight, +}; + /// This notification is sent when the first subviews are added to the root view /// after the application has loaded. This is used to hide the `loadingView`, and @@ -43,6 +57,28 @@ extern NSString *const HippySecondaryBundleDidLoadNotification DEPRECATED_MSG_AT /// all controlled by the same JavaScript application. @interface HippyRootView : UIView +/// The delegate of hippyRootView. +@property (nonatomic, weak) id delegate; + +/// The name of the JavaScript module to execute within the +/// specified scriptURL (required). Setting this will not have +/// any immediate effect, but it must be done prior to loading the script. +@property (nonatomic, copy, readonly) NSString *moduleName; + +/// The bridge used by the root view. Bridges can be shared between multiple +/// root views, so you can use this property to initialize another HippyRootView. +@property (nonatomic, strong, readonly) HippyBridge *bridge; + +/// The properties to apply to the view. Use this property to update +/// application properties and rerender the view. Initialized with +/// initialProperties argument of the initializer. +/// Set this property only on the main thread. +@property (nonatomic, copy, readwrite) NSDictionary *appProperties; + +/// The backing view controller of the root view. +@property (nonatomic, weak) UIViewController *hippyViewController; + + /// Create HippyRootView instance /// /// @param bridge the hippyBridge instance @@ -69,32 +105,11 @@ extern NSString *const HippySecondaryBundleDidLoadNotification DEPRECATED_MSG_AT initialProperties:(NSDictionary *)initialProperties delegate:(id)delegate; -/// The delegate of hippyRootView. -@property (nonatomic, weak) id delegate; - -/// The name of the JavaScript module to execute within the -/// specified scriptURL (required). Setting this will not have -/// any immediate effect, but it must be done prior to loading the script. -@property (nonatomic, copy, readonly) NSString *moduleName; - -/// The bridge used by the root view. Bridges can be shared between multiple -/// root views, so you can use this property to initialize another HippyRootView. -@property (nonatomic, strong, readonly) HippyBridge *bridge; -/// The properties to apply to the view. Use this property to update -/// application properties and rerender the view. Initialized with -/// initialProperties argument of the initializer. -/// Set this property only on the main thread. -@property (nonatomic, copy, readwrite) NSDictionary *appProperties; - -/// The backing view controller of the root view. -@property (nonatomic, weak) UIViewController *hippyViewController; - - -/// Run Hippy -/// +/// Run Hippy! /// This is the Hippy program entry. /// +/// Note: If init with businessURL, not need to call this method again. - (void)runHippyApplication; diff --git a/renderer/native/ios/renderer/HippyRootView.mm b/renderer/native/ios/renderer/HippyRootView.mm index d0d044e092a..5fe046e4950 100644 --- a/renderer/native/ios/renderer/HippyRootView.mm +++ b/renderer/native/ios/renderer/HippyRootView.mm @@ -30,6 +30,7 @@ #import "HippyDeviceBaseInfo.h" #include + NSString *const HippyContentDidAppearNotification = @"HippyContentDidAppearNotification"; NSString *const HippySecondaryBundleDidLoadNotification = @"HippySecondaryBundleDidLoadNotification"; @@ -42,11 +43,25 @@ } +@interface HippyRootContentView : HippyView + +@property (nonatomic, readonly) BOOL contentHasAppeared; +//@property (nonatomic, strong) HippyTouchHandler *touchHandler; +@property (nonatomic, assign) int64_t startTimpStamp; + +- (instancetype)initWithFrame:(CGRect)frame + bridge:(HippyBridge *)bridge + hippyTag:(NSNumber *)hippyTag + sizeFlexiblity:(HippyRootViewSizeFlexibility)sizeFlexibility NS_DESIGNATED_INITIALIZER; + +@end + @interface HippyRootView () { BOOL _contentHasAppeared; } +@property (nonatomic, strong) HippyRootContentView *contentView; @property (nonatomic, strong) NSDictionary *shareOptions; @end @@ -69,13 +84,13 @@ - (instancetype)initWithBridge:(HippyBridge *)bridge self.backgroundColor = [UIColor clearColor]; _bridge = bridge; - if (nil == _bridge.moduleName) { + if (!_bridge.moduleName) { _bridge.moduleName = moduleName; } _moduleName = moduleName; _appProperties = [initialProperties copy]; _delegate = delegate; - self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + // [[NSNotificationCenter defaultCenter] addObserver:self // selector:@selector(javaScriptDidLoad:) @@ -134,21 +149,39 @@ - (instancetype)initWithBridge:(HippyBridge *)bridge } - (void)dealloc { + [_contentView invalidate]; if ([_delegate respondsToSelector:@selector(rootViewWillBePurged:)]) { [_delegate rootViewWillBePurged:self]; } + [_bridge unloadInstanceForRootView:self.hippyTag]; HippyLogInfo(@"[Hippy_OC_Log][Life_Circle],HippyRootView dealloc %p", self); } +- (void)contentViewInvalidated { + [_contentView removeFromSuperview]; + _contentView = nil; +} + + - (void)runHippyApplication { // [_bridge.performanceLogger markStartForTag:HippyPLRunApplication]; - + __weak __typeof(self)weakSelf = self; dispatch_async(dispatch_get_main_queue(), ^{ __strong __typeof(weakSelf)strongSelf = weakSelf; + + [strongSelf.contentView removeFromSuperview]; + // todo: ContentRootView sizeFlexibility feature + HippyRootContentView *contentView = [[HippyRootContentView alloc] initWithFrame:strongSelf.bounds + bridge:strongSelf.bridge + hippyTag:strongSelf.hippyTag + sizeFlexiblity:HippyRootViewSizeFlexibilityWidthAndHeight]; + // 注册RootView - [strongSelf.bridge setRootView:strongSelf]; + [strongSelf.bridge setRootView:contentView]; [strongSelf.bridge loadInstanceForRootView:strongSelf.hippyTag withProperties:strongSelf.appProperties]; + strongSelf.contentView = contentView; + [strongSelf insertSubview:contentView atIndex:0]; HippyLogInfo(@"[Hippy_OC_Log][Life_Circle],Running application %@ (%@)", strongSelf.moduleName, strongSelf.appProperties); }); } @@ -191,27 +224,6 @@ - (void)javaScriptDidFailToLoad:(NSNotification *)notification { } } - -#pragma mark - HippyComponent Method - -- (void)insertHippySubview:(UIView *)subview atIndex:(NSInteger)atIndex { - [super insertHippySubview:subview atIndex:atIndex]; - // [_bridge.performanceLogger markStopForTag:HippyPLTTI]; - - __weak __typeof(self)weakSelf = self; - dispatch_async(dispatch_get_main_queue(), ^{ - __strong __typeof(weakSelf)strongSelf = weakSelf; - if (strongSelf && !strongSelf->_contentHasAppeared) { - strongSelf->_contentHasAppeared = YES; - // int64_t cost = [strongSelf.bridge.performanceLogger durationForTag:HippyPLTTI]; - [[NSNotificationCenter defaultCenter] postNotificationName:HippyContentDidAppearNotification - object:self userInfo:@{ - // @"cost": @(cost) - }]; - } - }); -} - - (void)setAppProperties:(NSDictionary *)appProperties { HippyAssertMainQueue(); @@ -251,3 +263,75 @@ - (void)onHostControllerTransitionedToSize:(CGSize)size { } @end + + + +#pragma mark - HippyRootContentView + +@implementation HippyRootContentView { + __weak HippyBridge *_bridge; + UIColor *_backgroundColor; +} + +- (instancetype)initWithFrame:(CGRect)frame + bridge:(HippyBridge *)bridge + hippyTag:(NSNumber *)hippyTag + sizeFlexiblity:(HippyRootViewSizeFlexibility)sizeFlexibility { + if ((self = [super initWithFrame:frame])) { + _bridge = bridge; + self.hippyTag = hippyTag; + + // FIXME: HippyTouchHandler +// _touchHandler = [[HippyTouchHandler alloc] initWithRootView:self bridge:bridge]; +// [self addGestureRecognizer:_touchHandler]; + + self.layer.backgroundColor = NULL; + _startTimpStamp = CACurrentMediaTime() * 1000; + } + return self; +} + +HIPPY_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame) +HIPPY_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (nonnull NSCoder *)aDecoder) + + +// FIXME: check +//- (void)setFrame:(CGRect)frame { +// CGRect originFrame = self.frame; +// if (!CGRectEqualToRect(originFrame, frame)) { +// super.frame = frame; +// if (self.hippyTag && _bridge.isValid) { +// [_bridge.uiManager setFrame:frame fromOriginFrame:originFrame forView:self]; +// } +// } +//} + +#pragma mark - HippyComponent Method + +- (void)insertHippySubview:(UIView *)subview atIndex:(NSInteger)atIndex { + [super insertHippySubview:subview atIndex:atIndex]; + // [_bridge.performanceLogger markStopForTag:HippyPLTTI]; + + __weak __typeof(self)weakSelf = self; + dispatch_async(dispatch_get_main_queue(), ^{ + __strong __typeof(weakSelf)strongSelf = weakSelf; + if (strongSelf && !strongSelf->_contentHasAppeared) { + strongSelf->_contentHasAppeared = YES; + // int64_t cost = [strongSelf.bridge.performanceLogger durationForTag:HippyPLTTI]; + [[NSNotificationCenter defaultCenter] postNotificationName:HippyContentDidAppearNotification + object:self userInfo:@{ + // @"cost": @(cost) + }]; + } + }); +} + +- (void)invalidate { + if (self.userInteractionEnabled) { + self.userInteractionEnabled = NO; + [(HippyRootView *)self.superview contentViewInvalidated]; + } +} + + +@end diff --git a/renderer/native/ios/renderer/HippyUIManager.mm b/renderer/native/ios/renderer/HippyUIManager.mm index 4d4a6eef232..548405e3ab3 100644 --- a/renderer/native/ios/renderer/HippyUIManager.mm +++ b/renderer/native/ios/renderer/HippyUIManager.mm @@ -179,11 +179,9 @@ @interface HippyUIManager() { NSMutableDictionary *_viewManagers; NSArray *_extraComponents; - std::weak_ptr _VFSUriLoader; NSMutableArray> *_imageProviders; std::function _rootViewSizeChangedCb; - std::weak_ptr _renderManager; } @end @@ -1476,14 +1474,6 @@ - (NSDictionary *)mergeProps:(NSDictionary *)newProps oldProps:(NSDictionary *)o return tmpProps; } -- (void)setVFSUriLoader:(std::weak_ptr)loader { - _VFSUriLoader = loader; -} - -- (std::weak_ptr)VFSUriLoader { - return _VFSUriLoader; -} - - (void)setRootViewSizeChangedEvent:(std::function)cb { _rootViewSizeChangedCb = cb; }