-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix issue with SwiftUI View hosted in a UIHostingController #6
Conversation
Hi Ruslan, Thank you for your suggestion, I have several concerns and want to share them with you:
What do you think with the light of the above? |
Hey,
struct TestView: View {
var body: some View {
ScrollView {
Button("Hello", action: {
print("Hello")
})
.padding()
}
}
}
extension ViewController: BottomSheetPresentationControllerFactory {
public func makeBottomSheetPresentationController(
presentedViewController: UIViewController,
presentingViewController: UIViewController?
) -> BottomSheetPresentationController {
.init(
presentedViewController: presentedViewController,
presentingViewController: presentingViewController,
dismissalHandler: self
)
}
}
extension ViewController: BottomSheetModalDismissalHandler {
public var canBeDismissed: Bool { true }
public func performDismissal(animated: Bool) {
transitionDelegate = nil
presentedViewController?.dismiss(animated: animated, completion: nil)
}
}
class ViewController: UIViewController {
private var transitionDelegate: UIViewControllerTransitioningDelegate?
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton()
button.setTitle("Press me", for: .normal)
button.setTitleColor(.systemBlue, for: .normal)
self.view.addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
button.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
button.addTarget(self, action: #selector(press), for: .touchUpInside)
}
@IBAction func press() {
let viewController = UIHostingController(rootView: TestView())
transitionDelegate = BottomSheetTransitioningDelegate(presentationControllerFactory: self)
viewController.transitioningDelegate = transitionDelegate
viewController.modalPresentationStyle = .custom
viewController.preferredContentSize = .init(width: 300, height: 300)
present(viewController, animated: true, completion: nil)
}
}
|
I've used the same approach with resetting frame in Here is the code (I've used BottomSheet 2.0.0): import UIKit
import SwiftUI
import BottomSheet
struct TestView: View {
var body: some View {
ScrollView {
Button("Hello", action: {
print("Hello")
})
.padding()
}
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton()
button.setTitle("Press me", for: .normal)
button.setTitleColor(.systemBlue, for: .normal)
self.view.addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
button.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
button.addTarget(self, action: #selector(press), for: .touchUpInside)
}
@IBAction func press() {
let viewController = MyHostingController(rootView: TestView())
presentBottomSheet(viewController: viewController, configuration: .default)
}
}
final class MyHostingController<Content: View>: UIHostingController<Content> {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
view.frame = .zero
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
preferredContentSize = view.intrinsicContentSize
}
} Can you verify that it solves your issue? |
Good day, I am author of this fix from openradar :D. I tested this fix on production ios 14 and ios 15. No issues. |
Great! Thank you for taking your time to verify this workaround, then I'm closing the PR 👍 |
I mean no problem with that fix on ios 14 and ios 15 with swiftui :) |
Oh, I see. I though that you've tested the proposed fix above with subclassing. Then I'll reopen the PR. As for testing radar's workaround, besides iOS 14 and iOS 15, there are other supported versions starting from 12. Fixing by subclassing |
In our project on production, I used fix in Bug by apple in transitionContext on during dismiss, if use UIHostingController. I suppose apple don't reset frame to default after dismiss dismissing :(. |
@mikhailmaslo I tested your proposed solution and seems it works fine. I think it is up to you to decide do you want to include this fix on the level of your code or leave the responsibility to other developers to subclass UIHostingController by themself. As for me it will be good to have fix here, because that way everyone will get this fix automatically without any needs to waste time on finding the issue and ways to fix it. I personally spent almost all day until I found what happened and why and how to fix it. |
If you don't mind, I'd make several changes then in suggested workaround:
Then I suppose we can include it to the library 👍 |
Of course
This one sounds good! |
(not insisting on it) In addition, maybe it's worth considering something like this, if it's enough for UIKit / SwiftUI to recalculate the frames let sourceViewFrame = sourceView.frame
sourceView.frame = .zero
sourceView.frame = sourceViewFrame |
As I understand @ivan-gaydamakin said that he didn't have any issues with |
@mikhailmaslo just realised that this is not very good idea just to check it as So we need this code not just for |
Additionally, it's quite complicated to check if a view controller is So, I suggest to make version check (iOS 14+) and do this workaround reseting frame back, as I've proposed above let sourceViewFrame = sourceView.frame
sourceView.frame = .zero
sourceView.frame = sourceViewFrame The reason is that such a trick doesn't work with It's hard to reason about why one thing works and the other not, but in the future versions of iOS this behaviour might change, that's why I suggest to include reseting back to the initial value. What do you think @rusik? |
Yeah, you are right here
Maybe iOS 13+? bc SwiftUI started from that version.
Sounds reasonable, I don't see any issue that might happen with this approach 👍 |
Hey @rusik, did you have a chance to finish discussed fix? |
Or sorry, I thought you are going to fix it by yourself 😁 I just played with it on Xcode 14 with iOS 16 and seems like this bug was fixed by apple 🥳 Surprisingly it also has been fixed for prior iOS versions as well. I don't know how this works, but I built the project with Xcode 13 for iOS 14 and 15 with both BottomSheet 1.0 and 2.0 and in all cases everything was fine. @mikhailmaslo could you please confirm that everything works for you as well, and if so we can close this PR. |
Tested on xcode 14 On simulator ios 16 bug not fixed by apple, still same problem. |
Weird 😧 |
@ivan-gaydamakin what code for test project did you use? |
Damn, sorry guys, I forgot that I need to try to dismiss first 🤦🏻♂️ @mikhailmaslo I just improved the code the way we discussed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉
@mikhailmaslo FYI I don't have merge button, you need to merge by yourself |
@mikhailmaslo I think would be great to bump version to 2.0.1 so everyone can get this fix |
Fix issue for apple bug when buttons inside SwiftUI view stop working after interactive dismiss cancellation
More info here → https://openradar.appspot.com/FB9075949