Hello!
After upgrading to Xcode 16 & Swift 6 & iOS 18 I starting receiveing strange crashes.
Happens randomly in different view and pointing to onGeometryChange action block. I added DispatchQueue.main.async { in hopes it will help but it didn't.
HStack {
...
}
.onGeometryChange(for: CGSize.self, of: \.size) { value in
DispatchQueue.main.async {
self.width = value.width
self.height = value.height
}
}
As far as I understand, onGeometryChange is defined as nonisolated and Swift 6 enforce thread checking for the closures, SwiftUI views are always run on the main thread. Does it mean we can not use onGeometryChange safely in swiftui?
BUG IN CLIENT OF LIBDISPATCH: Assertion failed: Block was expected to execute on queue [com.apple.main-thread (0x1eacdce40)]
Crashed: com.apple.SwiftUI.AsyncRenderer
0 libdispatch.dylib 0x64d8 _dispatch_assert_queue_fail + 120
1 libdispatch.dylib 0x6460 _dispatch_assert_queue_fail + 194
2 libswift_Concurrency.dylib 0x62b58 <redacted> + 284
3 Grit 0x3a57cc specialized implicit closure #1 in closure #1 in PurchaseModalOld.body.getter + 4377696204 (<compiler-generated>:4377696204)
4 SwiftUI 0x5841e0 <redacted> + 60
5 SwiftUI 0x5837f8 <redacted> + 20
6 SwiftUI 0x586b5c <redacted> + 84
7 SwiftUICore 0x68846c <redacted> + 48
8 SwiftUICore 0x686dd4 <redacted> + 16
9 SwiftUICore 0x6ecc74 <redacted> + 160
10 SwiftUICore 0x686224 <redacted> + 872
11 SwiftUICore 0x685e24 $s14AttributeGraph12StatefulRuleP7SwiftUIE15withObservation2doqd__qd__yKXE_tKlF + 72
12 SwiftUI 0x95450 <redacted> + 1392
13 SwiftUI 0x7e438 <redacted> + 32
14 AttributeGraph 0x952c AG::Graph::UpdateStack::update() + 540
15 AttributeGraph 0x90f0 AG::Graph::update_attribute(AG::data::ptr<AG::Node>, unsigned int) + 424
16 AttributeGraph 0x8cc4 AG::Subgraph::update(unsigned int) + 848
17 SwiftUICore 0x9eda58 <redacted> + 348
18 SwiftUICore 0x9edf70 <redacted> + 36
19 AttributeGraph 0x148c0 AGGraphWithMainThreadHandler + 60
20 SwiftUICore 0x9e7834 $s7SwiftUI9ViewGraphC18updateOutputsAsync2atAA11DisplayListV4list_AG7VersionV7versiontSgAA4TimeV_tF + 560
21 SwiftUICore 0x9e0fc0 $s7SwiftUI16ViewRendererHostPAAE11renderAsync8interval15targetTimestampAA4TimeVSgSd_AItF + 524
22 SwiftUI 0xecfdfc <redacted> + 220
23 SwiftUI 0x55c84 <redacted> + 312
24 SwiftUI 0x55b20 <redacted> + 60
25 QuartzCore 0xc7078 <redacted> + 48
26 QuartzCore 0xc52b4 <redacted> + 884
27 QuartzCore 0xc5cb4 <redacted> + 456
28 CoreFoundation 0x555dc <redacted> + 176
29 CoreFoundation 0x55518 <redacted> + 60
30 CoreFoundation 0x55438 <redacted> + 524
31 CoreFoundation 0x54284 <redacted> + 2248
32 CoreFoundation 0x535b8 CFRunLoopRunSpecific + 572
33 Foundation 0xb6f00 <redacted> + 212
34 Foundation 0xb6dd4 <redacted> + 64
35 SwiftUI 0x38bc80 <redacted> + 792
36 SwiftUI 0x1395d0 <redacted> + 72
37 Foundation 0xc8058 <redacted> + 724
38 libsystem_pthread.dylib 0x637c _pthread_start + 136
39 libsystem_pthread.dylib 0x1494 thread_start + 8
Post
Replies
Boosts
Views
Activity
Hi, my I know what is wrong with my code, I have a unintended border around my game although there is no padding, can someone help me thanks!
This is my code:
`
Dear DTS Engineer,
I hope this message finds you well. I am currently developing a Mac desktop application using the GTKMM framework, and I have some questions regarding the distribution of such an application through the Mac App Store.
Project Context:
I am building a native Mac desktop application using GTKMM as the UI framework. As GTKMM does not rely on macOS's AppKit or UIKit, my application does not use these Apple-specific frameworks for the UI. Instead, GTKMM provides its own cross-platform UI components. While this approach allows me to target macOS alongside Linux and Windows, I am uncertain whether this setup will be compatible with the Mac App Store's submission guidelines.
My Questions:
App Store Compatibility: Is it possible to distribute a macOS desktop application built with GTKMM (without using AppKit or UIKit) on the Mac App Store?
App Store Guidelines: Are there specific App Store guidelines I should be aware of when submitting a non-native, non-AppKit UI-based app, such as one using GTKMM for macOS?
Notarization & Code Signing: Does my app need to use AppKit/UIKit to meet the code signing and notarization requirements, or can I proceed with signing and notarizing a GTKMM-based app?
App Store Review Process: Will the absence of AppKit/UIKit affect the review process or the acceptance of the app into the Mac App Store?
I would greatly appreciate any guidance or clarification on these points. If you need additional details about my development environment or the specific technologies I'm using, please let me know.
Thank you for your time and assistance.
Hi. If the app is in landscape only and when the SKStoreProductViewController is presented, the safeArea changes to what looks like a portrait mode safe area. When the SKStoreProductViewController is dismissed, the safeArea does NOT revert back to the original values.
Is there a way to force the safeArea to "reset"? I've submitted some bug tickets through Apple Feedback but I haven't received any response about it.
The below code will pop up the SKStoreProductViewController and if you have a UIView that is constrained to the safe area, then you can visibly notice that the safe area is changed and doesn't go back.
I have tested this on iPhone 14 Pro, iPhone 15, and iPhone 16 Pro and in the Simulators. The incorrect behavior happens on those and probably more.
Thanks.
#import "ViewController.h"
#import &lt;StoreKit/StoreKit.h&gt;
@interface ViewController ()
@property (nonatomic, strong) SKStoreProductViewController *productViewController;
@end
@implementation ViewController
- (IBAction)buttonTapped:(id)sender {
self.productViewController = [[SKStoreProductViewController alloc] init];
NSDictionary *parameters = @{
@"id" : @"6443575749"
};
[self.productViewController loadProductWithParameters:parameters completionBlock:^(BOOL result, NSError * _Nullable error) {
[self presentViewController:self.productViewController animated:YES completion:^{
// presented
// The panel that is constraint to the safe area visibly shows that the safe area is no longer correct.
}];
}];
}
@end
Hello everyone,
I’m experiencing an issue with the Android Emulator in Android Studio (version Ladybug) on my Mac running macOS Monterey (12.7). The emulator frequently displays the message “System UI isn’t responding” and then crashes.
I've tried a few troubleshooting steps, including:
Restarting Android Studio and the emulator.
wipe data on AVD.
tried to change the emulator performance from automatic to hardware but this option isn't available to me.
Despite these efforts, the problem persists. Has anyone else encountered this issue? Any suggestions or solutions would be greatly appreciated!
Hey, I have an app that user selects wallpaper for iPhone. I want a feature that user can set wallpaper direct from app itself for lock screen and home screen not download the image and manually set the wallpaper. As my research there was a PhotoLibrary api that contains PLWallpaperImageViewController.h which allows you to set wallpaper directly.
Thank You!
If I put the phone flat on a table, the left and right swipe gestures is not working but up and down gestures works.
Only when I put the iPhone to some vertical degree, the left and right swipe works.
Tested on 2 iPhone 7 Plus and 2 iPhone 13.
Anyone has similar experience? If yes, why?
I am trying to change UITabBar background color runtime as theme changed. It is already working in iOS 17 as I am updating UITabBar.appearance().barTintColor and tintColor
But for iOS first i need to change because I don't want that new elevated tabbar so I create custom tabbar controller as described in
https://stackoverflow.com/questions/78631030/how-to-disable-the-new-uitabbarcontroller-view-style-in-ipados-18
Accepted Answer by awulf.
And by doing this, My tabbar looks same like Old and it is working in iPhone and ipad for iOS 16, iOS 17 and iOS 18 too.
But the issue is that I am unable to change my tabbar background color.
I have also checked this forum: https://forums.developer.apple.com/forums/thread/761056
But not able to change
I have set below 3 properties but no effect
let appearance = UITabBar.appearance()
appearance.backgroundColor =
appearance.barTintColor =
appearance.tintColor =
I have created CustomTabBarController in storyboard and all working fine
Also the appearance changed only once per application lifecycle.
It will change color by restarting the app then it will pick last selected theme and the colors are changed.
but not able to change colors runtime
I have also did below code for reloading purpose
tabBar.setNeedsLayout()
tabBar.setNeedsDisplay()
But nothing work
We're trying to implement a backup/restore data feature in our business productivity iPad app using UIDocumentPickerViewController and AppleArchive, but discovered odd behavior of [UIDocumentPickerViewController initForOpeningContentTypes: asCopy:YES] when reading large archive files from a USB drive.
We've duplicated this behavior with iPadOS 16.6.1 and 17.7 when building our app with Xcode 15.4 targeting minimum deployment of iPadOS 16. We haven't tested this with bleeding edge iPadOS 18.
Here's our Objective-C code which presents the picker:
NSArray* contentTypeArray = @[UTTypeAppleArchive];
UIDocumentPickerViewController* docPickerVC = [[UIDocumentPickerViewController alloc] initForOpeningContentTypes:contentTypeArray asCopy:YES];
docPickerVC.delegate = self;
docPickerVC.allowsMultipleSelection = NO;
docPickerVC.shouldShowFileExtensions = YES;
docPickerVC.modalPresentationStyle = UIModalPresentationPopover;
docPickerVC.popoverPresentationController.sourceView = self.view;
[self presentViewController:docPickerVC animated:YES completion:nil];
The UIDocumentPickerViewController remains visible until the selected external archive file has been copied from the USB drive to the app's local tmp sandbox. This may take several seconds due to the slow access speed of the USB drive. During this time the UIDocumentPickerViewController does NOT disable its tableview rows displaying files found on the USB drive. Even the most patient user will tap the desired filename a second (or third or fourth) time since the user's initial tap appears to have been ignored by UIDocumentPickerViewController, which lacks sufficient UI feedback showing it's busy copying the selected file.
When the user taps the file a second time, UIDocumentPickerViewController apparently begins to copy the archive file once again. The end result is a truncated copy of the selected file based on the time between taps. For instance, a 788 MB source archive may be copied as a 56 MB file. Here, the UIDocumentPickerDelegate receives a 56 MB file instead of the original 788 MB of data.
Not surprisingly, AppleArchive fails to decrypt the local copy of the archive because it's missing data. Instead of failing gracefully, AppleArchive crashes in AAArchiveStreamClose() (see forums post 765102 for details).
Does anyone know if there's a workaround for this strange behavior of UIDocumentPickerViewController?
Hi everyone,
I’m wondering about Core Data. When creating a private context using newBackgroundContext(), does it automatically set the parent to the view context, or is it independent?
Additionally, if I update objects in the context created by newBackgroundContext(), will the view context automatically notice the changes, and vice versa?
Lastly, are there other ways to set parent-child context relationships between contexts?
I'd appreciate it if anyone could clarify this for me.
Thanks in advance! 😊
Hi All!
I've encountered a SwiftUI NavigationSplitView bug in my app that I'd appreciate help with, I've spent quite some time trying to work out a solution to this problem.
I have a main list, which has either a Location or LocationGroup. When selecting a Location, the detail view is presented.
When selecting a LocationGroup, a subsequent list of Locations are presented (from the group).
When tapping on any of these Locations, the NavigationStack does not animate (push the view), and when tapping back from it, it jumps to the main selection.
The overall goal is to be able to present within the detail: of a NavigationSplitView a NavigationStack, and to be able to push onto that stack from both the main NavigationSplitView's list, and from the detail.
I created the following sample code that reproduces the issue:
ContentView.swift
public enum LocationSplitViewNavigationItem: Identifiable, Hashable {
case location(Location)
case locationGroup(LocationGroup)
public var id: UUID? {
switch self {
case .location(let location):
return location.id
case .locationGroup(let locationGroup):
return locationGroup.id
}
}
}
struct ContentView: View {
@State private var columnVisibility = NavigationSplitViewVisibility.doubleColumn
@State private var selectedNavigationItem: LocationSplitViewNavigationItem?
var body: some View {
NavigationSplitView(columnVisibility: $columnVisibility) {
LocationListView(selectedItem: $selectedNavigationItem, locationData: LocationSampleData(locations: LocationSampleData.sampleLocations, locationGroups: LocationSampleData.sampleLocationGroups))
} detail: {
if let selectedLocation = selectedNavigationItem {
switch selectedLocation {
case .location(let location):
LocationDetailView(selectedLocation: location)
case .locationGroup(let locationGroup):
LocationListView(selectedItem: $selectedNavigationItem, locationData: LocationSampleData(locations: locationGroup.locations))
}
}
}
.navigationSplitViewStyle(.balanced)
}
}
LocationListView.swift
struct LocationListView: View {
@Binding public var selectedItem: LocationSplitViewNavigationItem?
var locationData: LocationSampleData
var body: some View {
List(selection: $selectedItem) {
if let locations = locationData.locations {
ForEach(locations) { location in
NavigationLink(value: LocationSplitViewNavigationItem.location(location)) {
Text(location.name)
.bold()
}
}
}
if let locationGroups = locationData.locationGroups {
ForEach(locationGroups) { locationGroup in
NavigationLink(value: LocationSplitViewNavigationItem.locationGroup(locationGroup)) {
Text(locationGroup.name)
.bold()
.foregroundStyle(.red)
}
}
}
}
.navigationTitle("Saturday Spots")
.navigationBarTitleDisplayMode(.large)
}
}
LocationDetailView.swift
struct LocationDetailView: View {
var selectedLocation: Location
var body: some View {
Text(selectedLocation.name)
.font(.largeTitle)
.bold()
.foregroundStyle(LinearGradient(
colors: [.teal, .indigo],
startPoint: .top,
endPoint: .bottom
))
.toolbarBackground(
Color.orange,
for: .navigationBar
)
.toolbarBackground(.visible, for: .navigationBar)
}
}
Location.swift
import CoreLocation
struct LocationSampleData {
var locations: [Location]?
var locationGroups: [LocationGroup]?
static let sampleLocations: [Location]? = Location.sample
static let sampleLocationGroups: [LocationGroup]? = [LocationGroup.sample]
}
public struct Location: Hashable, Identifiable {
var name: String
var coordinates: CLLocationCoordinate2D
var photo: String
public var id = UUID()
static public let sample: [Location] = [
Location(name: "Best Bagel & Coffee", coordinates: CLLocationCoordinate2D(latitude: 123, longitude: 121), photo: "asdf"),
Location(name: "Absolute Bagels", coordinates: CLLocationCoordinate2D(latitude: 123, longitude: 121), photo: "asdf"),
Location(name: "Tompkins Square Bagels", coordinates: CLLocationCoordinate2D(latitude: 123, longitude: 121), photo: "asdf"),
Location(name: "Zabar's", coordinates: CLLocationCoordinate2D(latitude: 123, longitude: 121), photo: "asdf"),
]
static public let oneSample = Location(name: "Absolute Bagels", coordinates: CLLocationCoordinate2D(latitude: 123, longitude: 121), photo: "asdf")
}
public struct LocationGroup: Identifiable, Hashable {
var name: String
var locations: [Location]
public var id = UUID()
static public let sample: LocationGroup = LocationGroup(name: "Bowling", locations: [
Location(name: "Frames Bowling Lounge", coordinates: CLLocationCoordinate2D(latitude: 123, longitude: 121), photo: "asdf"),
Location(name: "Bowlero Chelsea Piers", coordinates: CLLocationCoordinate2D(latitude: 123, longitude: 121), photo: "asdf")
])
}
extension CLLocationCoordinate2D: Hashable {
public static func == (lhs: Self, rhs: Self) -> Bool {
return lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude
}
public func hash(into hasher: inout Hasher) {
hasher.combine(latitude)
hasher.combine(longitude)
}
}
I have a CarPlay navigation app and I would like to allow the user to speak an address and have our app search at that location.
In the Waze app, it provides a button to tap, then it brings up a CPVoiceControlTemplate and you can give it directions or a location and it will then show you search results including the text you spoke as the title. I assume that app would have the same limitations as I do, so I am wondering how another app might do this?
It was suggested that I use an App Intent with suggested phrases and then a Shortcut could perform the action. Is there documentation on this somewhere or am I going in the wrong direction here?
Obviously Waze is doing what I am wanting so there must be a way. Can anyone point me in the right direction?
So basically, if I put a .navigationModifier inside of a NavigationStack that's inside of a TabView, AND I supply a path argument to NavigationStack. I get this error:
Do not put a navigation destination modifier inside a "lazy” container, like `List` or `LazyVStack`. These containers create child views only when needed to render on screen. Add the navigation destination modifier outside these containers so that the navigation stack can always see the destination. There's a misplaced `navigationDestination(for:destination:)` modifier for type `NavPath`. It will be ignored in a future release.
Does TabView or NavigationStack suddenly become lazy when I put the path parameter in? It also causes weird unexplained behavior if I start removing tabs using state, but I do think I'm not supposed to do that.
Code for reference:
var body: some View {
@Bindable var nm = navManager
TabView{
NavigationStack(path: $nm.pathStack){
HomeView() // A custom view
.navigationDestination(for: NavPath.self) { np in // NavPath is a custom struct that's hashable
switch np.pathId {
case "home":
NavigationLazyView(HomeView()) // Ignore the NavigationLazyView, does not affect
...
I have a UIViewController that presents a UIPrintInteractionController when a user selects the print button on the UI. The problem is starting in iOS 18 (currently using beta 7) when the print controller is presented the UIViewController's viewWillAppear() is being called. This did not happen in earlier iOS releases and is causing unwanted behavior in the app. Is this a bug or will this be the behavior going forward?
Hi All,
I'm very new to iOS development and Swift UI is my first coding language. I'm trying to link the users search results in Spotlight with the detail view that is stored in Core Data. I can search for users data in spotlight but when I tap on it, it's only appearing in the main view of the app. Is there anyways that I can use .onContinueUserActivity at the launch of the app or is there any different code that I have to use? I've searched for many articles but I couldn't get a solution. It would be good if anyone can share some links or guide here. Thank you.
.onContinueUserActivity(DetailView.productUserActivityType) { userActivity in
if let product = try? userActivity.typedPayload(Product.self) {
selectedProduct = product.id.uuidString
}
}
I get this code from Apple's State restoration app but I can't use this with Core Data.
Hi there! My app supports one language by default Ukrainian (uk) and does not support multiple languages. In Xcode settings "Development Language" is set to Ukrainian by default also. I have a PKAddPassButton on a ViewController and "Add to Apple Wallet" always appears in Ukrainian (Tested on real device iOS 15/16/17). Apple's "Getting Started with Apple Pay: In-App Provisioning, Verification, Security, and Wallet Extensions” document states that "The Add to Apple Wallet button adapts to the device language and the light and dark appearances, but the issuer app needs to adapt the language of the row selector text." When I change device language to French the “Add to Apple Wallet” button does not change to French. I created a fresh swift app, added PKAddPassButton the "Add to Apple Wallet" button, General -> Language & Region changed the device language to French, etc, but the "Add to Apple Wallet" button is always in English. Has anyone run into the same issue? How to adapt the "Add to Apple Wallet" button to the device system language?
UITextView erroneously overrides string attributes when applying spellchecker annotation attributes.
It doesn't need any particular setting. Default UITextView instance with attributed text
let textView = UITextView(usingTextLayoutManager: true)
textView.spellCheckingType = .yes
Once spellcheck attributes get applied, other attributes like foreground color get applied to the misspelled words. This behavior happens only on Mac Catalyst, and started to appear on macOS 14 or newer.
Please check the Xcode project that demonstrates the issue https://github.com/user-attachments/files/16689336/TextEditor-FB14165227.zip
Open TextEditor project
Select "My Mac (Mac Catalyst)" build destination
Run the project. A window with a text area should appear
Select the whole text (either using mouse or keyboard command+a)
Observe how foregroundColor changes to text (this is the issue)
That eventually led to crash 💥
This bug is reported to Apple FB14165227
How to capture program crash exceptions with swift UI
I made a custom slider by subclassing UISlider, and I'm trying to add scrubbing functionality to it, but for some reason the scrubbing is barely even noticeable at 0.1? In my code, I tried multiplying change in x distance by the scrubbing value, but it doesn't seem to work. Also, when I manually set the scrubbing speed to a lower value such as 0.01, it does go slower but it looks really laggy and weird?? What am I doing wrong?
Any help or advice would be greatly appreciated!
Subclass of UISlider:
class SizeSliderView: UISlider {
private var previousLocation: CGPoint?
private var currentLocation: CGPoint?
private var translation: CGFloat = 0
private var scrubbingSpeed: CGFloat = 1
private var defaultDiameter: Float
init(startValue: Float = 0, defaultDiameter: Float = 500) {
self.defaultDiameter = defaultDiameter
super.init(frame: .zero)
value = clamp(value: startValue, min: minimumValue, max: maximumValue)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func draw(_ rect: CGRect) {
super.draw(rect)
clear()
createThumbImageView()
addTarget(self, action: #selector(valueChanged(_:)), for: .valueChanged)
}
// Clear elements
private func clear() {
tintColor = .clear
maximumTrackTintColor = .clear
backgroundColor = .clear
thumbTintColor = .clear
}
// Call when value is changed
@objc private func valueChanged(_ sender: SizeSliderView) {
CATransaction.begin()
CATransaction.setDisableActions(true)
CATransaction.commit()
createThumbImageView()
}
// Create thumb image with thumb diameter dependent on thumb value
private func createThumbImageView() {
let thumbDiameter = CGFloat(defaultDiameter * value)
let thumbImage = UIColor.red.circle(CGSize(width: thumbDiameter, height: thumbDiameter))
setThumbImage(thumbImage, for: .normal)
setThumbImage(thumbImage, for: .highlighted)
setThumbImage(thumbImage, for: .application)
setThumbImage(thumbImage, for: .disabled)
setThumbImage(thumbImage, for: .focused)
setThumbImage(thumbImage, for: .reserved)
setThumbImage(thumbImage, for: .selected)
}
// Return true so touches are tracked
override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
let location = touch.location(in: self)
// Ensure that start location is on thumb
let thumbDiameter = CGFloat(defaultDiameter * value)
if location.x < bounds.width / 2 - thumbDiameter / 2 || location.x > bounds.width / 2 + thumbDiameter / 2 || location.y < 0 || location.y > thumbDiameter {
return false
}
previousLocation = location
super.beginTracking(touch, with: event)
return true
}
// Track based on moving slider
override func continueTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
guard isTracking else { return false }
guard let previousLocation = previousLocation else { return false }
// Reference
// location: location of touch relative to device
// delta location: change in touch location WITH scrubbing
// adjusted location: location of touch to slider bounds (WITH scrubbing)
// translation: location of slider relative to device
let location = touch.location(in: self)
currentLocation = location
scrubbingSpeed = getScrubbingSpeed(for: location.y - 50)
let deltaLocation = (location.x - previousLocation.x) * scrubbingSpeed
var adjustedLocation = deltaLocation + previousLocation.x - translation
if adjustedLocation < 0 {
translation += adjustedLocation
adjustedLocation = deltaLocation + previousLocation.x - translation
} else if adjustedLocation > bounds.width {
translation += adjustedLocation - bounds.width
adjustedLocation = deltaLocation + previousLocation.x - translation
}
self.previousLocation = CGPoint(x: deltaLocation + previousLocation.x, y: location.y)
let newValue = Float(adjustedLocation / bounds.width) * (maximumValue - minimumValue) + minimumValue
setValue(newValue, animated: false)
sendActions(for: .valueChanged)
return true
}
// Reset start and current location
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
self.currentLocation = nil
self.translation = 0
super.touchesEnded(touches, with: event)
}
// Thumb location follows current location and resets in middle
override func thumbRect(forBounds bounds: CGRect, trackRect rect: CGRect, value: Float) -> CGRect {
let thumbDiameter = CGFloat(defaultDiameter * value)
let origin = CGPoint(x: (currentLocation?.x ?? bounds.width / 2) - thumbDiameter / 2, y: (currentLocation?.y ?? thumbDiameter / 2) - thumbDiameter / 2)
return CGRect(origin: origin, size: CGSize(width: thumbDiameter, height: thumbDiameter))
}
private func getScrubbingSpeed(for value: CGFloat) -> CGFloat {
switch value {
case 0:
return 1
case 0...50:
return 0.5
case 50...100:
return 0.25
case 100...:
return 0.1
default:
return 1
}
}
private func clamp(value: Float, min: Float, max: Float) -> Float {
if value < min {
return min
} else if value > max {
return max
} else {
return value
}
}
}
UIView representative:
struct SizeSlider: UIViewRepresentable {
private var startValue: Float
private var defaultDiameter: Float
init(startValue: Float, defaultDiameter: Float) {
self.startValue = startValue
self.defaultDiameter = defaultDiameter
}
func makeUIView(context: Context) -> SizeSliderView {
let view = SizeSliderView(startValue: startValue, defaultDiameter: defaultDiameter)
view.minimumValue = 0.1
view.maximumValue = 1
return view
}
func updateUIView(_ uiView: SizeSliderView, context: Context) {}
}
Content view:
struct ContentView: View {
var body: some View {
SizeSlider(startValue: 0.20, defaultDiameter: 100)
.frame(width: 400)
}
}
I'm working on a SwiftUI application that uses programmatic navigation with enums in a NavigationStack. My app is structured around a TabView with different tabs, each having its own navigation stack. I need to navigate to the same view from different tabs, but each tab has a separate navigation stack with custom paths.
Here's a simplified version of my setup:
class AppState: ObservableObject {
@Published var selectedTab: Tab = .feeds
@Published var tabANavigation: [TabANavDestination] = []
@Published var tabBNavigation: [TabBNavDestination] = []
}
enum TabANavDestination: Hashable {
case itemList()
case itemDetails(String)
}
enum TabBNavDestination: Hashable {
case storeList()
case itemList()
case itemDetails(String)
}
For example:
TabA: ItemsListScreen -> DetailsScreen.
TabB: StoreList -> ItemsListScreen -> DetailsScreen
I want to navigate from ItemsListScreen to DetailsScreen, but I can't use the same method to append the navigation state in both tabs:
appState.tabANavigation.append(.itemDetails(id))
How can I manage navigation across these different tabs, ensuring that the same screen (e.g., DetailsScreen) is accessible from different paths and tabs with their own navigation stacks? What’s the best approach to handle this scenario in a complex navigation setup?