Skip to content

Commit dcbab44

Browse files
authored
fix(ios): fix layout issue with new arch (#140)
* fix(ios): fix layout issue with new arch * fix(ios): events in new arch
1 parent 2919972 commit dcbab44

File tree

4 files changed

+52
-48
lines changed

4 files changed

+52
-48
lines changed

example/ios/Podfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
ENV['RCT_NEW_ARCH_ENABLED'] = '0'
1+
ENV['RCT_NEW_ARCH_ENABLED'] = '1'
22

33
# Resolve react_native_pods.rb with node to allow for hoisting
44
require Pod::Executable.execute_command('node', ['-p',

example/src/App.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const App = () => {
1111
<NavigationContainer>
1212
<Stack.Navigator
1313
screenOptions={{ headerTransparent: true, headerTintColor: 'white' }}
14-
initialRouteName="Navigation"
14+
initialRouteName="Map"
1515
>
1616
<Stack.Screen options={{ headerShown: false }} name="Map" component={MapScreen} />
1717
<Stack.Screen

ios/Extensions/UIView+pinTo.swift

+5
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,9 @@ extension UIView {
6666
height: heightConstraint
6767
))
6868
}
69+
70+
func unpin() {
71+
translatesAutoresizingMaskIntoConstraints = true
72+
removeConstraints(constraints)
73+
}
6974
}

ios/TrueSheetView.swift

+45-46
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,13 @@ class TrueSheetView: UIView, RCTInvalidating, TrueSheetViewControllerDelegate {
4141
// MARK: - Content properties
4242

4343
private var containerView: UIView?
44-
4544
private var contentView: UIView?
4645
private var footerView: UIView?
46+
private var scrollView: UIView?
4747

48-
// Reference the bottom constraint to adjust during keyboard event
49-
private var footerViewBottomConstraint: NSLayoutConstraint?
50-
51-
// Reference height constraint during content updates
52-
private var footerViewHeightConstraint: NSLayoutConstraint?
53-
54-
private var scrollableTag: NSNumber?
48+
// Bottom: Reference the bottom constraint to adjust during keyboard event
49+
// Height: Reference height constraint during content updates
50+
private var footerConstraints: Constraints?
5551

5652
private var uiManager: RCTUIManager? {
5753
guard let uiManager = bridge?.uiManager else { return nil }
@@ -101,12 +97,23 @@ class TrueSheetView: UIView, RCTInvalidating, TrueSheetViewControllerDelegate {
10197

10298
super.removeReactSubview(subview)
10399

100+
// Touch handler for Old Arch
104101
touchHandler.detach(from: subview)
102+
103+
// Touch handler that works in New Arch
105104
surfaceTouchHandler.detach(from: subview)
106105

106+
// Remove all constraints
107+
// Fixes New Arch weird layout issue :/
108+
containerView?.unpin()
109+
footerView?.unpin()
110+
contentView?.unpin()
111+
scrollView?.unpin()
112+
107113
containerView = nil
108114
contentView = nil
109115
footerView = nil
116+
scrollView = nil
110117
}
111118

112119
override func didUpdateReactSubviews() {
@@ -131,8 +138,7 @@ class TrueSheetView: UIView, RCTInvalidating, TrueSheetViewControllerDelegate {
131138
// Set footer constraints
132139
if let footerView {
133140
footerView.pinTo(view: viewController.view, from: [.left, .right, .bottom], with: 0) { constraints in
134-
self.footerViewBottomConstraint = constraints.bottom
135-
self.footerViewHeightConstraint = constraints.height
141+
self.footerConstraints = constraints
136142
}
137143

138144
// Set initial footer height
@@ -146,26 +152,22 @@ class TrueSheetView: UIView, RCTInvalidating, TrueSheetViewControllerDelegate {
146152
present(at: initialIndex, promise: nil, animated: initialIndexAnimated)
147153
}
148154

149-
dispatchEvent(name: "onMount", data: nil)
155+
dispatchEvent(name: "onMount", block: onMount, data: nil)
150156
}
151157
}
152158

153159
// MARK: - ViewController delegate
154160

155161
func viewControllerKeyboardWillHide() {
156-
guard let footerViewBottomConstraint else { return }
157-
158-
footerViewBottomConstraint.constant = 0
162+
footerConstraints?.bottom?.constant = 0
159163

160164
UIView.animate(withDuration: 0.3) {
161165
self.viewController.view.layoutIfNeeded()
162166
}
163167
}
164168

165169
func viewControllerKeyboardWillShow(_ keyboardHeight: CGFloat) {
166-
guard let footerViewBottomConstraint else { return }
167-
168-
footerViewBottomConstraint.constant = -keyboardHeight
170+
footerConstraints?.bottom?.constant = -keyboardHeight
169171

170172
UIView.animate(withDuration: 0.3) {
171173
self.viewController.view.layoutIfNeeded()
@@ -174,40 +176,46 @@ class TrueSheetView: UIView, RCTInvalidating, TrueSheetViewControllerDelegate {
174176

175177
func viewControllerDidChangeWidth(_ width: CGFloat) {
176178
// We only pass width to JS since height is handled by the constraints
177-
dispatchEvent(name: "onContainerSizeChange", data: ["width": width])
179+
dispatchEvent(name: "onContainerSizeChange", block: onContainerSizeChange, data: ["width": width])
178180
}
179181

180182
func viewControllerDidDrag(_ state: UIGestureRecognizer.State, _ height: CGFloat) {
181183
let sizeInfo = SizeInfo(index: activeIndex ?? 0, value: height)
182184

183185
switch state {
184186
case .began:
185-
dispatchEvent(name: "onDragBegin", data: sizeInfoData(from: sizeInfo))
187+
dispatchEvent(name: "onDragBegin", block: onDragBegin, data: sizeInfoData(from: sizeInfo))
186188
case .changed:
187-
dispatchEvent(name: "onDragChange", data: sizeInfoData(from: sizeInfo))
189+
dispatchEvent(name: "onDragChange", block: onDragChange, data: sizeInfoData(from: sizeInfo))
188190
case .ended, .cancelled:
189-
dispatchEvent(name: "onDragEnd", data: sizeInfoData(from: sizeInfo))
191+
dispatchEvent(name: "onDragEnd", block: onDragEnd, data: sizeInfoData(from: sizeInfo))
190192
default:
191193
Logger.info("Drag state is not supported")
192194
}
193195
}
194196

195197
func viewControllerWillAppear() {
196-
setupScrollable()
198+
guard let contentView, let scrollView, let containerView else {
199+
return
200+
}
201+
202+
// Add constraints to fix weirdness and support ScrollView
203+
contentView.pinTo(view: containerView, constraints: nil)
204+
scrollView.pinTo(view: contentView, constraints: nil)
197205
}
198206

199207
func viewControllerDidDismiss() {
200208
isPresented = false
201209
activeIndex = nil
202-
dispatchEvent(name: "onDismiss", data: nil)
210+
dispatchEvent(name: "onDismiss", block: onDismiss, data: nil)
203211
}
204212

205213
func viewControllerDidChangeSize(_ sizeInfo: SizeInfo?) {
206214
guard let sizeInfo else { return }
207215

208216
if sizeInfo.index != activeIndex {
209217
activeIndex = sizeInfo.index
210-
dispatchEvent(name: "onSizeChange", data: sizeInfoData(from: sizeInfo))
218+
dispatchEvent(name: "onSizeChange", block: onSizeChange, data: sizeInfoData(from: sizeInfo))
211219
}
212220
}
213221

@@ -257,19 +265,18 @@ class TrueSheetView: UIView, RCTInvalidating, TrueSheetViewControllerDelegate {
257265
@objc
258266
func setFooterHeight(_ height: NSNumber) {
259267
let footerHeight = CGFloat(height.floatValue)
260-
guard let footerView, let footerViewHeightConstraint,
261-
viewController.footerHeight != footerHeight else {
268+
guard let footerView, viewController.footerHeight != footerHeight else {
262269
return
263270
}
264271

265272
viewController.footerHeight = footerHeight
266273

267274
if footerView.subviews.first != nil {
268275
containerView?.bringSubviewToFront(footerView)
269-
footerViewHeightConstraint.constant = viewController.footerHeight
276+
footerConstraints?.height?.constant = viewController.footerHeight
270277
} else {
271278
containerView?.sendSubviewToBack(footerView)
272-
footerViewHeightConstraint.constant = 0
279+
footerConstraints?.height?.constant = 0
273280
}
274281

275282
if #available(iOS 15.0, *) {
@@ -366,7 +373,7 @@ class TrueSheetView: UIView, RCTInvalidating, TrueSheetViewControllerDelegate {
366373

367374
@objc
368375
func setScrollableHandle(_ tag: NSNumber?) {
369-
scrollableTag = tag
376+
scrollView = uiManager?.view(forReactTag: tag)
370377
}
371378

372379
// MARK: - Methods
@@ -391,22 +398,14 @@ class TrueSheetView: UIView, RCTInvalidating, TrueSheetViewControllerDelegate {
391398
}
392399
}
393400

394-
func setupScrollable() {
395-
guard let contentView, let containerView, let scrollableTag else {
396-
return
397-
}
398-
399-
let scrollView = uiManager?.view(forReactTag: scrollableTag)
400-
401-
// Add constraints to fix weirdness and support ScrollView
402-
if let scrollView {
403-
contentView.pinTo(view: containerView, constraints: nil)
404-
scrollView.pinTo(view: contentView, constraints: nil)
405-
}
406-
}
407-
408-
func dispatchEvent(name: String, data: [String: Any]?) {
409-
eventDispatcher?.send(TrueSheetEvent(viewTag: reactTag, name: name, data: data))
401+
func dispatchEvent(name: String, block: RCTDirectEventBlock?, data: [String: Any]?) {
402+
// eventDispatcher doesn't work in New Arch so we need to call it directly :/
403+
// we needed eventDispatcher for Reanimated to work on old arch.
404+
#if RCT_NEW_ARCH_ENABLED
405+
block?(data)
406+
#else
407+
eventDispatcher?.send(TrueSheetEvent(viewTag: reactTag, name: name, data: data))
408+
#endif
410409
}
411410

412411
func dismiss(promise: Promise) {
@@ -453,7 +452,7 @@ class TrueSheetView: UIView, RCTInvalidating, TrueSheetViewControllerDelegate {
453452
}
454453

455454
let data = self.sizeInfoData(from: self.viewController.currentSizeInfo)
456-
self.dispatchEvent(name: "onPresent", data: data)
455+
self.dispatchEvent(name: "onPresent", block: self.onPresent, data: data)
457456
promise?.resolve(nil)
458457
}
459458
}

0 commit comments

Comments
 (0)