diff --git a/framework/examples/ios-demo/HippyDemo/HippyConvenientBridge.h b/framework/examples/ios-demo/HippyDemo/HippyConvenientBridge.h deleted file mode 100644 index 52e19293dc2..00000000000 --- a/framework/examples/ios-demo/HippyDemo/HippyConvenientBridge.h +++ /dev/null @@ -1,87 +0,0 @@ -/*! - * 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 -#import - -#import "HippyModulesSetup.h" - -NS_ASSUME_NONNULL_BEGIN - -typedef void(^_Nullable HippyBridgeBundleLoadCompletion)(NSURL *_Nullable, NSError *_Nullable); - -@protocol HippyBridgeDelegate, HippyImageProviderProtocol, HippyMethodInterceptorProtocol; - -/** - * Convenient class for adative 2.0 interface - */ -@interface HippyConvenientBridge : NSObject - -@property(nonatomic, readonly) HippyBridge *bridge; -//Properties that must be set -@property(nonatomic, copy) NSString *moduleName; -@property(nonatomic, copy) NSString *contextName; -@property(nonatomic, strong) NSURL *sandboxDirectory; - -//Optional properties -@property(nonatomic, weak) id methodInterceptor; -@property(nonatomic, readonly, weak) id delegate; - -//Methods that must be called -- (instancetype)initWithDelegate:(id _Nullable)delegate - moduleProvider:(HippyBridgeModuleProviderBlock _Nullable)block - extraComponents:(NSArray * _Nullable)extraComponents - launchOptions:(NSDictionary * _Nullable)launchOptions - engineKey:(NSString *_Nullable)engineKey; - -- (void)loadBundleURL:(NSURL *)bundleURL completion:(HippyBridgeBundleLoadCompletion)completion; - -//Load debug url specified by [HippyBundleURLProvider sharedInstance] -//and `_debugMode` variable in HippyBridge will be set to YES -- (void)loadDebugBundleCompletion:(HippyBridgeBundleLoadCompletion)completion; - -- (void)setRootView:(UIView *)rootView; - -- (void)resetRootSize:(CGSize)size; - -- (void)loadInstanceForRootViewTag:(NSNumber *)tag props:(NSDictionary *)props; - -- (void)unloadRootViewByTag:(NSNumber *)tag; - -- (void)addExtraComponents:(NSArray *)components; - -- (void)setInspectable:(BOOL)inspectable; - -//Optianl properties set -- (void)addImageProviderClass:(Class)cls; - -#pragma mark event -- (void)sendEvent:(NSString *)eventName params:(NSDictionary *_Nullable)params; - -#pragma mark snap shot -- (NSData *)snapShotData; - -- (void)setSnapShotData:(NSData *)data; - -@end - -NS_ASSUME_NONNULL_END diff --git a/framework/examples/ios-demo/HippyDemo/HippyConvenientBridge.mm b/framework/examples/ios-demo/HippyDemo/HippyConvenientBridge.mm deleted file mode 100644 index a1f703f6dc6..00000000000 --- a/framework/examples/ios-demo/HippyDemo/HippyConvenientBridge.mm +++ /dev/null @@ -1,285 +0,0 @@ -/*! - * 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 "HippyConvenientBridge.h" - -#import "HippyBridge.h" -#import "HippyBundleURLProvider.h" -#import "HippyJSEnginesMapper.h" -#import "HippyFileHandler.h" -#import "HippyMethodInterceptorProtocol.h" -#import "NativeRenderManager.h" -#import "HippyDefaultImageProvider.h" -#import "HippyLog.h" -#import "UIView+Hippy.h" -#import "VFSUriLoader.h" - -#include -#include - -#include "dom/root_node.h" - -@interface HippyConvenientBridge () { - HippyBridge *_bridge; - std::shared_ptr _nativeRenderManager; - std::shared_ptr _rootNode; - std::shared_ptr _demoLoader; - NSString *_engineKey; - NSArray *_extraComponents; -} - -@end - -@implementation HippyConvenientBridge - -@synthesize bridge = _bridge; - -- (instancetype)initWithDelegate:(id _Nullable)delegate - moduleProvider:(HippyBridgeModuleProviderBlock _Nullable)block - extraComponents:(NSArray * _Nullable)extraComponents - launchOptions:(NSDictionary * _Nullable)launchOptions - engineKey:(NSString *_Nullable)engineKey { - self = [super init]; - if (self) { - _delegate = delegate; - _bridge = [[HippyBridge alloc] initWithDelegate:self moduleProvider:block - launchOptions:launchOptions engineKey:engineKey]; - _engineKey = engineKey; - _extraComponents = extraComponents; - [_bridge addImageProviderClass:[HippyDefaultImageProvider class]]; - [_bridge setVFSUriLoader:[self URILoader]]; - [self setUpNativeRenderManager]; - } - return self; -} - -- (NSString *)engineKey { - return _engineKey ?: [NSString stringWithFormat:@"%p", self]; -} - -- (void)setUpNativeRenderManager { - auto engineResource = [[HippyJSEnginesMapper defaultInstance] JSEngineResourceForKey:[self engineKey]]; - auto domManager = engineResource->GetDomManager(); - //Create NativeRenderManager - _nativeRenderManager = std::make_shared(); - _nativeRenderManager->Initialize(); - //set dom manager - _nativeRenderManager->SetDomManager(domManager); - //set image provider for native render manager - _nativeRenderManager->AddImageProviderClass([HippyDefaultImageProvider class]); - _nativeRenderManager->RegisterExtraComponent(_extraComponents); - _nativeRenderManager->SetVFSUriLoader([self URILoader]); - _nativeRenderManager->SetHippyBridge(self.bridge); - _bridge.renderManager = _nativeRenderManager; -} - -- (std::shared_ptr)URILoader { - if (!_demoLoader) { - auto demoHandler = std::make_shared(); - _demoLoader = std::make_shared(); - _demoLoader->PushDefaultHandler(demoHandler); - _demoLoader->AddConvenientDefaultHandler(demoHandler); - auto fileHandler = std::make_shared(_bridge); - _demoLoader->RegisterConvenientUriHandler(@"hpfile", fileHandler); - } - return _demoLoader; -} - -- (void)setModuleName:(NSString *)moduleName { - _bridge.moduleName = moduleName; -} - -- (NSString *)moduleName { - return _bridge.moduleName; -} - -- (void)setContextName:(NSString *)contextName { - _bridge.contextName = contextName; -} - -- (NSString *)contextName { - return _bridge.contextName; -} - -- (void)setSandboxDirectory:(NSURL *)sandboxDirectory { - _bridge.sandboxDirectory = sandboxDirectory; -} - -- (NSURL *)sandboxDirectory { - return _bridge.sandboxDirectory; -} - -- (void)setMethodInterceptor:(id)methodInterceptor { - _bridge.methodInterceptor = methodInterceptor; -} - -- (id)methodInterceptor { - return _bridge.methodInterceptor; -} - -- (void)loadBundleURL:(NSURL *)bundleURL completion:(HippyBridgeBundleLoadCompletion)completion { - [_bridge loadBundleURL:bundleURL completion:completion]; -} - -- (void)loadDebugBundleCompletion:(HippyBridgeBundleLoadCompletion)completion { - _bridge.debugMode = YES; - NSString *bundleStr = [HippyBundleURLProvider sharedInstance].bundleURLString; - NSURL *bundleUrl = [NSURL URLWithString:bundleStr]; - [_bridge loadBundleURL:bundleUrl completion:completion]; -} - -- (void)setRootView:(UIView *)rootView { - auto engineResource = [[HippyJSEnginesMapper defaultInstance] JSEngineResourceForKey:[self engineKey]]; - auto domManager = engineResource->GetDomManager(); - NSNumber *rootTag = [rootView hippyTag]; - //Create a RootNode instance with a root tag - _rootNode = std::make_shared([rootTag unsignedIntValue]); - //Set RootNode for AnimationManager in RootNode - _rootNode->GetAnimationManager()->SetRootNode(_rootNode); - //Set DomManager for RootNode - _rootNode->SetDomManager(domManager); - //Set screen scale factor and size for Layout system in RooNode - _rootNode->GetLayoutNode()->SetScaleFactor([UIScreen mainScreen].scale); - _rootNode->SetRootSize(rootView.frame.size.width, rootView.frame.size.height); - _rootNode->SetRootOrigin(rootView.frame.origin.x, rootView.frame.origin.y); - - //set rendermanager for dommanager - if (!domManager->GetRenderManager().lock()) { - domManager->SetRenderManager(_nativeRenderManager); - } - //bind rootview and root node - _nativeRenderManager->RegisterRootView(rootView, _rootNode); - - __weak HippyBridge *weakBridge = _bridge; - auto cb = [weakBridge](int32_t tag, NSDictionary *params){ - HippyBridge *strongBridge = weakBridge; - if (strongBridge) { - [strongBridge rootViewSizeChangedEvent:@(tag) params:params]; - } - }; - _nativeRenderManager->SetRootViewSizeChangedEvent(cb); - //setup necessary params for bridge - [_bridge setupDomManager:domManager rootNode:_rootNode]; -} - -- (void)resetRootSize:(CGSize)size { - auto engineResource = [[HippyJSEnginesMapper defaultInstance] JSEngineResourceForKey:[self engineKey]]; - std::weak_ptr rootNode = _rootNode; - auto domManager = engineResource->GetDomManager(); - std::weak_ptr weakDomManager = domManager; - std::vector> ops = {[rootNode, weakDomManager, size](){ - auto strongRootNode = rootNode.lock(); - auto strongDomManager = weakDomManager.lock(); - if (strongRootNode && strongDomManager) { - strongRootNode->SetRootSize(size.width, size.height); - strongDomManager->DoLayout(strongRootNode); - strongDomManager->EndBatch(strongRootNode); - } - }}; - domManager->PostTask(hippy::dom::Scene(std::move(ops))); -} - -- (void)addExtraComponents:(NSArray *)components { - _nativeRenderManager->RegisterExtraComponent(components); -} - -- (void)loadInstanceForRootViewTag:(NSNumber *)tag props:(NSDictionary *)props { - [_bridge loadInstanceForRootView:tag withProperties:props]; -} - -- (void)unloadRootViewByTag:(NSNumber *)tag { - [_bridge unloadInstanceForRootView:tag]; - _nativeRenderManager->UnregisterRootView([tag intValue]); - if (_rootNode) { - _rootNode->ReleaseResources(); - _rootNode = nullptr; - } -} - -- (void)addImageProviderClass:(Class)cls { - [_bridge addImageProviderClass:cls]; - _nativeRenderManager->AddImageProviderClass([HippyDefaultImageProvider class]); -} - -- (void)setInspectable:(BOOL)inspectable { - [_bridge setInspectable:inspectable]; -} - -#pragma mark HippyBridge Delegate - -static BOOL SelectorBelongsToProtocol(SEL selector, Protocol *protocol) { - if (!selector || !protocol) { - return NO; - } - struct objc_method_description methodDesc = protocol_getMethodDescription(protocol, selector, NO, YES); - return selector == methodDesc.name; -} - -- (BOOL)respondsToSelector:(SEL)aSelector { - if (aSelector == @selector(invalidateForReason:bridge:)) { - return YES; - } - return [_delegate respondsToSelector:aSelector]; -} - -- (id)forwardingTargetForSelector:(SEL)aSelector { - if (SelectorBelongsToProtocol(aSelector, @protocol(HippyBridgeDelegate))) { - return _delegate; - } - return [super forwardingTargetForSelector:aSelector]; -} - -- (void)invalidateForReason:(HippyInvalidateReason)reason bridge:(HippyBridge *)bridge { - [_nativeRenderManager->rootViews() enumerateObjectsUsingBlock:^(UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { - if ([obj respondsToSelector:@selector(invalidate)]) { - [obj performSelector:@selector(invalidate)]; - } - [self unloadRootViewByTag:[obj hippyTag]]; - }]; - if ([_delegate respondsToSelector:@selector(invalidateForReason:bridge:)]) { - [_delegate invalidateForReason:reason bridge:bridge]; - } -} - -- (void)sendEvent:(NSString *)eventName params:(NSDictionary *_Nullable)params { - [self.bridge sendEvent:eventName params:params]; -} - -- (NSData *)snapShotData { - return [_bridge snapShotData]; -} - -- (void)setSnapShotData:(NSData *)data { - [_bridge setSnapShotData:data]; -} - -- (void)dealloc { - if (_demoLoader) { - _demoLoader->Terminate(); - } - if (_rootNode) { - _nativeRenderManager->RemoveVSyncEventListener(_rootNode); - _rootNode->ReleaseResources(); - } -} - -@end diff --git a/framework/examples/ios-demo/HippyDemo/PageManager/HippyPageCache.h b/framework/examples/ios-demo/HippyDemo/PageManager/HippyPageCache.h index 4d96db45398..58b1c7ad776 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 HippyConvenientBridge; +@class HippyBridge; @class HippyPageCacheManager, HippyPageCache; @protocol HippyPageCacheManagerObserverProtocol @@ -55,7 +55,7 @@ typedef NS_ENUM(NSUInteger, RenderType) { @interface HippyPageCache : NSObject -@property(nonatomic, strong) HippyConvenientBridge *convenientBridge; +@property(nonatomic, strong) HippyBridge *hippyBridge; @property(nonatomic, strong) UIView *rootView; @property(nonatomic, strong, nullable) UIImage *snapshot; diff --git a/framework/examples/ios-demo/HippyDemo/PageManager/HippyPageCache.m b/framework/examples/ios-demo/HippyDemo/PageManager/HippyPageCache.m index 1456217141e..71443b975c1 100644 --- a/framework/examples/ios-demo/HippyDemo/PageManager/HippyPageCache.m +++ b/framework/examples/ios-demo/HippyDemo/PageManager/HippyPageCache.m @@ -28,11 +28,11 @@ - (BOOL)isEqual:(id)object { if (![object isKindOfClass:[self class]]) { return NO; } - return _convenientBridge == [object convenientBridge]; + return _hippyBridge == [object hippyBridge]; } - (NSUInteger)hash { - return [(NSObject *)_convenientBridge hash] + [_rootView hash]; + return [(NSObject *)_hippyBridge hash] + [_rootView hash]; } @end diff --git a/framework/examples/ios-demo/HippyDemo/RenderPage/HippyDemoViewController.mm b/framework/examples/ios-demo/HippyDemo/RenderPage/HippyDemoViewController.mm index b56d97491bf..a8fee04be42 100644 --- a/framework/examples/ios-demo/HippyDemo/RenderPage/HippyDemoViewController.mm +++ b/framework/examples/ios-demo/HippyDemo/RenderPage/HippyDemoViewController.mm @@ -21,26 +21,28 @@ */ #import "HippyDemoViewController.h" -#import "HippyLog.h" -#import "HippyBridge.h" -#import "HippyConvenientBridge.h" +#import "UIViewController+Title.h" +#import "HippyPageCache.h" #import "DemoConfigs.h" -#import "HippyAsserts.h" + #import "HippyMethodInterceptorProtocol.h" -#import "HippyRootView.h" -#import "UIView+Hippy.h" -#import "HippyPageCache.h" -#import "UIViewController+Title.h" + +#import +#import +#import +#import +#import static NSString *const engineKey = @"Demo"; -@interface HippyDemoViewController () { +@interface HippyDemoViewController () { DriverType _driverType; RenderType _renderType; BOOL _isDebugMode; - HippyConvenientBridge *_convenientBridge; NSURL *_debugURL; - UIView *_rootView; + + HippyBridge *_hippyBridge; + UIView *_hippyRootView; BOOL _fromCache; } @@ -69,24 +71,29 @@ - (instancetype)initWithPageCache:(HippyPageCache *)pageCache { _renderType = pageCache.renderType; _debugURL = pageCache.debugURL; _isDebugMode = pageCache.isDebugMode; - _rootView = pageCache.rootView; - [_rootView addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:NULL]; - _convenientBridge = pageCache.convenientBridge; + _hippyRootView = pageCache.rootView; + [_hippyRootView addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:NULL]; + _hippyBridge = pageCache.hippyBridge; _fromCache = YES; } return self; } +- (void)dealloc { + [_hippyRootView removeObserver:self forKeyPath:@"frame"]; + [[HippyPageCacheManager defaultPageCacheManager] addPageCache:[self toPageCache]]; +} + - (void)viewDidLoad { [super viewDidLoad]; - // Do any additional setup after loading the view. [self setNavigationAreaBackground:[UIColor whiteColor]]; [self setNavigationItemTitle:@"Demo"]; + [self registerLogFunction]; + if (_fromCache) { [self runHippyCache]; - } - else { + } else { [self runHippyDemo]; } } @@ -98,62 +105,65 @@ - (void)registerLogFunction { } - (void)runHippyCache { - _rootView.frame = self.contentAreaView.bounds; - [self.contentAreaView addSubview:_rootView]; + _hippyRootView.frame = self.contentAreaView.bounds; + [self.contentAreaView addSubview:_hippyRootView]; } - (void)runHippyDemo { NSDictionary *launchOptions = @{@"EnableTurbo": @(DEMO_ENABLE_TURBO), @"DebugMode": @(_isDebugMode)}; - NSString *key = [NSString stringWithFormat:@"%@_%u", engineKey, arc4random()]; - - _convenientBridge = [[HippyConvenientBridge alloc] initWithDelegate:self - moduleProvider:nil - extraComponents:nil - launchOptions:launchOptions - engineKey:key]; - [_convenientBridge setInspectable:YES]; - _convenientBridge.contextName = key; - _convenientBridge.moduleName = @"Demo"; - _convenientBridge.methodInterceptor = self; - [self mountConnector:_convenientBridge]; + NSString *executorKey = [NSString stringWithFormat:@"%@_%u", engineKey, arc4random()]; + + _hippyBridge = [[HippyBridge alloc] initWithDelegate:self + moduleProvider:nil + launchOptions:launchOptions + executorKey:executorKey]; + _hippyBridge.contextName = executorKey; + _hippyBridge.moduleName = @"Demo"; + _hippyBridge.methodInterceptor = self; + + [_hippyBridge setInspectable:YES]; + + [self mountConnector:_hippyBridge]; } -- (void)mountConnector:(HippyConvenientBridge *)convenientBridge { +- (void)mountConnector:(HippyBridge *)hippyBridge { BOOL isSimulator = NO; #if TARGET_IPHONE_SIMULATOR - isSimulator = YES; + isSimulator = YES; #endif + HippyRootView *rootView = [[HippyRootView alloc] initWithFrame:self.contentAreaView.bounds]; rootView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; - [convenientBridge setRootView:rootView]; + [hippyBridge setRootView:rootView]; NSNumber *rootTag = [rootView hippyTag]; + if (_isDebugMode) { - convenientBridge.sandboxDirectory = [_debugURL URLByDeletingLastPathComponent]; - [convenientBridge loadBundleURL:_debugURL completion:^(NSURL * _Nullable, NSError * _Nullable) { - [convenientBridge loadInstanceForRootViewTag:rootTag props:@{@"isSimulator": @(isSimulator)}]; + hippyBridge.sandboxDirectory = [_debugURL URLByDeletingLastPathComponent]; + [hippyBridge loadBundleURL:_debugURL completion:^(NSURL * _Nullable, NSError * _Nullable) { + [hippyBridge loadInstanceForRootView:rootTag withProperties:@{@"isSimulator": @(isSimulator)}]; }]; - } - else { + } else { NSURL *vendorBundleURL = [self vendorBundleURL]; - [convenientBridge loadBundleURL:vendorBundleURL completion:^(NSURL * _Nullable, NSError * _Nullable) { + [hippyBridge loadBundleURL:vendorBundleURL completion:^(NSURL * _Nullable, NSError * _Nullable) { NSLog(@"url %@ load finish", vendorBundleURL); }]; NSURL *indexBundleURL = [self indexBundleURL]; - convenientBridge.sandboxDirectory = [indexBundleURL URLByDeletingLastPathComponent]; - [convenientBridge loadBundleURL:indexBundleURL completion:^(NSURL * _Nullable, NSError * _Nullable) { + hippyBridge.sandboxDirectory = [indexBundleURL URLByDeletingLastPathComponent]; + [hippyBridge loadBundleURL:indexBundleURL completion:^(NSURL * _Nullable, NSError * _Nullable) { NSLog(@"url %@ load finish", indexBundleURL); - [convenientBridge loadInstanceForRootViewTag:rootTag props:@{@"isSimulator": @(isSimulator)}]; + [hippyBridge loadInstanceForRootView:rootTag withProperties:@{@"isSimulator": @(isSimulator)}]; }]; } + [self.contentAreaView addSubview:rootView]; - if (_rootView) { - [_rootView removeObserver:self forKeyPath:@"frame" context:NULL]; + if (_hippyRootView) { + [_hippyRootView removeObserver:self forKeyPath:@"frame" context:NULL]; } [rootView addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:NULL]; - _rootView = rootView; + _hippyRootView = rootView; } - (void)observeValueForKeyPath:(NSString *)keyPath @@ -161,18 +171,18 @@ - (void)observeValueForKeyPath:(NSString *)keyPath change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqualToString:@"frame"] && - object == _rootView) { + object == _hippyRootView) { CGRect frame = [change[NSKeyValueChangeNewKey] CGRectValue]; CGRect oldFrame = [change[NSKeyValueChangeOldKey] CGRectValue]; if (!CGRectEqualToRect(frame, oldFrame)) { - [_convenientBridge resetRootSize:frame.size]; + [_hippyBridge resetRootSize:frame.size]; } } } - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; - _rootView.frame = self.contentAreaView.bounds; + _hippyRootView.frame = self.contentAreaView.bounds; } - (NSURL *)vendorBundleURL { @@ -214,46 +224,23 @@ - (BOOL)isDebugMode { } - (void)reload:(HippyBridge *)bridge { - [self mountConnector:_convenientBridge]; + [self mountConnector:_hippyBridge]; } - (void)removeRootView:(NSNumber *)rootTag bridge:(HippyBridge *)bridge { [[[self.contentAreaView subviews] firstObject] removeFromSuperview]; } -- (BOOL)shouldStartInspector:(HippyBridge *)bridge { - return bridge.debugMode; -} - -- (BOOL)shouldInvokeWithModuleName:(NSString *)moduleName - methodName:(NSString *)methodName - arguments:(NSArray> *)arguments - argumentsValues:(NSArray *)argumentsValue - containCallback:(BOOL)containCallback { - HippyAssert(moduleName, @"module name must not be null"); - HippyAssert(methodName, @"method name must not be null"); - return YES; -} - -- (BOOL)shouldCallbackBeInvokedWithModuleName:(NSString *)moduleName - methodName:(NSString *)methodName - callbackId:(NSNumber *)cbId - arguments:(id)arguments { - HippyAssert(moduleName, @"module name must not be null"); - HippyAssert(methodName, @"method name must not be null"); - return YES; -} - - (HippyPageCache *)toPageCache { HippyPageCache *pageCache = [[HippyPageCache alloc] init]; - pageCache.convenientBridge = _convenientBridge; - pageCache.rootView = _rootView; + pageCache.hippyBridge = _hippyBridge; + pageCache.rootView = _hippyRootView; pageCache.driverType = _driverType; pageCache.renderType = _renderType; pageCache.debugURL = _debugURL; pageCache.debugMode = _isDebugMode; - UIGraphicsBeginImageContextWithOptions(_rootView.bounds.size, NO, [UIScreen mainScreen].scale); - [_rootView drawViewHierarchyInRect:_rootView.bounds afterScreenUpdates:YES]; + UIGraphicsBeginImageContextWithOptions(_hippyRootView.bounds.size, NO, [UIScreen mainScreen].scale); + [_hippyRootView drawViewHierarchyInRect:_hippyRootView.bounds afterScreenUpdates:YES]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); pageCache.snapshot = image; @@ -268,13 +255,33 @@ - (UIInterfaceOrientationMask)supportedInterfaceOrientations { return UIInterfaceOrientationMaskAllButUpsideDown; } -- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { - return UIInterfaceOrientationPortrait; + +#pragma mark - HippyBridgeDelegate + +- (BOOL)shouldStartInspector:(HippyBridge *)bridge { + return bridge.debugMode; } -- (void)dealloc { - [_rootView removeObserver:self forKeyPath:@"frame"]; - [[HippyPageCacheManager defaultPageCacheManager] addPageCache:[self toPageCache]]; + +#pragma mark - HippyMethodInterceptorProtocol + +- (BOOL)shouldInvokeWithModuleName:(NSString *)moduleName + methodName:(NSString *)methodName + arguments:(NSArray> *)arguments + argumentsValues:(NSArray *)argumentsValue + containCallback:(BOOL)containCallback { + HippyAssert(moduleName, @"module name must not be null"); + HippyAssert(methodName, @"method name must not be null"); + return YES; +} + +- (BOOL)shouldCallbackBeInvokedWithModuleName:(NSString *)moduleName + methodName:(NSString *)methodName + callbackId:(NSNumber *)cbId + arguments:(id)arguments { + HippyAssert(moduleName, @"module name must not be null"); + HippyAssert(methodName, @"method name must not be null"); + return YES; } @end diff --git a/framework/examples/ios-demo/HippyDemo/TestModule.mm b/framework/examples/ios-demo/HippyDemo/TestModule.mm index 0046fe2f7f9..d76134a9089 100644 --- a/framework/examples/ios-demo/HippyDemo/TestModule.mm +++ b/framework/examples/ios-demo/HippyDemo/TestModule.mm @@ -27,7 +27,6 @@ #import "HippyJSEnginesMapper.h" #import "HippyRootView.h" #import "UIView+Hippy.h" -#import "HippyConvenientBridge.h" #import "HippyLog.h" #import "HippyRedBox.h" #import "DemoConfigs.h" @@ -36,8 +35,8 @@ static NSString *const engineKey = @"Demo"; -@interface TestModule () { - HippyConvenientBridge *_connector; +@interface TestModule () { + HippyBridge *_connector; } @end @@ -69,7 +68,10 @@ - (void)runCommonDemo:(nonnull NSString *)bundleUrl { NSURL *url = [NSURL URLWithString:bundleUrl]; NSDictionary *launchOptions = @{@"EnableTurbo": @(DEMO_ENABLE_TURBO), @"DebugMode": @(YES), @"DebugURL": url}; NSURL *sandboxDirectory = [url URLByDeletingLastPathComponent]; - _connector = [[HippyConvenientBridge alloc] initWithDelegate:self moduleProvider:nil extraComponents:nil launchOptions:launchOptions engineKey:engineKey]; + _connector = [[HippyBridge alloc] initWithDelegate:self + moduleProvider:nil + launchOptions:launchOptions + executorKey:engineKey]; [_connector setInspectable:YES]; //set custom vfs loader _connector.sandboxDirectory = sandboxDirectory; @@ -81,7 +83,7 @@ - (void)runCommonDemo:(nonnull NSString *)bundleUrl { [rootViewController presentViewController:vc animated:YES completion:NULL]; } -- (void)mountConnector:(HippyConvenientBridge *)connector onView:(UIView *)view { +- (void)mountConnector:(HippyBridge *)connector onView:(UIView *)view { BOOL isSimulator = NO; #if TARGET_IPHONE_SIMULATOR isSimulator = YES; @@ -96,7 +98,7 @@ - (void)mountConnector:(HippyConvenientBridge *)connector onView:(UIView *)view NSNumber *rootTag = [rootView hippyTag]; [connector loadBundleURL:bundleUrl completion:^(NSURL * _Nullable, NSError * _Nullable) { NSLog(@"url %@ load finish", bundleStr); - [connector loadInstanceForRootViewTag:rootTag props:@{@"isSimulator": @(isSimulator)}]; + [connector loadInstanceForRootView:rootTag withProperties:@{@"isSimulator": @(isSimulator)}]; }]; [view addSubview:rootView]; } diff --git a/framework/ios/base/bridge/HippyBridge.h b/framework/ios/base/bridge/HippyBridge.h index 88c712ec47e..82e84d92858 100644 --- a/framework/ios/base/bridge/HippyBridge.h +++ b/framework/ios/base/bridge/HippyBridge.h @@ -34,8 +34,10 @@ @class HippyJSExecutor; @class HippyModuleData; +@class HippyRootView; class VFSUriLoader; +class NativeRenderManager; namespace hippy { inline namespace dom { @@ -90,21 +92,19 @@ HIPPY_EXTERN NSString *HippyBridgeModuleNameForClass(Class bridgeModuleClass); @property (nonatomic, copy, readonly) NSDictionary *launchOptions; -@property (nonatomic, assign) std::weak_ptr renderManager; - /** * Create A HippyBridge instance * * @param delegate bridge delegate * @param block for user-defined module * @param launchOptions launch options, will not be sent to frontend - * @param engineKey key to engine instance. HippyBridge with same engine key will share same engine intance + * @param executorKey key to engine instance. HippyBridge with same engine key will share same engine intance * @return A HippyBridge instance */ - (instancetype)initWithDelegate:(id)delegate - moduleProvider:(HippyBridgeModuleProviderBlock)block + moduleProvider:(nullable HippyBridgeModuleProviderBlock)block launchOptions:(NSDictionary *)launchOptions - engineKey:(NSString *)engineKey; + executorKey:(NSString *)executorKey; /** * Context name for HippyBridge @@ -175,6 +175,11 @@ HIPPY_EXTERN NSString *HippyBridgeModuleNameForClass(Class bridgeModuleClass); */ @property (nonatomic, readonly) HippyJSExecutor *javaScriptExecutor; + +/// The C++ version of RenderManager instance, bridge holds +@property (nonatomic, assign) std::shared_ptr renderManager; + + /** * JS invocation methods */ @@ -281,6 +286,14 @@ HIPPY_EXTERN NSString *HippyBridgeModuleNameForClass(Class bridgeModuleClass); - (void)setSnapShotData:(NSData *)data; + + +- (void)setRootView:(HippyRootView *)rootView; + +- (void)resetRootSize:(CGSize)size; + + + @end diff --git a/framework/ios/base/bridge/HippyBridge.mm b/framework/ios/base/bridge/HippyBridge.mm index bae7a77e3af..2eff74fb565 100644 --- a/framework/ios/base/bridge/HippyBridge.mm +++ b/framework/ios/base/bridge/HippyBridge.mm @@ -65,6 +65,11 @@ #include "vfs/uri_loader.h" #include "VFSUriHandler.h" +#import "NativeRenderManager.h" +#import "HippyRootView.h" +#import "UIView+Hippy.h" + + #ifdef ENABLE_INSPECTOR #include "devtools/vfs/devtools_handler.h" #include "devtools/devtools_data_source.h" @@ -96,9 +101,12 @@ @interface HippyBridge() { HippyBundleOperationQueue *_bundlesQueue; NSMutableArray *_bundleURLs; NSURL *_sandboxDirectory; - std::weak_ptr _uriLoader; - std::weak_ptr _renderManager; + footstone::TimePoint _startTime; + + std::shared_ptr _uriLoader; + std::shared_ptr _rootNode; + } @property(readwrite, strong) dispatch_semaphore_t moduleSemaphore; @@ -133,14 +141,14 @@ + (void)initialize { - (instancetype)initWithDelegate:(id)delegate moduleProvider:(HippyBridgeModuleProviderBlock)block launchOptions:(NSDictionary *)launchOptions - engineKey:(NSString *)engineKey { + executorKey:(NSString *)executorKey { if (self = [super init]) { _delegate = delegate; _moduleProvider = block; - _bundleURLs = [NSMutableArray arrayWithCapacity:8]; + _bundleURLs = [NSMutableArray array]; _debugMode = [launchOptions[@"DebugMode"] boolValue]; _enableTurbo = !!launchOptions[@"EnableTurbo"] ? [launchOptions[@"EnableTurbo"] boolValue] : YES; - _engineKey = engineKey; + _engineKey = executorKey; _invalidateReason = HippyInvalidateReasonDealloc; _valid = YES; _bundlesQueue = [[HippyBundleOperationQueue alloc] init]; @@ -150,6 +158,13 @@ - (instancetype)initWithDelegate:(id)delegate HippyExecuteOnMainThread(^{ [self bindKeys]; }, YES); + + + + [self addImageProviderClass:[HippyDefaultImageProvider class]]; + [self setVFSUriLoader:[self createURILoaderIfNeeded]]; + [self setUpNativeRenderManager]; + [HippyBridge setCurrentBridge:self]; HippyLogInfo(@"[Hippy_OC_Log][Life_Circle],%@ Init %p", NSStringFromClass([self class]), self); } @@ -162,7 +177,7 @@ - (void)rootViewContentDidAppear:(NSNotification *)noti { auto domManager = _javaScriptExecutor.pScope->GetDomManager().lock(); if (domManager) { auto viewRenderManager = [rootView renderManager]; - if (_renderManager.lock() == viewRenderManager.lock()) { + if (_renderManager == viewRenderManager.lock()) { auto entry = _javaScriptExecutor.pScope->GetPerformance()->PerformanceNavigation("hippyInit"); entry->SetHippyDomStart(domManager->GetDomStartTimePoint()); entry->SetHippyDomEnd(domManager->GetDomEndTimePoint()); @@ -182,6 +197,15 @@ - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; self.invalidateReason = HippyInvalidateReasonDealloc; [self invalidate]; + + // FIXME: 检查问题 + if (_uriLoader) { + _uriLoader->Terminate(); + } + if (_rootNode) { + _renderManager->RemoveVSyncEventListener(_rootNode); + _rootNode->ReleaseResources(); + } } - (void)bindKeys { @@ -197,6 +221,36 @@ - (void)bindKeys { #endif } +- (NSString *)engineKey { + return _engineKey ?: [NSString stringWithFormat:@"%p", self]; +} + +- (void)setUpNativeRenderManager { + auto engineResource = [[HippyJSEnginesMapper defaultInstance] JSEngineResourceForKey:[self engineKey]]; + auto domManager = engineResource->GetDomManager(); + //Create NativeRenderManager + auto nativeRenderManager = std::make_shared(); + nativeRenderManager->Initialize(); + //set dom manager + nativeRenderManager->SetDomManager(domManager); + nativeRenderManager->SetVFSUriLoader([self createURILoaderIfNeeded]); + nativeRenderManager->SetHippyBridge(self); + _renderManager = nativeRenderManager; +} + +- (std::shared_ptr)createURILoaderIfNeeded { + if (!_uriLoader) { + auto uriHandler = std::make_shared(); + auto uriLoader = std::make_shared(); + uriLoader->PushDefaultHandler(uriHandler); + uriLoader->AddConvenientDefaultHandler(uriHandler); + auto fileHandler = std::make_shared(self); + uriLoader->RegisterConvenientUriHandler(@"hpfile", fileHandler); + _uriLoader = uriLoader; + } + return _uriLoader; +} + - (NSArray *)moduleClasses { return _moduleSetup.moduleClasses; } @@ -213,15 +267,16 @@ - (void)addImageProviderClass:(Class)cls { HippyAssertParam(cls); @synchronized (self) { if (!_imageProviders) { - _imageProviders = [NSMutableArray arrayWithCapacity:8]; + _imageProviders = [NSMutableArray array]; } [_imageProviders addObject:cls]; } } + - (NSArray> *)imageProviderClasses { @synchronized (self) { if (!_imageProviders) { - _imageProviders = [NSMutableArray arrayWithCapacity:8]; + _imageProviders = [NSMutableArray array]; } return [_imageProviders copy]; } @@ -397,6 +452,12 @@ - (void)unloadInstanceForRootView:(NSNumber *)rootTag { footstone::value::HippyValue value = [param toHippyValue]; std::shared_ptr domValue = std::make_shared(value); self.javaScriptExecutor.pScope->UnloadInstance(domValue); + + _renderManager->UnregisterRootView([rootTag intValue]); + if (_rootNode) { + _rootNode->ReleaseResources(); + _rootNode = nullptr; + } } } @@ -423,7 +484,6 @@ - (void)rootViewSizeChangedEvent:(NSNumber *)tag params:(NSDictionary *)params { } - (void)setVFSUriLoader:(std::weak_ptr)uriLoader { - _uriLoader = uriLoader; [_javaScriptExecutor setUriLoader:uriLoader]; #ifdef ENABLE_INSPECTOR auto devtools_data_source = _javaScriptExecutor.pScope->GetDevtoolsDataSource(); @@ -775,8 +835,8 @@ - (void)setupDomManager:(std::shared_ptr)domManager if (!strongSelf || !domManager) { return; } - strongSelf->_javaScriptExecutor.pScope->SetDomManager(domManager); - strongSelf->_javaScriptExecutor.pScope->SetRootNode(rootNode); + strongSelf.javaScriptExecutor.pScope->SetDomManager(domManager); + strongSelf.javaScriptExecutor.pScope->SetRootNode(rootNode); #ifdef ENABLE_INSPECTOR auto devtools_data_source = strongSelf->_javaScriptExecutor.pScope->GetDevtoolsDataSource(); if (devtools_data_source) { @@ -990,6 +1050,64 @@ - (void)setSnapShotData:(NSData *)data { domManager->SetSnapShot(rootNode, string); } + +#pragma mark - + + +//FIXME: 调整优化 +- (void)setRootView:(HippyRootView *)rootView { + auto engineResource = [[HippyJSEnginesMapper defaultInstance] JSEngineResourceForKey:[self engineKey]]; + auto domManager = engineResource->GetDomManager(); + NSNumber *rootTag = [rootView hippyTag]; + //Create a RootNode instance with a root tag + _rootNode = std::make_shared([rootTag unsignedIntValue]); + //Set RootNode for AnimationManager in RootNode + _rootNode->GetAnimationManager()->SetRootNode(_rootNode); + //Set DomManager for RootNode + _rootNode->SetDomManager(domManager); + //Set screen scale factor and size for Layout system in RooNode + _rootNode->GetLayoutNode()->SetScaleFactor([UIScreen mainScreen].scale); + _rootNode->SetRootSize(rootView.frame.size.width, rootView.frame.size.height); + _rootNode->SetRootOrigin(rootView.frame.origin.x, rootView.frame.origin.y); + + //set rendermanager for dommanager + if (!domManager->GetRenderManager().lock()) { + domManager->SetRenderManager(_renderManager); + } + //bind rootview and root node + _renderManager->RegisterRootView(rootView, _rootNode); + + __weak HippyBridge *weakBridge = self; + auto cb = [weakBridge](int32_t tag, NSDictionary *params){ + HippyBridge *strongBridge = weakBridge; + if (strongBridge) { + [strongBridge rootViewSizeChangedEvent:@(tag) params:params]; + } + }; + _renderManager->SetRootViewSizeChangedEvent(cb); + //setup necessary params for bridge + [self setupDomManager:domManager rootNode:_rootNode]; +} + +- (void)resetRootSize:(CGSize)size { + auto engineResource = [[HippyJSEnginesMapper defaultInstance] JSEngineResourceForKey:[self engineKey]]; + std::weak_ptr rootNode = _rootNode; + auto domManager = engineResource->GetDomManager(); + std::weak_ptr weakDomManager = domManager; + std::vector> ops = {[rootNode, weakDomManager, size](){ + auto strongRootNode = rootNode.lock(); + auto strongDomManager = weakDomManager.lock(); + if (strongRootNode && strongDomManager) { + strongRootNode->SetRootSize(size.width, size.height); + strongDomManager->DoLayout(strongRootNode); + strongDomManager->EndBatch(strongRootNode); + } + }}; + domManager->PostTask(hippy::dom::Scene(std::move(ops))); +} + + + @end void HippyBridgeFatal(NSError *error, HippyBridge *bridge) { diff --git a/hippy.podspec b/hippy.podspec index 838b2182259..0e32cc620b9 100644 --- a/hippy.podspec +++ b/hippy.podspec @@ -26,17 +26,10 @@ Pod::Spec.new do |s| framework_header_path = '${PODS_CONFIGURATION_BUILD_DIR}/hippy/hippy.framework/Headers' s.module_map = false; end - puts 'hippy.podspec read begins' + s.name = 'hippy' s.version = '3.0.0' s.summary = 'Hippy Cross Platform Framework' - -# This description is used to generate tags and improve search results. -# * Think: What does it do? Why did you write it? What is the focus? -# * Try to keep it short, snappy and to the point. -# * Write the description between the DESC delimiters below. -# * Finally, don't worry about the indent, CocoaPods strips it! - s.description = <<-DESC Hippy is designed for developers to easily build cross-platform and high-performance awesome apps. DESC @@ -72,6 +65,8 @@ Pod::Spec.new do |s| framework.dependency 'hippy/Base' framework.dependency 'hippy/JSDriver' framework.dependency 'hippy/Image' + framework.dependency 'hippy/iOSVFS' + framework.dependency 'hippy/NativeRenderer' puts 'hippy subspec \'framework\' read end' end @@ -455,5 +450,4 @@ Pod::Spec.new do |s| end end - puts 'hippy.podspec read ends' end diff --git a/modules/ios/base/NSObject+Render.h b/modules/ios/base/NSObject+Render.h index de33d40859e..2b3ad2d569d 100644 --- a/modules/ios/base/NSObject+Render.h +++ b/modules/ios/base/NSObject+Render.h @@ -32,7 +32,8 @@ class RenderManager; }; }; -@interface NSObject (Render) +// FIXME: remove this category +@interface UIView (HippyRenderManager) @property(nonatomic, assign) std::weak_ptr renderManager; diff --git a/modules/ios/base/NSObject+Render.mm b/modules/ios/base/NSObject+Render.mm index d6f5fa6dd49..fd4291d02d5 100644 --- a/modules/ios/base/NSObject+Render.mm +++ b/modules/ios/base/NSObject+Render.mm @@ -35,7 +35,7 @@ @implementation RenderManagerWrapper @end -@implementation NSObject (Render) +@implementation UIView (HippyRenderManager) - (void)setRenderManager:(std::weak_ptr)renderManager { RenderManagerWrapper *wrapper = [[RenderManagerWrapper alloc] init]; diff --git a/renderer/native/ios/renderer/HippyUIManager.h b/renderer/native/ios/renderer/HippyUIManager.h index bd2bb6ae1f2..1fa540a5a14 100644 --- a/renderer/native/ios/renderer/HippyUIManager.h +++ b/renderer/native/ios/renderer/HippyUIManager.h @@ -70,9 +70,6 @@ class HippyValue; @property (nonatomic, readonly) std::weak_ptr domManager; @property (nonatomic, readonly) HippyComponentMap *viewRegistry; -- (void)addImageProviderClass:(Class)cls; -- (NSArray> *)imageProviderClasses; - /** * Gets the view associated with a hippyTag. */ diff --git a/renderer/native/ios/renderer/HippyUIManager.mm b/renderer/native/ios/renderer/HippyUIManager.mm index b3be1d4710b..178e6788fec 100644 --- a/renderer/native/ios/renderer/HippyUIManager.mm +++ b/renderer/native/ios/renderer/HippyUIManager.mm @@ -181,7 +181,6 @@ @interface HippyUIManager() { std::weak_ptr _VFSUriLoader; NSMutableArray> *_imageProviders; - std::mutex _imageProviderMutex; std::function _rootViewSizeChangedCb; std::weak_ptr _renderManager; @@ -1477,22 +1476,6 @@ - (NSDictionary *)mergeProps:(NSDictionary *)newProps oldProps:(NSDictionary *)o return tmpProps; } -- (void)addImageProviderClass:(Class)cls { - HippyAssertParam(cls); - std::lock_guard lock(_imageProviderMutex); - if (!_imageProviders) { - _imageProviders = [NSMutableArray arrayWithCapacity:8]; - } - [_imageProviders addObject:cls]; -} -- (NSArray> *)imageProviderClasses { - std::lock_guard lock(_imageProviderMutex); - if (!_imageProviders) { - _imageProviders = [NSMutableArray arrayWithCapacity:8]; - } - return [_imageProviders copy]; -} - - (void)setVFSUriLoader:(std::weak_ptr)loader { _VFSUriLoader = loader; } @@ -1535,7 +1518,7 @@ - (void)domEventDidHandle:(const std::string &)eventName forNode:(int32_t)tag on @implementation HippyBridge (HippyUIManager) - (HippyUIManager *)uiManager { - auto renderManager = [self renderManager].lock(); + auto renderManager = [self renderManager]; if (renderManager) { auto nativeRenderManager = std::static_pointer_cast(renderManager); return nativeRenderManager->GetHippyUIManager(); diff --git a/renderer/native/ios/renderer/NativeRenderManager.h b/renderer/native/ios/renderer/NativeRenderManager.h index 7673fe4f3d6..e1a1011905b 100644 --- a/renderer/native/ios/renderer/NativeRenderManager.h +++ b/renderer/native/ios/renderer/NativeRenderManager.h @@ -190,14 +190,6 @@ class NativeRenderManager : public hippy::RenderManager ,public std::enable_shar */ void SetUICreationLazilyEnabled(bool enabled); - /** - * Image provider method - * Users adds or obtains image providers in the following methods - */ - void AddImageProviderClass(Class cls); - - NSArray> *GetImageProviderClasses(); - /** * Set vfs uri loader of CPP version * diff --git a/renderer/native/ios/renderer/NativeRenderManager.mm b/renderer/native/ios/renderer/NativeRenderManager.mm index 07259efdeb2..b24ca5c313a 100644 --- a/renderer/native/ios/renderer/NativeRenderManager.mm +++ b/renderer/native/ios/renderer/NativeRenderManager.mm @@ -212,20 +212,6 @@ renderImpl_.uiCreationLazilyEnabled = enabled; } -void NativeRenderManager::AddImageProviderClass(Class cls) { - @autoreleasepool { - HippyAssert(renderImpl_, @"renderImpl_ is null, did you forget to call Initialize()?"); - [renderImpl_ addImageProviderClass:cls]; - } -} - -NSArray> *NativeRenderManager::GetImageProviderClasses() { - @autoreleasepool { - HippyAssert(renderImpl_, @"renderImpl_ is null, did you forget to call Initialize()?"); - return [renderImpl_ imageProviderClasses]; - } -} - void NativeRenderManager::SetVFSUriLoader(std::shared_ptr loader) { @autoreleasepool { HippyAssert(renderImpl_, @"renderImpl_ is null, did you forget to call Initialize()?"); diff --git a/renderer/native/ios/renderer/component/image/NativeRenderImageViewManager.mm b/renderer/native/ios/renderer/component/image/NativeRenderImageViewManager.mm index 739f7153dbf..603048f7b2f 100644 --- a/renderer/native/ios/renderer/component/image/NativeRenderImageViewManager.mm +++ b/renderer/native/ios/renderer/component/image/NativeRenderImageViewManager.mm @@ -73,11 +73,13 @@ - (void)loadImageSource:(NSString *)path forView:(NativeRenderImageView *)view { if (!loader) { return; } + __weak __typeof(self)weakSelf = self; loader->RequestUntrustedContent(path, nil, nil, ^(NSData *data, NSURLResponse *response, NSError *error) { - HippyUIManager *renderImpl = self.bridge.uiManager; + __strong __typeof(weakSelf)strongSelf = weakSelf; + HippyUIManager *renderImpl = strongSelf.bridge.uiManager; id imageProvider = nil; if (renderImpl) { - for (Class cls in [renderImpl imageProviderClasses]) { + for (Class cls in [strongSelf.bridge imageProviderClasses]) { if ([cls canHandleData:data]) { imageProvider = [[(Class)cls alloc] init]; break; diff --git a/renderer/native/ios/renderer/component/view/HippyViewManager.mm b/renderer/native/ios/renderer/component/view/HippyViewManager.mm index 1dfa9235366..f9c73dda39a 100644 --- a/renderer/native/ios/renderer/component/view/HippyViewManager.mm +++ b/renderer/native/ios/renderer/component/view/HippyViewManager.mm @@ -251,7 +251,7 @@ - (void)loadImageSource:(NSString *)path forView:(HippyView *)view { HippyUIManager *renderImpl = strongSelf.bridge.uiManager; id imageProvider = nil; if (renderImpl) { - for (Class cls in [renderImpl imageProviderClasses]) { + for (Class cls in [strongSelf.bridge imageProviderClasses]) { if ([cls canHandleData:data]) { imageProvider = [[(Class)cls alloc] init]; break;