After upgrading to iOS 17 I am struggling to get decimals working in my app - here is a sample code: for clarity I provide a complete "working" sample (I am pulling data from a back-end server using json, etc - all of that is working ok, it's the UI issue - see below):
Model
import Foundation
struct TestFloat: Encodable {
var testFloatNumber: Float = 0
}
Observable Class
import Foundation
class TestFloatViewModel: ObservableObject {
@Published var testFloat = TestFloat()
}
View
struct TestFloatView: View {
@ObservedObject var testFloatVM: TestFloatViewModel
let formatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
return formatter
}()
var body: some View {
VStack {
HStack {
Text("Enter Float Number")
Spacer()
}
Spacer()
.frame(height: 2.0)
HStack {
TextField("Enter Float Number", value: $testFloatVM.testFloat.testFloatNumber, formatter: formatter)
.keyboardType(.decimalPad)
.textFieldStyle(.roundedBorder)
}
}
}
}
This is working on a device with iOS16; however when run on device with iOS17:
you can enter maximum four digits?
using backspace you can delete all numbers apart of the first one
you cannot enter the decimal (.) at all even though decimal keyboard is provided
Any help is greatly appreciated.
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
Activity
I'm working on a NavigationStack based app. Somewhere I'm using:
@Environment(\.dismiss) private var dismiss
and when trying to navigate to that view it gets stuck.
I used Self._printChanges() and discovered the environment variable dismiss is changing repeatedly. Obviously I am not changing that variable explicitly. I wasn't able to reproduce this in a small project so far, but does anybody have any idea what kind of thing I could be doing that might be causing this issue?
iOS 17.0.3
I am using public struct ShareLink<Data, PreviewImage, PreviewIcon, Label> : View where Data : RandomAccessCollection, PreviewImage : Transferable, PreviewIcon : Transferable, Label : View, Data.Element : Transferable {}
And it is generating entitlement errors and not working reliably ( will transfer 1-3 items, but not 4+ ; will not work a second time)
Error is:
Error acquiring assertion: <Error Domain=RBSServiceErrorDomain Code=1 "(originator doesn't have entitlement com.apple.runningboard.primitiveattribute AND originator doesn't have entitlement com.apple.runningboard.assertions.frontboard AND target is not running or doesn't have entitlement com.apple.runningboard.trustedtarget AND Target not hosted by originator)" UserInfo={NSLocalizedFailureReason=(originator doesn't have entitlement com.apple.runningboard.primitiveattribute AND originator doesn't have entitlement com.apple.runningboard.assertions.frontboard AND target is not running or doesn't have entitlement com.apple.runningboard.trustedtarget AND Target not hosted by originator)}>
Received port for identifier response: <> with error:Error Domain=RBSServiceErrorDomain Code=1 "Client not entitled" UserInfo={RBSEntitlement=com.apple.runningboard.process-state, NSLocalizedFailureReason=Client not entitled, RBSPermanent=false}
elapsedCPUTimeForFrontBoard couldn't generate a task port
Received port for identifier response: <> with error:Error Domain=RBSServiceErrorDomain Code=1 "Client not entitled" UserInfo={RBSEntitlement=com.apple.runningboard.process-state, NSLocalizedFailureReason=Client not entitled, RBSPermanent=false}
elapsedCPUTimeForFrontBoard couldn't generate a task port
Received port for identifier response: <> with error:Error Domain=RBSServiceErrorDomain Code=1 "Client not entitled" UserInfo={RBSEntitlement=com.apple.runningboard.process-state, NSLocalizedFailureReason=Client not entitled, RBSPermanent=false}
Code is
import SwiftUI
var images = Array<Image?>(repeating: nil , count: 200);
struct ShareTestGContentView: View {
let columns = [GridItem(.fixed(165)), GridItem(.fixed(165))]
private let twoColumnGrid = [ GridItem(.flexible(minimum: 40), spacing: 2), GridItem(.flexible(minimum: 40), spacing: 2) ]
@State var selected = Set()
var body: some View {
topSection()
ScrollView {
LazyVGrid(columns: twoColumnGrid, spacing: 2) { // columns: [GridItem(.flexible())]) {
ForEach(1...100, id: \.self) { idx in
var cr = ( selected.contains(idx) ? 16.0 : 0 )
var lw = ( selected.contains(idx) ? 8.0 : 0 )
VStack{
Button(action: {
if selected.contains(idx) {
selected.remove(idx); cr = 0.0; lw = 0.0
} else {
selected.insert(idx); cr = 16.0; lw = 8.0
}
} , label: {
AsyncImage(url :URL(string: "https://picsum.photos/800/800?\(idx)")) { image in
let _ = ( images[idx] = image.image )
image.image
}.frame(width: boxHalf,height:boxHalf).drawingGroup()
})
}.overlay(
RoundedRectangle(cornerRadius: cr).stroke(Color.yellow, lineWidth: lw)
).drawingGroup()
}
}
}
}
func topSection() -> some View {
let imgarray = selected.compactMap { images[$0] }
return HStack {
ShareLink("",items: imgarray) { img in
SharePreview("images", image: Image(systemName: "captions.bubble.fill"))
}
}
}
}
#Preview {
ShareTestGContentView()
}
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.
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
I have my ContentView which has a Sheet that will appear when a button is pressed.
struct ContentView: View {
@EnvironmentObject private var settings: SettingsHandler
@State private var settingsView: Bool = false
var body: some View {
NavigationStack {
Button(action: {
settingsView.toggle()
}, label: {
Image(systemName: "gearshape.fill")
})
}
.preferredColorScheme(settings.darkTheme ? .dark : nil)
.sheet(isPresented: $settingsView, content: {
SettingsView()
})
}
}
Let's say the app is in light mode based on the phones theme settings. You open the SettingsView and select the toggle that will switch to dark mode. Everything changes to dark mode, including the SettingsView sheet. Then you select the same toggle to switch back and ContentView in the background changes to light theme but the sheet doesn't until you close and reopen it. I would think it would change back considering it changed to dark mode without needing to be closed.
I tried attaching an ID to the SettingsView and having it refresh when settings.darkTheme is changed, however, it doesn't seem to be doing anything. I also added the .preferredColorScheme() modifier into the SettingsView, but it did nothing. I also replaced the nil to .light, and the same issue occurred. Settings is an EnvironmentObject that I created to manage all the Settings I have.
At the moment, I'm thinking I can have the sheet just close and reopen, however, I would like for it to update properly. Any ideas?
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-Dick")
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.