Hi,
I'm trying to build iOS app, but I found out that .onPreferenceChange has strange behaviour if the view contains an if statement below view which sets .preference.
Here is an repository with minimal reproduction: https://github.com/Mordred/swiftui-preference-key-bug
There should be displayed title text on the top and bottom of the screen. But the bottom is empty.
If you delete if statement if true { at https://github.com/Mordred/swiftui-preference-key-bug/blob/main/PreferenceKeyBug/PreferenceKeyBug.swift then it works fine.
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
Please update charts framework to have z axis for 3D plotting
My usage of TextField.focused() works fine in Xcode 14.3.1 but is broken as of Xcode 15. I first noticed it in the second beta and it's still broken as of the 4th beta.
Feedback / OpenRadar # FB12432084
import SwiftUI
struct ContentView: View {
@State private var text = ""
@FocusState var isFocused: Bool
var body: some View {
ScrollView {
TextField("Test", text: $text)
.textFieldStyle(.roundedBorder)
.focused($isFocused)
Text("Text Field Is Focused: \(isFocused.description)")
}
}
}
SwiftUI Buttons in a List no longer highlight when tapped. Seems to have stopped highlighting after iOS 16.0 I've only tested on an iPhone/simulators so not sure if iPad has the same issue.
The issue has been carried over to iOS 17 Beta 4. My app does not feel Apple like as there is no visual feedback for the user when a button in the list is pressed.
Does anyone know why this is occurring? Is this a bug on Apple's end?
I have an app that uses RealityKit and ARKit, which includes some capturing features (to capture and image with added Entities). I have a navigationLink that allows the user to see the gallery of the images he has taken.
When launching the App, the rotation animation of the ARView happens smoothly, the navigationBar transitions from one orientation to another with the ARView keeping it's orientation.
However, when I go to the galeryView to see the images and go back to the root view where the ARView is, the rotation animation of the ARView changed:
When transitioning from one orientation to another, the ARView is flipped by 90° before transitioning to the new orientation.
The issue is shown in this gif (https://i.stack.imgur.com/IOvCx.gif)
Any idea why this happens and how I could resolve it without locking the App's orientation changes?
Thanks!
Hi,
I'm trying to toggle the visibility of an overlay by using hovering. However, I found onHover() and onContinuousHover() don't work on visionOS. Is it intended?
Is there an solution for my case?
My SwiftUI code runs fine on macOS, iOS(iPad) and larger iPhones, but will not display the detail view on smaller iPhones.
Is there a way to force the smaller iPhones to display the detail view?
And if not,
When I put the App on the Apple store, for sale, will the Apple store be smart enough to flag the App as not appropriate for smaller iPhones, such as the SE (2nd and 3rd gen.) and prevent downloads?
Thanks in advance for any guidance.
I have a regular SwiftUI View embedded inside of a NavigationStack. In this view, I make use of the .searchable() view modifier to make that view searchable. I have a button on the toolbar placed on the .confirmationAction section, which is a problem when a User types into the search bar and the button gets replaced by the SearchBar's cancel button.
Thus, I conditionally place the button, depending on whether a User is searching, either on the navigationBar or on the keyboard. The latter does not work however, as the button does not show and when trying to debug the View Hierarchy, Xcode throws an error saying the View Hierarchy could not be displayed. If I set the button to be on the .bottomBar instead, it shows up perfectly and the View Hierarchy also displays with no further issue.
Has someone come across this issue and if so, how did you get it fixed?
Thank you in advance.
I'm using Xcode 14.3.1 on macOS 13.5, and I've managed to reproduce my issue in a trivial application. All the project settings are left at the defaults for a macOS project.
It looks like using a GroupBox breaks the ability of XCTest to find popovers connected to buttons (I suspect any UI element) inside the GroupBox.
The debug console output from the code below lists 15 descendants from my window with the outside-the-GroupBox popover open, and one of them is definitely a popover. With the inside-the-GroupBox popover open, my window only shows nine descendants, and no popover (the rest of the difference is the popover's contents). It's simple enough I don't see what I could be doing wrong:
import SwiftUI
@main
struct GroupBox_Popover_DemoApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
@State var outsidePopoverPresented: Bool = false
@State var insidePopoverPresented: Bool = false
var body: some View {
VStack {
Button("Outside GroupBox") {
outsidePopoverPresented = true
}
.popover(isPresented: $outsidePopoverPresented,
attachmentAnchor: .point(.leading),
arrowEdge: .leading) {
Popover(selected: .constant("Item A"), isPresented: $outsidePopoverPresented)
}
.padding()
GroupBox {
Button("Inside GroupBox") {
insidePopoverPresented = true
}
.popover(isPresented: $insidePopoverPresented,
attachmentAnchor: .point(.leading),
arrowEdge: .leading) {
Popover(selected: .constant("Item B"), isPresented: $insidePopoverPresented)
}
.padding()
}
}
.padding()
}
}
struct Popover: View {
@Binding var selected: String
@Binding var isPresented: Bool
var body: some View {
VStack(alignment: .leading) {
Picker("", selection: $selected) {
Text("Item A").tag("Item A")
Text("Item B").tag("Item B")
Text("Item C").tag("Item C")
}
.pickerStyle(.radioGroup)
HStack {
Spacer()
Button("Cancel") {
isPresented = false
}
}
}
.padding()
.frame(width: 200)
}
}
Then in my UI tests:
import XCTest
final class GroupBox_Popover_DemoUITests: XCTestCase {
let mainWindow = XCUIApplication().windows
override func setUpWithError() throws {
continueAfterFailure = false
XCUIApplication().launch()
}
func testPopovers() {
let myDescendants = mainWindow.descendants(matching: .any)
mainWindow.buttons["Outside GroupBox"].click()
print("Window descendants with outside popover open:")
print(myDescendants.debugDescription)
mainWindow.popovers.buttons["Cancel"].click()
mainWindow.buttons["Inside GroupBox"].click()
print("Window descendants with inside popover open:")
print(myDescendants.debugDescription)
mainWindow.popovers.buttons["Cancel"].click()
XCTAssert(true, "Test was able to hit cancel on both popovers.")
}
}
Any ideas? Have I missed unchecking some "Ignore anything in a GroupBox" checkbox somewhere?
I've read all previous posts on this topic but none seem to address what I'm seeing for iOS 16 and using NavigationStack. I'm also using an overall @EnvironmentObject for navigation state.
I have a split view app. In the detail section, I have a NavigationStack surrounding the detail view. Within the detail view (MyView), there is a base view with a "+" button in the toolbar to create a new entity.
That opens NewEntityView where I show a grid of buttons for the user to select a type to create a new entity before moving to NewEntityView to fill in the details for the entity. The top row of the grid of buttons takes the user straight to the NewEntityView with a NavigationLink. These work fine.
The next row of buttons present a menu of sub-types and then should take the user to the NewEntityView view. These buttons do not work.
Code (simplified to not have clutter):
SplitViewDetailView:
struct SplitViewDetailView: View {
@EnvironmentObject var navigationManager: NavigationStateManager
@Binding var selectedCategory: Route?
var body: some View {
NavigationStack(path: $navigationManager.routes) {
// other irrelevant stuff
MyView()
}
.environmentObject(navigationManager)
.navigationDestination(for: Route.self) { $0 }
}
}
MyView:
struct MyView: View {
@EnvironmentObject var navigationManager: NavigationStateManager
var body: some View {
List {
// other stuff
}
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {}, label: {
NavigationLink(value: Route.newTypeSelect) {
Image(systemName: "plus")
.frame(width: 44, height: 44)
}
} )
}
}
.navigationDestination(for: Route.self) { $0 }
}
SelectTypeView:
struct SelectTypeView: View {
var body: some View {
ZStack {
VStack {
// Top row with no subtypes
HStack {
ForEach (topRows, id: \.self) { type in
NavigationLink(value: Route.newEntityDetails(type.rawValue)) { <-- these work
Text(type)
}
}
}
HStack {
ForEach (middleRow, id: \.self) { type in
Menu {
ForEach (subtype[type], id: \.self) { sub in
NavigationLink(value: Route.newEntityDetails(sub.rawValue)) { <-- these go nowhere
Text(sub)
}
}
} label: {
Text(type)
}
}
}
}
}
}
}
NavigationStateManager:
class NavigationStateManager: ObservableObject {
@Published var routes = [Route]()
// other stuff
}
And Route:
enum Route: Identifiable {
var id: UUID { UUID() }
case newTypeSelect
case newEntityDetails(String)
}
extension Route: View {
var body: some View {
switch self {
case .newTypeSelect:
SelectTypeView()
case .newEntityDetails(let type):
NewEntityView(selectedType: type)
}
}
}
The menus show up fine but tapping on an item does nothing. I've attempted to wrap the menu in its own NavigationStack but that is rejected stating it is already in one defined by a parent view. I've tried making the links Buttons with destinations and those are also rejected.
What is the newest/best way to present a menu with NavigationLinks? One doesn't simply wrap the menu in a NavigationView if one is using a NavigationStack?
Try the following code on macOS, and you'll see the marker is added in the wrong place, as the conversion from screen coordinates to map coordinates doesn't work correctly.
The screenCoord value is correct, but reader.convert(screenCoord, from: .local) offsets the resulting coordinate by the height of the content above the map, despite the .local parameter.
struct TestMapView: View {
@State var placeAPin = false
@State var pinLocation :CLLocationCoordinate2D? = nil
@State private var cameraProsition: MapCameraPosition = .camera(
MapCamera(
centerCoordinate: .denver,
distance: 3729,
heading: 92,
pitch: 70
)
)
var body: some View {
VStack {
Text("This is a bug demo.")
Text("If there are other views above the map, the MapProxy doesn't convert the coordinates correctly.")
MapReader { reader in
Map(
position: $cameraProsition,
interactionModes: .all
)
{
if let pl = pinLocation {
Marker("(\(pl.latitude), \(pl.longitude))", coordinate: pl)
}
}
.onTapGesture(perform: { screenCoord in
pinLocation = reader.convert(screenCoord, from: .local)
placeAPin = false
if let pinLocation {
print("tap: screen \(screenCoord), location \(pinLocation)")
}
})
.mapControls{
MapCompass()
MapScaleView()
MapPitchToggle()
}
.mapStyle(.standard(elevation: .automatic))
}
}
}
}
extension CLLocationCoordinate2D {
static var denver = CLLocationCoordinate2D(latitude: 39.742043, longitude: -104.991531)
}
(FB13135770)
I recently was thinking about which is the best format to use for my little icons in the app, and was considering the performance of PNG versus SVG . I know that PNG decoders are hardware accelerated and parallelized, and the rendering is as simple as placing the pixels on the screen.
On the other hand, SVG requires computation to determine the placement of pixels based on mathematical equations.
Considering this, my current assumption is that PNG is faster to render than SVG. However, if SVG is also hardware-accelerated, it could alter the situation, although this may not be the case.
Hello everyone,
I am currently working on a project that requires me to programmatically manage keyboard layouts on both iOS and macOS devices. I'm looking for a comprehensive list of KeyboardLayout ID values for all the native keyboard layouts available in both iOS and macOS. While I can extract some of this information from the /System/Library/Keyboard Layouts/ directory on macOS, I cannot extract all without adding every keyboard layout active, having a complete and pre-compiled list would be immensely helpful.
Does anyone here have such a list or know where I might find one? Any guidance on this matter would be greatly appreciated.
Thank you in advance for your assistance!
JJ
We have separated much of our UI into different packages to reduce complexity and compile time. When we recently tested using new .xcstrings string catalogs, we hit an unexpected problem.
Strings extracted from SwiftUI components like Text or Button are extracted into the Localizable.xcstrings in the same package, but the default behaviour of Text(_ key:tableName:bundle:comment:) is to use Bundle.main.
When the default behaviour of the string extraction isn't to extract to the main app target, this introduces a very fragile system where it's easy to add code that looks localised, but ends up failing lookup at runtime.
I don't feel comfortable that we will always remember to define the correct module every time we create a Text. Also, other components like Button doesn't have an init that takes a Bundle, so we would also have to remember that Button(_ titleKey:action:) can now only be used in a package if we make sure that the main bundle contains a matching key.
Is there a way for us to make sure that strings are always extracted to the same place as they are resolved against by default? Either by having strings in packages extracted to an xcstrings file in the main app or having Text default to resolving against the module bundle by default?
In my Watch app on watchOS 9 I was using .foregroundColor(myColour) to colour the text in a widgetLabel on a corner complication like this:
let myColour: Color = functionThatReturnsAColorObjectConstructedLike Color.init(...) // green
.widgetLabel {
Text(myText)
.foregroundColor(myColour)
}
It worked fine; the widget label was green.
Now, in watchOS 10, I see that foregroundColor() is being deprecated in favour of foregroundStyle(), and I can use .foregroundStyle(.green), and - importantly - foregroundStyle() is only available on watchOS 10 and newer.
myColour is calculated depending on some other info, so I can't just write .green, and when I use .foregroundStyle(myColour) the widget label comes out as white every time, even if I set myColour = .green.
I think I have to use some sort of extension to pick the right combination, something like:
extension View {
func foregroundType(colour: Colour, style: any ShapeStyle) -> some THING? {
if #available(watchOS 10.0, *) {
return foregroundStyle(style)
} else {
return foregroundColor(colour)
}
}
}
// Usage
let myStyle: any ShapeStyle = SOMETHING?
...
.widgetLabel {
Text(myText)
.foregroundType(colour: myColour, style: myStyle)
It doesn't work. I just can't figure out what should be returned, nor how to return it. Any ideas?
I'm running into an issue with using .topBarTrailing placement for a toolbar item. The app fails to launch (crashes) with this placement. The following view works fine with any other placement (other than .topBarLeading).
What am I doing wrong?
var body: some View {
NavigationStack {
Text("Overview")
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button {
// noop
} label: {
Label("Add", systemImage: "plus")
}
}
}
.navigationTitle("Overview")
.navigationBarTitleDisplayMode(.inline)
}
}
I've opted to use .confirmationAction as a workaround, which works fine. It also positions the toolbar item in the same place on the view as the .topBarTrailing placement would.
I'm using Xcode version 15.0 and targeting WatchOS 10.
Verbose error output when trying to run the app in the simulator:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Layout requested for visible navigation bar, <PUICStackedNavigationBar: 0x100e1e8d0; baseClass = UINavigationBar; frame = (0 0; 198 60); opaque = NO; autoresize = W; layer = <CALayer: 0x60000027c280>> delegate=0x101877800 standardAppearance=0x60000261cc60, when the top item belongs to a different navigation bar. topItem = <UINavigationItem: 0x100f11230> title='Overview' style=navigator, navigation bar = <PUICStackedNavigationBar: 0x100f22a80; baseClass = UINavigationBar; frame = (0 0; 198 60); opaque = NO; autoresize = W; layer = <CALayer: 0x6000002887c0>> delegate=0x101069600 standardAppearance=0x60000261f3c0, possibly from a client attempt to nest wrapped navigation controllers.'
I found an issue when implementing an alert with a TextField to input a name. I want the action button to be disabled until a name has been entered, but the action block is never executed when the button has become enabled and pressed. The problem seems to appear only when name is initially an empty string. Tested with iOS 17.0.
struct MyView: View {
@State private var name = ""
var body: some View {
SomeView()
.alert(...) {
TextField("Name", text: $name)
Button("Action") {
// Action
}.disabled(name.isEmpty)
Button("Cancel", role: .cancel) {}
}
}
}
In visionOS, is there a way to temporarily hide the window close/position handle at the bottom of a window?
The Safari app does this, so it must be possible.
I'm experiencing a peculiar issue with SwiftUI's TextField. Whenever I long-press on the TextField, the console outputs an error about passing an invalid numeric value (NaN, or not-a-number) to the CoreGraphics API. This issue persists even in a new Xcode project with minimal code.
Code Snippet:
import SwiftUI
struct ContentView: View {
@State private var text: String = ""
var body: some View {
TextField("Placeholder", text: $text)
}
}
Error: this application, or a library it uses, has passed an invalid numeric value (NaN, or not-a-number) to CoreGraphics API and this value is being ignored. Please fix this problem.
Steps to Reproduce:
Create a new SwiftUI project in Xcode.
Add a TextField to the ContentView.
Run the app on a device or simulator.
Long-press inside the TextField.
What I've Tried:
Updating to the latest version of Xcode and iOS.
Using UIViewRepresentable to wrap a UIKit UITextField.
Creating a new Xcode project to isolate the issue.
None of these steps have resolved the issue.
Questions:
Has anyone else encountered this problem?
Are there any known workarounds for this issue?
Is this a known bug, and if so, has it been addressed in any updates?
Okay so I'm getting this log every time I present a UIAlertController:
Mac Catalyst: Presenting view controller <UIAlertController: 0x10f027000> from detached view controller <MyViewController: 0x10d104080> is not supported, and may result in incorrect safe area insets and a corrupt root presentation. Make sure <MyViewController: 0x10d104080> is in the view controller hierarchy before presenting from it. Will become a hard exception in a future release.
A few points:
MyViewController is not detached and the presentation shows just fine.
I specifically check for this before presenting the alert controller like so:
BOOL okayToPresentError = (self.isViewLoaded
&& self.view.window != nil);
if (okayToPresentError)
{
[self presentErrorInAlertController:error];
}
else
{
//Wait until view did appear.
self.errorToPresentInViewDidAppear = error;
}
It spews out every time an error is fed back to my app and I present the alert controller (I can turn off the network connection and I show an alert controller with a "retry" button in it which will loop the error back so I can replay the error alert presentation over and over again) .
Every time the alert controller is presented, I get this spewing in the console. Please don't start throwing hard exceptions because the check is faulty.