SwiftUI equivalent to apportionsSegmentWidthsByContent? - swiftui

In SwiftUI .pickerStyle(SegmentedPickerStyle()) will give you a SegmentedControl with all segments having equal size.
How do we do the SwiftUI equivalent to setting the UIKit property apportionsSegmentWidthsByContent = true

There is no equivalent apportionsSegmentWidthsByContent property in SwiftUI,
also the PickerStyle protocol its defined internally so you have 3 options
Set the property globally, all segmented controls in your SwiftUI project will be affected.
UISegmentedControl.appearance().apportionsSegmentWidthsByContent = true
Use UIViewRepresentable to wrap the UIKit segmented control
make your own picker, experiments
SwiftUI Custom PickerStyle

Related

Change Title Bar Colour SwiftUI (No NavigationView nor .ignoresSafeArea())

There are two solutions I have seen can be used to change the colour of the title bar in SwiftUI:
Making the use of NavigationView
Ignoring the sage area with .ignoresSafeArea()
I have no use for a NavigationView nor I want to use .ignoresSafeArea() since it helps on giving the TabView bottom tab space.
The only requirement to the solution I am looking for is that it cannot be for iOS 16 and above only, since it will not be viable to use in production for at least the next two years.
TL;DR:
I need to change the colour of the title bar (the upper-most part of the app) with features available in versions prior to iOS 16, and without the use of NavigationView and .ignoresSafeArea()
The white stuff in this image:

SwiftUI: deinit equivalent?

What is the equivalent of UIKit View's deinit for a SwiftUI view?
I have looked at .onDisappear... but, it does not seem to me that is the hook I should be using to know when a SwiftUI View is gone for good, for example during navigation etc...

Does UIHostingController have to be in the view controller hierarchy?

I want to embed some SwiftUI in my UIKit-based UI, and unfortunately Apple doesn't provide UIHostingView, only UIHostingController. Can I more or less ignore that controller and just use its view, or do I really need to add it as a child view controller as well? What happens if I don't?
The problem is that finding the parent view controller can be difficult in some contexts. UIView itself doesn't know anything about view controllers, so I'd have to come up with my own way of keeping track of which is the "current" view controller. And I'd rather not do that unless it's actually necessary.
So far in my experiments it's working fine without adding UIHostingController as a child. Device rotation is handled appropriately, and SwiftUI's dark mode override (.colorScheme()) even works through the embedding.
With UIHostingController(rootView:) you just pass in a SwiftUI View.
You can treat it as a UIView by doing:
let myView = UIHostingController(rootView: Text("Hello world!")).view
And then add it as a subview for example:
let parent = UIView()
parent.addSubview(myView)

SwiftUI TextField does not work after adding gesture

After adding a combined gesture to a view, a TextField inside the view would no longer respond when I would tap into it to change the text. I discovered this after adding a custom combined gesture - where I used a long press to start things before dragging. (Note: things still worked if just a drag gesture was added. Not sure what is particularly different between these two cases.)
The combined gesture:
let combined = longPressGesture.simultaneously(with: dragGesture)
The gesture was added to the view with:
.gesture(combined)
I got things to work by adding an onTapGesture{} to the TextField. Didn’t have to put anything into the action. Seems like a side effect whose behavior could change in the future. Appreciate any comments on if this makes sense or other ways to handle.
TextField(“Enter Text”, text: $myText)
.textFieldStyle(RoundedBorderTextFieldStyle())
.onTapGesture {}
In case one would have this issue with a drag gesture, you can set the minimumDistance. This would still register the tap on the textfield to edit it.
DragGesture(minimumDistance: 30, coordinateSpace: .global)
Adding a drag gesture in SwiftUI to a View inside a ScrollView blocks the scrolling

UIViewRepresentable not sizing correctly in ScrollView

I followed Apple's guide on using UIPageViewController with SwiftUI. Their guide works fine. However I ran into an issue, where if I have my PageView inside a ScrollView - the height of the PageView is no longer respected and I have to set the frame manually. Not ideal, as the content inside PageView is dynamic and thus, heights will vary.
This seems to be an issue with ScrollView; as I have another view - UIViewRepresentable - that is a simple wrapper around WKWebView - with the same issue.
Is there a way to have these views size themselves, inside a SwiftUI ScrollView?
If I place these views outside of a ScrollView and into a simple VStack for example, they size themselves correctly.