Skip to content

Commit

Permalink
refactor(ios): add a uiManager getter for UIView (#4022)
Browse files Browse the repository at this point in the history
For compatibility,
some third-party components want to get UIManager
or HippyBridge directly through UIView,
although there is a slight performance penalty doing this.
  • Loading branch information
wwwcg authored Sep 10, 2024
1 parent c9ddbc1 commit e5fcf2f
Show file tree
Hide file tree
Showing 12 changed files with 127 additions and 28 deletions.
3 changes: 3 additions & 0 deletions renderer/native/ios/renderer/HippyUIManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
@class HippyComponentMap;
@protocol HippyImageProviderProtocol;

NS_ASSUME_NONNULL_BEGIN

/**
* Posted whenever a new root view is registered with HippyUIManager. The userInfo property
Expand Down Expand Up @@ -156,3 +157,5 @@ HIPPY_EXTERN NSString *const HippyUIManagerDidEndBatchNotification;
@property (nonatomic, strong, readonly) id<HippyCustomTouchHandlerProtocol> customTouchHandler;

@end

NS_ASSUME_NONNULL_END
19 changes: 15 additions & 4 deletions renderer/native/ios/renderer/HippyUIManager.mm
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,18 @@ static void NativeRenderTraverseViewNodes(id<HippyComponent> view, void (^block)
}
}


@interface UIView (HippyUIManagerPrivate)

/// Bind UIView with HippyUIManager
/// This is a convenient method for UIView to get HippyUIManager instance.
/// - Parameter uiManager: HippyUIManager instance
- (void)setUiManager:(HippyUIManager *)uiManager;

@end

#pragma mark -

#define AssertMainQueue() NSAssert(HippyIsMainQueue(), @"This function must be called on the main thread")

NSString *const HippyUIManagerDidRegisterRootViewNotification = @"HippyUIManagerDidRegisterRootViewNotification";
Expand Down Expand Up @@ -318,8 +330,8 @@ - (void)registerRootView:(UIView *)rootView asRootNode:(std::weak_ptr<RootNode>)
// Register view
[_viewRegistry addRootComponent:rootView rootNode:rootNode forTag:hippyTag];
[rootView addObserver:self forKeyPath:@"frame"
rootView.uiManager = self;
[rootView addObserver:self forKeyPath:@"frame"
options:(NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew)
context:NULL];
CGRect frame = rootView.frame;
Expand Down Expand Up @@ -516,6 +528,7 @@ - (UIView *)createViewFromShadowView:(HippyShadowView *)shadowView {
view.viewName = viewName;
view.rootTag = rootTag;
view.hippyShadowView = shadowView;
view.uiManager = self;
[componentData setProps:props forView:view]; // Must be done before bgColor to prevent wrong default
}
}
Expand Down Expand Up @@ -1523,7 +1536,5 @@ - (void)setCustomTouchHandler:(id<HippyCustomTouchHandlerProtocol>)customTouchHa
objc_setAssociatedObject(self, @selector(customTouchHandler), customTouchHandler, OBJC_ASSOCIATION_RETAIN);
}


@end


Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#import "HippyShadowView.h"
#import "UIView+DirectionalLayout.h"
#import "UIView+Hippy.h"
#import "UIView+Render.h"
#import "HippyShadowListView.h"

static NSString *const kCellIdentifier = @"HippyListCellIdentifier";
Expand All @@ -48,8 +49,8 @@ @implementation HippyNextBaseListView

#pragma mark - Life Cycle

- (instancetype)initWithBridge:(HippyBridge *)bridge {
if (self = [super initWithBridge:bridge]) {
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
_isInitialListReady = NO;
self.preloadItemNumber = 1;
}
Expand Down Expand Up @@ -220,7 +221,7 @@ - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
forIndexPath:indexPath];
HippyShadowView *headerRenderObject = [self.dataSource headerForSection:section];
if (headerRenderObject && [headerRenderObject isKindOfClass:[HippyShadowView class]]) {
UIView *headerView = [self.bridge.uiManager createViewForShadowListItem:headerRenderObject];
UIView *headerView = [self.uiManager createViewForShadowListItem:headerRenderObject];
CGRect frame = headerView.frame;
frame.origin = CGPointZero;
headerView.frame = frame;
Expand Down Expand Up @@ -272,7 +273,7 @@ - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cell
cellView = cachedVisibleCellView;
HippyLogTrace(@"🟢 use cached visible cellView at %@ for %@", indexPath, shadowView.hippyTag);
} else {
cellView = [self.bridge.uiManager createViewForShadowListItem:shadowView];
cellView = [self.uiManager createViewForShadowListItem:shadowView];
[_cachedWeakCellViews setObject:cellView forKey:shadowView.hippyTag];
HippyLogTrace(@"🟡 create cellView at %@ for %@", indexPath, shadowView.hippyTag);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ @implementation HippyNextBaseListViewManager
HIPPY_EXPORT_VIEW_PROPERTY(horizontal, BOOL)

- (UIView *)view {
return [[HippyNextBaseListView alloc] initWithBridge:self.bridge];
return [[HippyNextBaseListView alloc] init];
}

- (HippyShadowView *)shadowView {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
#import "HippyScrollProtocol.h"
#import "UIView+MountEvent.h"
#import "UIView+Hippy.h"

#import "UIView+Render.h"
#include <objc/runtime.h>

static NSInteger kInfiniteLoopBegin = 2;
Expand Down Expand Up @@ -58,8 +58,8 @@ - (void)setPreviousMargin:(CGFloat)previousMargin nextMargin:(CGFloat)nextMargin
@implementation NativeRenderSmartViewPagerView

#pragma mark Life Cycle
- (instancetype)initWithBridge:(HippyBridge *)bridge {
if (self = [super initWithBridge:bridge]) {
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
_isInitialListReady = NO;
_dataSource = [[HippyNextBaseListViewDataSource alloc] initWithDataSource:nil
itemViewName:[self compoentItemName]
Expand Down Expand Up @@ -356,7 +356,7 @@ - (void)collectionView:(UICollectionView *)collectionView
NSIndexPath *adjustIndexPath = [NSIndexPath indexPathForRow:cellIndex inSection:indexPath.section];
HippyWaterfallViewCell *hpCell = (HippyWaterfallViewCell *)cell;
HippyShadowView *renderObject = [_dataSource cellForIndexPath:adjustIndexPath];
UIView *cellView = [self.bridge.uiManager createViewForShadowListItem:renderObject];
UIView *cellView = [self.uiManager createViewForShadowListItem:renderObject];
hpCell.cellView = cellView;
cellView.parent = self;
}
Expand Down
37 changes: 37 additions & 0 deletions renderer/native/ios/renderer/component/view/UIView+Render.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*!
* 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 <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@class HippyUIManager;
/// UIView's UIManager category
@interface UIView (HippyUIManager)

/// Convenient method to get HippyUIManager instance,
/// UIView's uiManager property is set when created.
- (nullable HippyUIManager *)uiManager;

@end

NS_ASSUME_NONNULL_END
38 changes: 38 additions & 0 deletions renderer/native/ios/renderer/component/view/UIView+Render.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*!
* 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 "UIView+Render.h"
#import <objc/runtime.h>

@implementation UIView (HippyUIManager)

- (HippyUIManager *)uiManager {
NSValue *weakValue = objc_getAssociatedObject(self, @selector(uiManager));
return [weakValue nonretainedObjectValue];
}

- (void)setUiManager:(HippyUIManager *)uiManager {
NSValue *weakValue = [NSValue valueWithNonretainedObject:uiManager];
objc_setAssociatedObject(self, @selector(uiManager), weakValue, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,6 @@ typedef NS_ENUM(NSInteger, NativeRenderScrollState) {
BOOL _allowNextScrollNoMatterWhat;
}

/// Weak ref of HippyBridge
@property (nonatomic, weak, readonly) HippyBridge *bridge;

/**
* Content inset for HippyWaterfallView
*/
Expand Down Expand Up @@ -119,12 +116,6 @@ typedef NS_ENUM(NSInteger, NativeRenderScrollState) {
@property (nonatomic, copy) HippyDirectEventBlock onRefresh;
@property (nonatomic, copy) HippyDirectEventBlock onExposureReport;

/// Init method
/// - Parameter bridge: HippyBridge instance
- (instancetype)initWithBridge:(HippyBridge *)bridge NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder *)coder NS_UNAVAILABLE;

/**
* Initial collection view
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#import "HippyFooterRefresh.h"
#import "HippyWaterfallItemView.h"
#import "UIView+Hippy.h"
#import "UIView+Render.h"
#import "HippyRefresh.h"
#import "HippyWaterfallViewDataSource.h"
#import "HippyShadowView.h"
Expand Down Expand Up @@ -61,9 +62,8 @@ @implementation HippyWaterfallView {

@synthesize contentSize;

- (instancetype)initWithBridge:(id)bridge {
if (self = [super initWithFrame:CGRectZero]) {
_bridge = bridge;
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor clearColor];
_scrollListeners = [NSHashTable weakObjectsHashTable];
_scrollEventThrottle = 100.f;
Expand Down Expand Up @@ -266,7 +266,7 @@ - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cell
if (cachedCellView) {
cellView = cachedCellView;
} else {
cellView = [self.bridge.uiManager createViewForShadowListItem:shadowView];
cellView = [self.uiManager createViewForShadowListItem:shadowView];
[_cachedWeakCellViews setObject:cellView forKey:shadowView.hippyTag];
}

Expand Down
22 changes: 20 additions & 2 deletions tests/ios/HippyUIViewCategoryTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,18 @@
*/

#import <XCTest/XCTest.h>
#import "UIView+Hippy.h"
#import <hippy/UIView+Hippy.h>
#import <hippy/UIView+Render.h>
#import <hippy/HippyUIManager.h>

@interface UIView (HippyUIManagerUnitTest)

/// Bind UIView with HippyUIManager
/// This is a convenient method for UIView to get HippyUIManager instance.
/// - Parameter uiManager: HippyUIManager instance
- (void)setUiManager:(HippyUIManager *)uiManager;

@end

@interface HippyUIViewCategoryTest : XCTestCase

Expand All @@ -47,8 +58,15 @@ - (void)testGetHippyRootView {
XCTAssert([testView hippyRootView] == testSuperView);
testView.hippyTag = @(11);
XCTAssert([testView hippyRootView] == nil);
}

- (void)testGetHippyUIManager {
UIView *testView = [UIView new];
XCTAssertNil([testView uiManager]);


HippyUIManager *uiManager = [[HippyUIManager alloc] init];
XCTAssertNoThrow(testView.uiManager = uiManager);
XCTAssertTrue(testView.uiManager == uiManager);
}


Expand Down

0 comments on commit e5fcf2f

Please sign in to comment.