Provide views, controls, and layout structures for declaring your app's user interface using SwiftUI.

Posts under SwiftUI tag

200 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

How to extend my exist Toggle with intents
I create a toggle component based on Toggle public struct Checkbox: View { ... public init(...) { ... } public var body: some View { return HStack(spacing: 8) { ZStack { Toggle("", isOn: $isPrivateOn) ... } ... } } } how can I create a init method to support init with AppIntent like: // Available when SwiftUI is imported with AppIntents @available(iOS 17.0, macOS 14.0, tvOS 17.0, watchOS 10.0, *) extension Toggle { /// Creates a toggle performing an `AppIntent`. /// /// - Parameters: /// - isOn: Whether the toggle is on or off. /// - intent: The `AppIntent` to be performed. /// - label: A view that describes the purpose of the toggle. public init<I>(isOn: Bool, intent: I, @ViewBuilder label: () -> Label) where I : AppIntent }
0
0
42
7h
Background updates with the app closed
Hello everyone, I am spending a lot of work with an application, this is based on obtaining the information from the official USCIS website, the user enters their receipt and it verifies on the USCIS website if that receipt exists, once verified it returns the information of that receipt, which I save in coredata so that the user only has to press a button to reload that information, all this is perfect, the problem is that I want the cases to be updated in the background so that the user does not have to be Entering the application, it is responsible for updating only the cases and if there was a change in your case, showing a notification to the user, I have the function of updating the cases so that when it detects a change in the database it notifies the change to the user. user, I have read the documentation but Background Task, Fetch etc. does work for me if the application is in the background that is, not closed, but when it is closed completely it does not update these cases, I have read in groups and with silent notifications to lift the application but I don't want to depend on a server, is there a method to call the function to update the cases when the application is closed (SwiftUI - Swift for iOS I am programming)
0
0
68
11h
Passing touches from UIView to a child view?
I made an extension with a UIView that takes a SwiftUI view, gets its UIView, and then adds it as a subview. But now the subview isn't receiving any touches and idk how to fix that. I've already tried point(inside:with:) but it doesn't seem to work. I've also tried forwarding the touches from touchesBegan, touchesMoved, etc., but that didn't work either. Any help or advice would be greatly appreciated! Extension with the UIView: // Add view modifier to View extension View { func transformable() -> some View { modifier(Transformable()) } } // View modifier struct Transformable: ViewModifier { func body(content: Content) -> some View { TransformableUIView(content: content) } } // Wrap UIView struct TransformableUIView<V>: UIViewRepresentable where V: View { private var content: V init(content: V) { self.content = content } func makeUIView(context: Context) -> TransformableView<V> { TransformableView(content: content) } func updateUIView(_ uiView: TransformableView<V>, context: Context) {} } // View that handles zoom, pan, and rotate gestures class TransformableView<V>: UIView, UIGestureRecognizerDelegate where V: View { private var content: V private var initialCenter: CGPoint = .zero private var totalScale: CGFloat = 1.0 private var boundsDidSet = false required init(content: V) { self.content = content super.init(frame: .zero) self.addSubview(content.uiView) let panGesture = UIPanGestureRecognizer(target: self, action: #selector(panPiece(_:))) panGesture.minimumNumberOfTouches = 2 panGesture.maximumNumberOfTouches = 2 panGesture.delegate = self self.addGestureRecognizer(panGesture) let scaleGesture = UIPinchGestureRecognizer(target: self, action: #selector(scalePiece(_:))) scaleGesture.delegate = self self.addGestureRecognizer(scaleGesture) let rotateGesture = UIRotationGestureRecognizer(target: self, action: #selector(rotatePiece(_:))) rotateGesture.delegate = self self.addGestureRecognizer(rotateGesture) } // Position content in center of view override func layoutSubviews() { super.layoutSubviews() // Return if bounds are already set if boundsDidSet { return } guard let piece = self.subviews.first else { return } piece.center = CGPoint(x: self.bounds.size.width / 2, y: self.bounds.size.height / 2) boundsDidSet = true } // Function called when pan gesture is recognized @objc private func panPiece(_ gestureRecognizer: UIPanGestureRecognizer) { guard let piece = gestureRecognizer.view?.subviews.first else { return } // Get the changes in the X and Y directions relative to // the superview's coordinate space. let translation = gestureRecognizer.translation(in: piece.superview) if gestureRecognizer.state == .began { // Save the view's original position. self.initialCenter = piece.center } // Update the position for the .began, .changed, and .ended states if gestureRecognizer.state != .cancelled { // Add the X and Y translation to the view's original position. var newCenter = CGPoint(x: initialCenter.x + translation.x, y: initialCenter.y + translation.y) // Prevent content from leaving view newCenter.x = clamp(value: newCenter.x, min: 0, max: self.bounds.width) newCenter.y = clamp(value: newCenter.y, min: 0, max: self.bounds.height) piece.center = newCenter } else { // On cancellation, return the piece to its original location. piece.center = initialCenter } } // Function called when scale gesture is recognized @objc private func scalePiece(_ gestureRecognizer : UIPinchGestureRecognizer) { guard let piece = gestureRecognizer.view?.subviews.first else { return } if gestureRecognizer.state == .began || gestureRecognizer.state == .changed { // Set min/max zoom let newScale = clamp(value: totalScale * gestureRecognizer.scale, min: 0.2, max: 20) / totalScale piece.transform = (piece.transform.scaledBy(x: newScale, y: newScale)) gestureRecognizer.scale = 1.0 totalScale *= newScale } } // Function called when rotate gesture is recognized @objc private func rotatePiece(_ gestureRecognizer : UIRotationGestureRecognizer) { guard let piece = gestureRecognizer.view?.subviews.first else { return } if gestureRecognizer.state == .began || gestureRecognizer.state == .changed { piece.transform = piece.transform.rotated(by: gestureRecognizer.rotation) gestureRecognizer.rotation = 0 } } func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { return true } func clamp(value: CGFloat, min: CGFloat, max: CGFloat) -> CGFloat { if value < min { return min } else if value > max { return max } else { return value } } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } } Get UIView from SwiftUI View: // Get UIView from SwiftUI View extension View { var uiView: UIView { UIHostingController(rootView: self).view } } ContentView: struct ContentView: View { var body: some View { CanvasView() .frame(width: 880, height: 608) .transformable() .background(Color.blue) } }
1
0
96
13h
SwiftCharts Not Showing Accurate Data Until Tap Gesture on Chart
I am showing weather data in a TabView where each tab will show the forecast for that day and then an hour-by-hour Swift Charts of the temperature, chance of precipitation, and then dew point for that day. The day and a text description of that forecast correctly displays for each tab. However, the chart will only show the correct data if you perform a tap gesture on the chart. To reproduce this issue, I do the following: Tap on a day in the "Upcoming Week", preferably a day in the middle. Swipe a couple days to the left or right and use the tap gesture on one of the charts. Oddly, other data on the tab is accurate, it is really just within the SwiftChart. I did try doing a horizontal ScrollView instead but I had the same issue. I also followed the demo for SwiftCharts from WWDC. Below is code that shows the TabView: struct UpcomingDaysView: View { let forecastModel:WeatherModel @State var targetPeriod:WeatherForecastDayPeriod var body: some View { TabView(selection:$targetPeriod) { ForEach(forecastModel.dailyPeriods, id: \.self) {period in DailyViewChartDetail(forecastModel: forecastModel, periodToShow: period) .frame(alignment: .topLeading) .tag(period) } } .containerRelativeFrame([.vertical]) .tabViewStyle(.page) .indexViewStyle(.page(backgroundDisplayMode: .always)) .padding(EdgeInsets(top: 20, leading: 0, bottom: 0, trailing: 0)) } } } And here is the DailyViewChartDetail: struct DailyViewChartDetail: View { var forecastModel:WeatherModel var periodToShow:WeatherForecastDayPeriod var body: some View { VStack { Text("\(DateUtility.getLongerDay(date: DateUtility.getDate(stringDate: periodToShow.dayForecast.startTime)))") .font(.title2) Text("\(periodToShow.dayForecast.detailedForecast)") .font(.subheadline) .padding(5) HourlyViewChart(forecastModel: WeatherPeriodUtility.filterModel(forecastModel: forecastModel, targetPeriod: periodToShow)) .padding(5) Spacer() } .frame( alignment: .topLeading ) } } And then some of the more relevant code in the HourlyViewChart struct HourlyViewChart: View { var forecastModel:WeatherModel @State var range: (Date, Date)? = nil @State var rawSelectedDateTemp: Date? = nil @State var rawSelectedDatePrecipitation: Date? = nil @State var rawSelectedDewPoint: Date? = nil // ... more code Below is an image that shows the issue:
0
0
59
15h
PhotoAsset in TagView
I'm trying to recreate the Tag people functionality in Instagram. Where a carousel of media the user has selected is displayed to them. They can then go through and tag people to the media. I'm trying to achieve this (but with food items instead of people) with TagView using PHAssets however the result is some funky behaviour I'm pulling my hair out trying to understand. The items are tagging correctly but the scroll feature on the TabView works sporadically. It occasionally scrolls fine but all of a sudden won't let me scroll past one image.. (See attached video for example). import SwiftUI import Photos struct TagItemView: View { @Binding var selectedAssets: [PHAsset] @State private var showTagSheet = false @State private var currentAsset: PHAsset? { didSet { if let currentAsset = currentAsset { assetTags = tags[currentAsset.localIdentifier] ?? [] } } } @State private var tags: [String: [String]] = [:] // Dictionary to store tags for each media item @State private var assetTags: [String] = [] // Tags for the current asset var body: some View { VStack { mediaCarousel tagsView Spacer() } .background(Color.black.ignoresSafeArea()) .onAppear { if let firstAsset = selectedAssets.first { currentAsset = firstAsset } } .onChange(of: currentAsset) { newAsset in if let currentAsset = newAsset { assetTags = tags[currentAsset.localIdentifier] ?? [] print("currentAsset changed: \(currentAsset.localIdentifier)") print("assetTags: \(assetTags)") } } .sheet(isPresented: $showTagSheet) { TagSheetView(selectedAsset: $currentAsset, tags: $tags, showTagSheet: $showTagSheet, assetTags: $assetTags) } } private var mediaCarousel: some View { VStack { TabView(selection: $currentAsset) { ForEach(selectedAssets, id: \.self) { asset in if asset.mediaType == .image { TagItemImageView(asset: asset) .tag(asset.localIdentifier) .onAppear { currentAsset = asset print("Asset in view (onAppear): \(asset.localIdentifier)") } .onTapGesture { currentAsset = asset showTagSheet = true } } else if asset.mediaType == .video { TagItemVideoView(asset: asset) .tag(asset.localIdentifier) .onAppear { currentAsset = asset print("Asset in view (onAppear): \(asset.localIdentifier)") } .onTapGesture { currentAsset = asset showTagSheet = true } } } } .tabViewStyle(PageTabViewStyle(indexDisplayMode: .always)) .frame(height: UIScreen.main.bounds.height * 0.4) // Fixed height for carousel } } private var tagsView: some View { ScrollView { if !assetTags.isEmpty { ItemView(assetTags: assetTags, removeTag: { tag in removeTag(tag, from: currentAsset!) }) .transition(.opacity) } else { InstructionsView() .transition(.opacity) } } .background(Color.black) .padding(.top, 8) .padding(.horizontal, 15) } private func removeTag(_ tag: String, from asset: PHAsset) { guard var assetTags = tags[asset.localIdentifier] else { return } assetTags.removeAll { $0 == tag } tags[asset.localIdentifier] = assetTags if currentAsset?.localIdentifier == asset.localIdentifier { self.assetTags = assetTags } } }
0
0
47
16h
visionOS 2 full immersive space permission change?
Does visionOS 2 still prompt the user with a permission alert when a full immersive space is presented? In visionOS 1, the first time an app presented an immersive space, the user was prompted with an alert to grant permission. openImmersiveSpace would return an error code if the user opted not to grant permission. In visionOS 1, it was important to handle this case correctly. In visionOS 1, the Settings > Developer menu had an option to reset the immersive user's space permission prompting state so developers could test this interaction flow. In visionOS 2, I no longer see the full immersive space permissions alert. I can't remember if I saw it once, the first time visionOS 2.0 beta was installed, or if I never saw it at all. The Settings > Developer menu no longer has an option to reset the permission prompting state. I can't find any way to test the interaction flow in my app to make sure that it will work correctly for users. Does visionOS 2 no longer ask for full immersive space permission at all? I can't find this change documented anywhere. If visionOS 2 does prompt the user for permission, is there any way to reproduce and test this interaction flow so I can make sure my app handles it correctly? Thanks for taking the time to answer this question.
2
0
105
9h
SwiftUI DatePicker color contrast
Hi! Is there a way to increase the color contrast of the calendar version of the SwiftUI DatePicker? Even with high contrast turned on in the general IOS settings, the contrast between the "Sun", "Mon", "Tue" etc and a plain white background is only 3.86:1, which is less than the WCAG AA recommendations of 4:5:1. The contrast with the text for non-selectable dates is even lower. I tried a couple of different options - setting tint, foregroundColor and so on, but they don't change the text color. Thanks in advance!
0
0
88
17h
Question about using multiple NavigationLinks in same project
Hello, I want to write an app for following requirements: Four views(A,B,C and D) has navigationlink as a button to move to view E. so I wrote a navigationlink on view A as follows: NavigationLink(destination: DestinationView(result: iOSVM.add(a: (Int(numberA) ?? 0), b: (Int(numberB) ?? 0)))) { Text("Add?") } and another navigationlink on view B like this: NavigationLink(destination: DestinationView(result:iOSVM.subtract(a:number1,b:number2))){ Text("Result?") } after running these codes, navigationlink on view A works properly. but another one on view B remains diabled. help me to fix this. thx, c00012
1
0
77
18h
Is ObservableObject implicitly a MainActor in iOS 16 and later?
This is a question regarding the specification of ObservalObject. The following code does not cause a compilation error when the deployment target is set to iOS 16, but it does cause the following error when set to iOS 15: class Model: ObservableObject { let player: AVPlayer @Published var isPlaying = false var playerObserver: NSKeyValueObservation? init() { self.player = AVPlayer() self.playerObserver = self.player.observe(\.rate, options: [.new, .old]) { player, change in NSLog("changed rate: \(String(describing: change.newValue))") } } func setup() { let name = "sample" let url = Bundle.main.url(forResource: name, withExtension: "m4a")! let playerItem = AVPlayerItem(url: url) self.player.replaceCurrentItem(with: playerItem) } func play() { self.player.play() self.isPlaying = true } } The following error occurs in iOS 15: Cannot form key path to main actor-isolated property 'rate' Call to main actor-isolated instance method 'play()' in a synchronous nonisolated context Additionally, if the code is modified as follows, the error does not occur even in iOS 15. Specifically, adding @MainActor to the Model resolves the issue. @MainActor class Model: ObservableObject { ... } From this behavior, I guessed that ObservableObject is implicitly a MainActor in iOS 16 and later. Is this understanding correct?
1
0
90
1d
Unable to Display Text Fully in Text() SwiftUI
Hi! I am working on an app that requires displaying special characters and I have currently implemented it to just use Text() in swiftUI. Unfortunately, it can't display the full height of the text. Attached is one example of this happening. I have attempted to do .linespacing() but that method doesn't work. .frame also doesn't seem to make a change. Does anyone have a solution to this? Thanks!
6
0
99
1d
Most efficient way to call a function upon variable state change
Hi, I have a button view that is used in many different ways in an app that I'm working on. One of the ways it is used is in an account creation form. Since the button is in a child view, the action: { } button function isn't available in the view where the input field variables are. I could import the class with the function to the button view but I don't want to pass the input field variables into the button view. I tried binding a boolean variable to the button view and checked for it's state change in the parent view using .onChange(), but the use case for that I found was depreciated and I'm unable to revert the state of the variable in the .onChange function. To reiterate, in a main view, I need to call a function in a given class and pass variables to it, upon a button being pressed in a child view. Any help would be greatly appreciated.
1
0
132
1d
WidgetKit Not running in iOS 14/15 (FBSOpenApplicationServiceErrorDomain)
I was adding WidgetExtension target for my old project. The widget target is running fine in iOS 17, In my case, widget need to support iOS 14 and above, so I updated my widget code to old style, To removing WidgetConfigurationIntent and AppIntentTimelineProvider. import WidgetKit import SwiftUI struct Provider: TimelineProvider { func placeholder(in context: Context) -> SimpleEntry { SimpleEntry() } func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> Void) { completion(SimpleEntry()) } func getTimeline(in context: Context, completion: @escaping (Timeline<SimpleEntry>) -> Void) { completion(Timeline(entries: [SimpleEntry()], policy: .never)) } typealias Entry = SimpleEntry } struct SimpleEntry: TimelineEntry { let date: Date = Date() } struct NCWidgetEntryView : View { var entry: Provider.Entry var body: some View { VStack { Text("Time:") Text(entry.date, style: .time) } } } struct NCWidget: Widget { let kind: String = "NCWidget" var body: some WidgetConfiguration { StaticConfiguration(kind: kind, provider: Provider()) { entry in NCWidgetEntryView(entry: entry) } .configurationDisplayName("DisplayName") .description("description") } } In my case, the code was working fine in iOS 17 simulator, But if I try to run in iOS 15, it returns the below error code-SendProcessControlEvent:toPid: encountered an error: Error Domain=com.apple.dt.deviceprocesscontrolservice Code=8 "Failed to show Widget 'com.name-pprd.NCWidgetExtension' error: Error Domain=FBSOpenApplicationServiceErrorDomain Code=5 "The request to open "com.apple.springboard" failed." UserInfo={NSLocalizedDescription=The request to open "com.apple.springboard" failed., NSLocalizedFailureReason=Unexpected error type., NSUnderlyingError=0x600003570b40 {Error Domain=BSServiceConnectionErrorDomain Code=3 "XPC error received on message reply handler" UserInfo={BSErrorCodeDescription=OperationFailed, NSLocalizedFailureReason=XPC error received on message reply handler}}, BSErrorCodeDescription=InvalidResponse}." UserInfo={NSLocalizedDescription=Failed to show Widget 'com.name-pprd.NCWidgetExtension' error: Error Domain=FBSOpenApplicationServiceErrorDomain Code=5 "The request to open "com.apple.springboard" failed." UserInfo={NSLocalizedDescription=The request to open "com.apple.springboard" failed., NSLocalizedFailureReason=Unexpected error type., NSUnderlyingError=0x600003570b40 {Error Domain=BSServiceConnectionErrorDomain Code=3 "XPC error received on message reply handler" UserInfo={BSErrorCodeDescription=OperationFailed, NSLocalizedFailureReason=XPC error received on message reply handler}}, BSErrorCodeDescription=InvalidResponse}., NSUnderlyingError=0x600003570bd0 {Error Domain=FBSOpenApplicationServiceErrorDomain Code=5 "The request to open "com.apple.springboard" failed." UserInfo={NSLocalizedDescription=The request to open "com.apple.springboard" failed., NSLocalizedFailureReason=Unexpected error type., NSUnderlyingError=0x600003570b40 {Error Domain=BSServiceConnectionErrorDomain Code=3 "XPC error received on message reply handler" UserInfo={BSErrorCodeDescription=OperationFailed, NSLocalizedFailureReason=XPC error received on message reply handler}}, BSErrorCodeDescription=InvalidResponse}}} Domain: DTXMessage Code: 1 User Info: { DVTErrorCreationDateKey = "2024-07-20 17:30:58 +0000"; } -- System Information macOS Version 14.5 (Build 23F79) Xcode 15.0.1 (22266) (Build 15A507) Timestamp: 2024-07-20T23:00:58+05:30 In widget target Minimum target is 14.0 In App target Minimum target is 13.0
1
0
136
2d
Keyboard pushes Custom TabBar Up
Hello, so I created a custom TabBar using the .overlay modifier on TabView. However, when clicking/pressing on a TextField, the keyboard causes the TabBar to be pushed up in the view. From Reddit, I found that this is caused by using the .overlay modifier. How should I go about fixing this issue or what is the standard way of implementing custom tab bars? Thanks in advance! -- Kohl J Screenshot TabView Code struct RootView: View { @State var selectedTab : Tabs = .home; var body: some View { TabView(selection: $selectedTab) { HomeView(selectedTab: $selectedTab) .tag(Tabs.home) TaskListView(selectedTab: $selectedTab) .tag(Tabs.taskList) CreateTaskView(selectedTab: $selectedTab) .tag(Tabs.create) TrophiesView(selectedTab: $selectedTab) .tag(Tabs.trophies) SettingsView(selectedTab: $selectedTab) .tag(Tabs.settings) } .overlay(alignment: .bottom) { TabBar(selectedTab: $selectedTab) .padding(.horizontal) } } } Custom TabBar Code struct TabBar: View { @Binding var selectedTab : Tabs var body : some View { HStack (alignment: .center) { Button(action: { // switch to home view selectedTab = Tabs.home }, label: { TabBarButton(buttonText: "Home", imageName: "house.fill", size: 24, isActive: selectedTab == .home, hasTopBar: true) }) Button(action: { // switch to task list view selectedTab = Tabs.taskList }, label: { TabBarButton(buttonText: "Task List", imageName: "list.bullet.clipboard.fill", size: 24, isActive: selectedTab == .taskList, hasTopBar: true) }) Button(action: { // switch to create view selectedTab = Tabs.create }, label: { TabBarButton(buttonText: "Create", imageName: "plus.circle.fill", size: 32, isActive: selectedTab == .create, hasTopBar: false) }) Button(action: { // switch to trophies view selectedTab = Tabs.trophies }, label: { TabBarButton(buttonText: "Trophies", imageName: "trophy.fill", size: 24, isActive: selectedTab == .trophies, hasTopBar: true) }) Button(action: { // switch to settings view selectedTab = Tabs.settings }, label: { TabBarButton(buttonText: "Settings", imageName: "gearshape.fill", size: 24, isActive: selectedTab == .settings, hasTopBar: true) }) } .frame(height: 60) } }
1
0
109
2d
SwiftUI Gestures prevent scrolling with iOS 18
I added gesture support to my app that supports iOS 16 and 17 and have never had issues with it. However, when I compiled my app with Xcode 16 I immediately noticed a problem with the app when I ran it in the simulator. I couldn't scroll up or down. I figured out it’s because of my gesture support. My gesture support is pretty simple. let myDragGesture = DragGesture() .onChanged { gesture in self.offset = gesture.translation } .onEnded { _ in if self.offset.width > threshold { ...some logic } else if self.offset.width < -threshold { ...some other logic } logitUI.debug("drag gesture width was \(self.offset.width)") self.offset = .zero } If I pass nil to .gesture instead of myDragGesture then scrolling starts working again. Here’s some example output when I’m trying to scroll down. These messages do NOT appear when I run my app on an iOS 16/17 simulator with Xcode 15. drag gesture width was 5.333328 drag gesture width was -15.333344 drag gesture width was -3.000000 drag gesture width was -24.333328 drag gesture width was -30.666656 I opened FB14205678 about this.
1
0
106
17h
How to use the new Text timer formats?
I'm trying to get a countdown timer to work, and the way I currently do it in my watchOS 10 app is a complicated load of nonsense to get two Strings that look like "1w 1d" and "12:34:56", i.e. a String that shows components like year, week and day, and another String showing hours, minutes and seconds. The new Text formats seen here https://developer.apple.com/wwdc24/10144?time=645 look useful, but I can't get them to return the values I need. If I use this: let dateA = Date.now let dateB = Date.advanced(by: /* value for 8 days, 12 hours, 34 minutes and 56 seconds */) Text(dateA, format: .offset(to: dateB, allowedFields: [.year, .week, .day], maxFieldCount: 3)) I expect to see "1 week 1 day", but it always comes back as "8 days". I guess it's giving me the most concise result, but I don't want that. I'm not sure anyone would want that. Imagine you have an event coming up in 3 days 6 hours, do you want to see "in 78 hours" or do you want "in 3 days and 6 hours"? Why must we make the user calculate the days and hours in their head when we have the ability to give them the right information? While I'm on this, why does the resulting String have to have "in " at the beginning? I don't want that; it's not my use case, but it's forced on me. I've raised this a hundred times with Apple. I just want to see a String that shows the difference between two dates in a format of my choosing, i.e. "1w 1d", but they never give me what I need, so I have to write extremely complex - and fragile - code that figures this stuff out, and I still can't get that to work properly. Why can't we just have something like: Text(from: dateA, to: dateB, format: "%yy %ww %dd") // for "1 year 2 weeks 3 days", show parts with a value > 0 Text(from: dateA, to: dateB, format: "%0yy %0ww %0dd") // for "0 years 2 weeks 3 days", show all parts regardless of value Text(from: dateA, to: dateB, format: "%y %w %d") // for "1y 2w 3d", show parts with a value > 0 Text(from: dateA, to: dateB, format: "%0y %0w %0d") // for "0y 2w 3d", show all parts regardless of value
1
0
70
14h
iOS 18 beta bug: NavigationStack pushes the same view twice
Hello, community and Apple engineers. I need your help. Our app has the following issue: NavigationStack pushes a view twice if the NavigationStack is inside TabView and NavigationStack uses a navigation path of custom Hashable elements. Our app works with issues in Xcode 18 Beta 13 + iOS 18.0. The same issue happened on previous beta versions of Xcode 18. The issue isn’t represented in iOS 17.x and everything worked well before iOS 18.0 beta releases. I was able to represent the same issue in a clear project with two simple views. I will paste the code below. Several notes: We use a centralised routing system in our app where all possible routes for navigation path are implemented in a View extension called withAppRouter(). We have a enum RouterDestination that contains all possible routes and is resolved in withAppRouter() extension. We use Router class that contains @Published var path: [RouterDestination] = [] and this @Published property is bound to NavigationStack. In the real app, we need to have an access to this path property for programmatic navigation purposes. Our app uses @ObservableObject / @StateObject approach. import SwiftUI struct ContentView: View { @StateObject private var router = Router() var body: some View { TabView { NavigationStack(path: $router.path) { NavigationLink(value: RouterDestination.next, label: { Label("Next", systemImage: "plus.circle.fill") }) .withAppRouter() } } } } enum RouterDestination: Hashable { case next } struct SecondView: View { var body: some View { Text("Screen 2") } } class Router: ObservableObject { @Published var path: [RouterDestination] = [] } extension View { func withAppRouter() -> some View { navigationDestination(for: RouterDestination.self) { destination in switch destination { case .next: return SecondView() } } } } Below you can see the GIF with the issue: What I tried to do: Use iOS 17+ @Observable approach. It didn’t help. Using @State var path: [RouterDestination] = [] directly inside View seems to help. But it is not what we want as we need this property to be @Published and located inside Router class where we can get an access to it, and use for programmatic navigation if needed. I ask Apple engineers to help with that, please, and if it is a bug of iOS 18 beta, then please fix it in the next versions of iOS 18.0
2
2
125
14h
onContinueUserActivity not working on first app launch
HI, I'm trying to deeplink from my widget to a view in my app. I'm using the "SwiftUI app lifecycle". This the code I'm currently using: var body: some Scene { WindowGroup { RootView() .onContinueUserActivity("NextDeparturesWidgetConfigurationIntent") { userActivity in guard let configuration: NextDeparturesWidgetConfigurationIntent = userActivity .widgetConfigurationIntent(), let stationEntity = configuration.stationEntity else { return } NotificationCenter.default.post(name: .onOpenStation, object: stationEntity.id) } } } It is working fine when the app is already running (in the background). However when the app is "cold starting" (ie. not in memory) onContinueUserActivity is never called. I tried adding a UIApplicationDelegateAdaptor: func application( _ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions ) -> UISceneConfiguration { if let userActivity = options.userActivities.first { let configuration: NextDeparturesWidgetConfigurationIntent? = userActivity.widgetConfigurationIntent() // casting fails } return UISceneConfiguration( name: nil, sessionRole: connectingSceneSession.role ) } I can see that the activity is received but it is never casted to NextDeparturesWidgetConfigurationIntent. What am I missing ?
0
0
68
3d
SwiftUI URLRequest Warning: "Connection has no local endpoint"
I have a simple SwiftUI application that sends a URLRequest as shown in the code snippet below: import SwiftUI @main struct GOGODemoApp: App { var body: some Scene { WindowGroup { MyView() } } } struct MyView: View { var body: some View { Button("Click") { sendHTTPRequest(to: "https://www.google.com") { code, err in print("Finished, code: \(code ?? -1), err: \(String(describing: err))") } } } } func sendHTTPRequest(to urlString: String, completion: @escaping (Int?, Error?) -&gt; Void) { guard let url = URL(string: urlString) else { completion(nil, NSError(domain: "InvalidURL", code: 0, userInfo: nil)) return } let task = URLSession.shared.dataTask(with: url) { _, resp, error in if let httpResponse = resp as? HTTPURLResponse { completion(httpResponse.statusCode, error) } else { completion(-1, error) } } task.resume() } However, Xcode prints the following warning messages: nw_connection_copy_connected_local_endpoint_block_invoke [C1] Connection has no local endpoint nw_connection_copy_connected_local_endpoint_block_invoke [C1] Connection has no local endpoint nw_connection_copy_connected_local_endpoint_block_invoke [C3] Connection has no local endpoint nw_connection_copy_connected_local_endpoint_block_invoke [C3] Connection has no local endpoint Finished, code: 200, err: nil What does the warning 'Connection has no local endpoint' mean? Thank you for your assistance!
1
0
85
33m
How to get Command Line Tool code to launch SwiftUI App code
For MacOS I wrote a Terminal Command Line Tool to help me do number crunching calculations. No need for UI. This works great as-is, but there are opportunities to make the work more interesting by giving it some graphical representation like a heat map of the data. To that end I want the terminal to launch a SwiftUI code to open a window given an optional command line parameter that would display this visual representation of data in a new window. It would be nice to interact with that window visualization in some ways using SwiftUI. I originally thought it'd just be as easy as creating a SwiftUI View file and then throwing what normally appears under @main into a launch function and then calling the launch function from my main.swift file: import SwiftUI struct SwiftUIView: View { var body: some View { Text("Hello, World!") } } #Preview { SwiftUIView() } func LaunchSwiftUIApp() { //@main struct SwiftUIApp: App { var body: some Scene { WindowGroup { SwiftUIView() } } } } Of course this doesn't work. I've already have the command line code just spit out various png files via command line so looking to make those visualization a little more interactive or readable/organized by coding some SwiftUI stuff around those current visualizations. Anyway. Looking around this doesn't seem to be a thing people normally do. I'm not sure how to setup the Terminal Command Line Tool code that I wrote to optionally launch into SwiftUI code.
1
0
66
23h