Hello all, I am playing with MapKit for SwiftUI, so far so good. There is one thing I have not seen any documentations, or sample codes around and that's elevation data, e.g.
My questions are:
Is there a way to get this information from an MKRoute?
Is it possible to get the elevation gain/drop at a given point in the route?
Many thank in advance for your help.
Explore the various UI frameworks available for building app interfaces. Discuss the use cases for different frameworks, share best practices, and get help with specific framework-related questions.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Created
According to docs, .focusedObject() usage should be moved to .focusedValue() when migrating to @Observable, but there is no .focusedSceneValue() overload that accepts Observable like with .focusedValue(). So how are we supposed migrate .focusedSceneObject() to @Observable?
My App development language is only Arabic. I am using textField to Login User, whenever user long pressed, ToolTip showed up. Problem is with tool tip text it is flipped. My device language is English
After updating to Mac OS Sonoma, we have encountered compatibility issues with our iPad-designed application, specifically with the AirPrint functionality, when it is run on MacOS. The AirPrint feature stopped working properly through UIPrintInteractionController.shared.
We have noticed that when we compile the application using Catalyst, the AirPrint functionality is restored and works as expected. However, this solution is not viable for us due to the restrictions associated with the frameworks we are utilizing.
We are seeking alternative solutions, and any help or guidance would be highly appreciated to resolve this issue and ensure a seamless and uninterrupted user experience in our application.
STEPS TO REPRODUCE
Create an app for ipad with just a button and this code
var str = "TEST"
let printInfo = UIPrintInfo(dictionary:nil)
printInfo.outputType = .general
printInfo.jobName = "Report"
printInfo.orientation = .portrait
let printController = UIPrintInteractionController.shared
printController.printInfo = printInfo
printController.showsNumberOfCopies = false
printController.showsPageRange = false
printController.showsNumberOfCopies = false
let formatter = UIMarkupTextPrintFormatter(markupText: str)
formatter.contentInsets = UIEdgeInsets(top: 72, left: 72, bottom: 72, right: 72)
printController.printFormatter = formatter
printController.present(animated: true, completionHandler: nil)
2.Run it on a MacOS with Sonoma, there is no error on console or anything but it don't work.
-If you run it with Catalyst it just works when adding the Printing permission of App Sandbox in Signing & Capabilities.
Given that SwiftUI and modern programming idioms promote asynchronous activity, and observing a data model and reacting to changes, I wonder why it's so cumbersome in Swift at this point.
Like many, I have run up against the problem where you perform an asynchronous task (like fetching data from the network) and store the result in a published variable in an observed object. This would appear to be an extremely common scenario at this point, and indeed it's exactly the one posed in question after question you find online about this resulting error:
Publishing changes from background threads is not allowed
Then why is it done? Why aren't the changes simply published on the main thread automatically?
Because it isn't, people suggest a bunch of workarounds, like making the enclosing object a MainActor. This just creates a cascade of errors in my application; but also (and I may not be interpreting the documentation correctly) I don't want the owning object to do everything on the main thread.
So the go-to workaround appears to be wrapping every potentially problematic setting of a variable in a call to DispatchQueue.main. Talk about tedious and error-prone. Not to mention unmaintainable, since I or some future maintainer may be calling a function a level or two or three above where a published variable is actually set. And what if you decide to publish a variable that wasn't before, and now you have to run around checking every potential change to it?
Is this not a mess?
I've encountered a weird issue with the new Map for iOS 17. In my list, which includes a MapView among other elements, I've observed that with the new initializer, the top and bottom bars are persistently displayed. They don't hide and only appear when scrolling, as they should. This problem doesn't occur with the old, now-deprecated initializer. To illustrate this, I have two screenshots: one with the map enabled and the other with the map disabled, demonstrating the issue.
Here is also my new Map code:
struct MapListRowView: View {
@Binding internal var location: LocationModel
@State internal var user: Bool = true
private var position: CLLocationCoordinate2D { .init(latitude: location.latitude, longitude: location.longitude) }
private var isPad: Bool { UIDevice.current.userInterfaceIdiom == .pad ? true : false }
var body: some View {
Map(bounds: .init(minimumDistance: 1250)) {
if user { UserAnnotation() }
Annotation("", coordinate: position) {
ZStack {
Circle().fill().foregroundColor(.white).padding(1)
Image(systemName: "mappin.circle.fill")
.resizable()
.foregroundColor(.indigo)
}.frame(width: 20, height: 20).opacity(user ? .zero : 1.0)
}
}
.frame(height: isPad ? 200 : 100)
.cornerRadius(8)
.listRowInsets(.init(top: -5, leading: .zero, bottom: -5, trailing: .zero))
.padding(.vertical, 5)
.disabled(true)
}
}
I have something that looks like:
NavigationStack {
List(self.items, id: \.self, selection: self.$selectedItems) { item in
NavigationLink {
ItemView(item: item)
.environment(\.managedObjectContext, self.viewContext)
} label: {
LabelWithMenuView(object: item) { ptr in
self.labelHandler(item: item, newName: ptr)
}
}
}
if self.editMode?.wrappedValue == .active {
editButtons
} else {
TextField("Add Item", text: self.$newItem)
.onSubmit {
self.addItem()
self.newItem = ""
}
.padding()
}
}
#if os(iOS)
.toolbar {
EditButton()
}
.onChange(of: self.editMode?.wrappedValue) { old, new in
print("editMode \(old) -> \(new)")
}
#endif
With that layout, the edit button doesn't show up at all; if I put it as part of the List, it does show up, but the first click doesn't do anything; after that, it works, but the onChange handler doesn't show it getting changed, and the editButtons don't go away.
Hello! I've been digging into this for a little bit now, and am hitting something of a wall. Our app is crashing occasionally, and googling the crash yields literally 0 results.
Tl;dr: Something related to adaptivePresentationStyle(for:traitCollection:) is resulting in our app crashing.
Context
In our app, we have a custom UIPresentationController that we use to present a small sheet of content overlaying other app content - similar to a UISheetPresentationController with a medium-ish size. So we have a custom UIViewController to present, and it conforms to the UIAdaptivePresentationControllerDelegate protocol. We also have custom present and dismiss animators.
The crash
However, we seem to be running into a really odd crash. I've attached a crash report as well, but here's what one sees in xcode on reproducing the crash:
The _computeToEndFrameForCurrentTransition block is nil inside the _transitionViewForCurrentTransition block, value of outerStrongSelf currently : <XxxYyyyyyZzz.PopupPresentationController: 0x12d017a40>. This most likely indicates that an adaptation is happening after a transtion cleared out _computeToEndFrameForCurrentTransition. Captured debug information outside block: presentationController : <XxxYyyyyyZzz.PopupPresentationController: 0x12d017a40> presentedViewController : <XxxYyyyyyZzz.SomeViewController: 0x12d03a690> presentingViewController : <UINavigationController: 0x12a817400>
2023-09-25_08-02-33.6523_-0500-7d355cd4a86427213389765ef070a777c4b4aaa3.crash
Whenever we present one of these view controllers, things work just fine. When we try to present another one though, if someone is aggressively changing the phone orientation, the app crashes. This crash occurs somewhere in between dismissing the old VC and presenting the new one. It occurs before I ever hit any breakpoints in the "present" animator for the second view controller.
I've narrowed things down a bit, and by commenting out our implementation of adaptivePresentationStyle(for:traitCollection:), the crash can't be reproduced anymore. The downside there being that the app no longer functions how we want it to. Our definition of that function (which causes crashes) looks like this:
public func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
guard forceUsingFullScreenIfCompact else {
return .none
}
return traitCollection.verticalSizeClass == .compact ? .overFullScreen : .none
}
A bit more testing, and it seems like if that function returns the same thing consistently, nothing crashes. Are we not allowed to put conditional logic in this function?
In the crash, we can see that it occurs due to a failing assertion internal to UIPresentationController:
Last Exception Backtrace:
0 CoreFoundation 0x1afa28cb4 __exceptionPreprocess + 164 (NSException.m:202)
1 libobjc.A.dylib 0x1a8abc3d0 objc_exception_throw + 60 (objc-exception.mm:356)
2 Foundation 0x1aa1b2688 -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:] + 172 (NSException.m:251)
3 UIKitCore 0x1b1d05610 __80-[UIPresentationController _initViewHierarchyForPresentationSuperview:inWindow:]_block_invoke + 2588 (UIPresentationController.m:1594)
4 UIKitCore 0x1b21f1ff4 __56-[UIPresentationController runTransitionForCurrentState]_block_invoke_3 + 300 (UIPresentationController.m:1228)
The question
This all leads us to wonder if we're doing something wrong, or if there could be a bug in one of the iOS APIs that we're consuming. Thus, posting here. Does anyone have any insight into how this could be occurring, or has seen this before and has ideas? Thanks!
Miscellaneous info
We target iOS 14+
We've seen this issue in debug and release builds from Xcode 14 and 15
We see the issue on users with iOS 15+, though it could be occurring on 14 in just incredibly low numbers
This is a re-post of https://developer.apple.com/forums/thread/738257, because I accidentally closed that out as resolved
Hello,
I have a SwiftUI application that uses NavigationSplitView. It's working great on iOS, iPad, and macOS. I decided to give it a try on tvOS. After it builds, it will not allow user interaction on the NavigationSplitView's sidebar. I've tried various view focus modifiers without any success. I'd also expect this to "just work" as default behavior. I have filed FB13447961 on this issue. Here is a distillation of the code that demonstrates the problem. Any ideas? Thank you.
enum Category : String, CaseIterable {
case first
case second
case third
}
enum Detail : String, CaseIterable {
case one
case two
case three
}
struct DetailView : View {
let category : Category?
var body: some View {
if let category {
Text(category.rawValue)
List(Detail.allCases, id: \.self) { detail in
NavigationLink(value: detail) {
Text(detail.rawValue)
}
}
} else {
Text("Select Category")
}
}
}
struct ContentView: View {
// NOTE: If this category is set to something, it will show that category's detail.
// The problem is that the NavigationSplitView sidebar does not have, nor does not
// seem to be able to get focus.
@State var category: Category?
@State var path : [Detail] = []
var body: some View {
NavigationSplitView {
List(Category.allCases, id: \.self, selection: $category) { category in
Text(category.rawValue)
}
} detail: {
NavigationStack(path: $path) {
DetailView(category: category)
.navigationDestination(for: Detail.self) { detail in
Text("\(detail.rawValue)")
}
}
}
}
}
#wwdc2023-10162 #wwdc20-10042
I have a scroll view that scrolls horizontally and one of my users is asking that it respond to their scroll wheel without them having to use the shift key. Is there some way to do this natively? If not, how can I listen for the scroll wheel events in swiftUI and make my scroll wheel scroll to respond to them?
Trying to use new Swift @Observable to monitor GPS position within SwiftUI content view. But how do I tie the latest locations to the SwiftUI Map's mapCameraPosition?
Well ideally the answer could cover:
How to fix this error - So get map tracking along with the User Position, but also
How to include facility to turn on/off the map moving to track the user position (which I'll need to do next). So could be tracking, then disable, move map around and have a look at things, then click button to start syncing the mapcameraposition to the GPS location again
Refer to error I'm embedded in the code below.
import SwiftUI
import MapKit
@Observable
final class NewLocationManager : NSObject, CLLocationManagerDelegate {
var location: CLLocation? = nil
private let locationManager = CLLocationManager()
func startCurrentLocationUpdates() async throws {
if locationManager.authorizationStatus == .notDetermined {
locationManager.requestWhenInUseAuthorization()
}
for try await locationUpdate in CLLocationUpdate.liveUpdates() {
guard let location = locationUpdate.location else { return }
self.location = location
}
}
}
struct ContentView: View {
var newlocationManager = NewLocationManager()
@State private var cameraPosition: MapCameraPosition = .region(MKCoordinateRegion(
center: newlocationManager.location?.coordinate ?? <#default value#>,
span: MKCoordinateSpan(latitudeDelta: 0.25, longitudeDelta: 0.25)
))
// GET ERROR: Cannot use instance member 'newlocationManager' within property initializer; property initializers run before 'self' is available
var body: some View {
ZStack {
Map(position: $cameraPosition)
Text("New location manager: \(newlocationManager.location?.description ?? "NIL" )") // works
}
.task {
try? await newlocationManager.startCurrentLocationUpdates()
}
}
}
#Preview {
ContentView()
}
I tried building the View from this section, but when there is a List on the second tab, the animation performed by the matchedGeometryEffect does not work as intended.
This video shows how the transition works with Text("Second Tab") as the second tab. Everything looks fine.
But when I replace the Text with a List, the transition flickers and does not look smooth anymore.
List {
Text("The Scarlet Letter")
Text("Moby-****")
Text("Little Women")
Text("Adventures of ")
}
Here is the code for the app.
import SwiftUI
@main
struct MyWatchApp: App {
@Namespace var library
@State var pageNumber = 0
private let bookIcon = "bookIcon"
var body: some Scene {
WindowGroup {
NavigationStack {
TabView(selection: $pageNumber) {
VStack {
Image(systemName: "books.vertical.fill")
.imageScale(.large)
.matchedGeometryEffect(
id: bookIcon,
in: library,
properties: .frame,
isSource: pageNumber == 0)
Text("Books")
}
.tag(0)
Text("Second Tab").tag(1)
}
.tabViewStyle(.verticalPage)
.toolbar {
ToolbarItem(placement: .topBarLeading) {
Image(systemName: "books.vertical.fill")
.matchedGeometryEffect(
id: bookIcon,
in: library,
properties: .frame,
isSource: pageNumber != 0)
}
}
}
}
}
}
I think I'm misunderstanding something here, maybe someone could point me in the right direction.
In System Settings, "Correct spelling automatically" is DISABLED, along with all the other options that ruin what you're typing.
In TextEdit, it continues to highlight spelling and grammar mistakes, so does Mail, Safari and others.
Yet SwiftUI made apps, don't.
I can right-click, enable "Check Spelling while typing", but after typing a few characters, words, it becomes disabled again.
I've busted through the view hierarchy to get the hosted NSTextView and overridden "isContinuousSpellCheckingEnabled" but something frequently reverts this to false.
Is my only option to have a large TextEditor with spell checking (but not auto correction) to create my own version of TextEditor by hosting the NSTextView myself. That's a lot of work for something which seems wrong, when I'm hoping that I'm simply missing something here.
Xcode 15.2 on macOS 13.5.
Hi - I use TipKit in my App and AppClip. TipKit is configured with the app group's datastore. The tips show in the App, but on the AppClip, with the same rules/state, the tips do not display. Is this expected? TipKit is not listed as one of the frameworks unavailable to AppClips.
try? Tips.configure([
Tips.ConfigurationOption.displayFrequency(.hourly),
Tips.ConfigurationOption.datastoreLocation(.groupContainer(identifier: BuildConfiguration.shared.userDefaultsSuite))
])
Hello SwiftUI devs, I would like to remove the "More" button that appears in the top left of the screen whenever the selected tab of a tab view is in 5th position and beyond. It ruins the layout.
struct ContentView: View {
private let tabs = (1...10).map { "\($0)" }
@State private var selectedTab: String = "5"
var body: some View {
TabView(selection: $selectedTab) {
ForEach(tabs, id: \.self) { tab in
Text("Tab \(tab)")
.tabItem {
Label("Tab \(tab)", systemImage: "star")
}
.toolbar(.hidden, for: .tabBar)
}
}
}
}
At first glance, one easy fix would be to rearrange the tabs list in the ForEach loop, putting the selected tab at the first position. This does the trick BUT we lose the states of the views, which is out of the question in my use-case.
Getting rid of the tab view and handling the logic with a simple Switch paired with a state restoration mechanism using SceneStorage or SwiftData is probably possible but sounds like a white elephant compared to finding a solution to remove that "More" button.
Thank you
The following WatchOs App example is very short, but already not functioning as it is expected, when using Digital Crown (full code):
import SwiftUI
struct ContentView: View {
let array = ["One","Two","Three","Four"]
@State var selection = "One"
var body: some View {
Picker("Array", selection: $selection) {
ForEach(array, id: \.self) {
Text($0)
}
}
}
}
The following 2 errors are thrown, when using Digital Crown for scrolling:
ScrollView contentOffset binding has been read; this will cause grossly inefficient view performance as the ScrollView's content will be updated whenever its contentOffset changes. Read the contentOffset binding in a view that is not parented between the creator of the binding and the ScrollView to avoid this.
Error: Error Domain=NSOSStatusErrorDomain Code=-536870187 "(null)"
Any help appreciated. Thanks a lot.
Hi! While working on my Swift Student Challenge submission it seems that I found a race condition (TOCTOU) bug in SwiftUI when using sheets, and I'm not sure if this is expected behaviour or not.
Here's an example code:
import SwiftUI
struct ContentView: View {
@State var myVar: Int?
@State private var presentSheet: Bool = false
var body: some View {
VStack {
// Uncommenting the following Text() view will "fix" the bug (kind of, see a better workaround below).
// Text("The value is \(myVar == nil ? "nil" : "not nil")")
Button {
myVar = nil
} label: {
Text("Set value to nil.")
}
Button {
myVar = 1
presentSheet.toggle()
} label: {
Text("Set value to 1 and open sheet.")
}
}
.sheet(isPresented: $presentSheet, content: {
if myVar == nil {
Text("The value is nil")
.onAppear {
print(myVar) // prints Optional(1)
}
} else {
Text("The value is not nil")
}
})
}
}
When opening the app and pressing the open sheet button, the sheet shows "The value is nil", even though the button sets myVar to 1 before the presentSheet Bool is toggled.
Thankfully, as a workaround to this bug, I found out you can change the sheet's view to this:
.sheet(isPresented: $presentSheet, content: {
if myVar == nil {
Text("The value is nil")
.onAppear {
if myVar != nil {
print("Resetting View (TOCTOU found)")
let mySwap = myVar
myVar = nil
myVar = mySwap
}
}
} else {
Text("The value is not nil")
}
})
This triggers a view refresh by setting the variable to nil and then to its non-nil value again if the TOCTOU is found.
Do you think this is expected behaivor? Should I report a bug for this? This bug also affects .fullScreenCover() and .popover().
In my visionOS app, I'm seeing this error in the console dozens of times. Anyone know what it means, or how to troubleshoot it?
Searching these forums and the usual other places hasn't come up with anything that seems relevant.
Hi everyone,
I'm currently facing an issue with AVAudioPlayer in my SwiftUI project. Despite ensuring that the sound file "buttonsound.mp3" is properly added to the project's resources (I dragged and dropped it into Xcode), the application is still unable to locate the file when attempting to play it.
Here's the simplified version of the code I'm using:
import SwiftUI
import AVFoundation
struct ContentView: View {
var body: some View {
VStack {
Button("Play sound") {
playSound(named: "buttonsound", ofType: "mp3")
}
}
}
}
func playSound(named name: String, ofType type: String) {
guard let soundURL = Bundle.main.url(forResource: name, withExtension: type) else {
print("Sound file not found")
return
}
do {
let audioPlayer = try AVAudioPlayer(contentsOf: soundURL)
audioPlayer.prepareToPlay()
audioPlayer.play()
} catch let error {
print("Error playing sound: \(error.localizedDescription)")
}
}
Hello, I can't seem to set any breakpoint in didSet for all properties inside Observable.
Is this a bug?
XcodeVersion 15.2
(15C500b)
Thanks!