Before visionOS Beta 4 it was possible to define the launch size in the Info.plist using PreferredLaunchSize like so:
<key>UILaunchPlacementParameters</key>
<dict>
<key>PreferredLaunchSize</key>
<dict>
<key>Height</key>
<integer>750</integer>
<key>Width</key>
<integer>750</integer>
</dict>
</dict>
In visionOS Beta 4 this now doesn't work anymore and the window opens in a 16:9 format and then will scale down to the .defaultSize of the WindowGroup with an animation.
Settings, Notes, Safari still open with a different default size though, including the launch screen.
How are we supposed to do this now?
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
Hello There,
I was trying to do a Button with title left aligned. With the old UIButton, I would have used the title-/contentEdgeInsets to achieve this, but with the new button these values are deprecated and do not work anymore. As far as I understood, with the new button only the spacing between the elements (sub-, title and image) is controllable. I also tried just setting the buttons width to the same width as the label, what would be possible in my case since it should be kind of a "hyperlink-button" which has no background or border. This works so far, but once the user interacts with the button, the title label gets multiline, which is on the one hand not wanted and on the other hand of course does not look left aligned anymore. (Besides the buttons height is fix in my case which leads to clipping of the title)
So here again in short: Is there any way to make the title of the new UIButton left aligned inside of the button?
Thank you very much in advance.
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
Hi,
I have a NavigationSplitView with a view in the detail section:
NavigationSplitView {
ZStack {
Color.black.ignoresSafeArea()
gradientBlack2Blue.opacity(0.25)
.ignoresSafeArea()
GeometryReader { p in
VStack {
List {
SidebarViewCell(id: "1",
text: "Steuersätze" ,
type: .TAX_MASTERDATA ,
selectedMasterdataType: $selectedMasterdataType)
}.listRowSpacing(size.height * 1.25 / 100 )
.scrollContentBackground(.hidden)
.toolbar(.hidden, for: .navigationBar)
.frame(width: p.size.width * 98 / 100 , height: p.size.height,
alignment: .topLeading).
}alignment: .topLeading)
}
}
}
detail: {
MasterdataDetailView().ignoresSafeArea()
}
}.navigationSplitViewStyle(.balanced)
When I place a Button-Control in the MasterdataDetailView it cannot be clicked because it is in the safe area. How can I make it clickable?
Best Regards,
Frank
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?
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 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?
Hi,
I've tried to find a solution for this problem for weeks now but it seems no one knows how to solve it and Apple doesn't seem to care.
I have a NavigationSplitView with two columns. In the detail column I have a button - or any other clickable control - which is placed in the very top where usually the safe area resides.
The button is NOT clickable when he is in the safe area and I have NO idea why. I know I can place buttons in safe areas of other views and they are clickable.
Please have a look at the code:
`struct NavTestView: View {
var body: some View {
GeometryReader { p in
VStack(spacing: 0) {
NavigationSplitView {
List(names) {
Text($0.name).frame(width: p.size.width)
.background(Color.green)
}.listRowSpacing(p.size.height * 0.15 / 100 )
.toolbar(.hidden, for: .navigationBar)
} detail: {
TestView().ignoresSafeArea()
}.frame(width: p.size.width, height: p.size.height, alignment: .topLeading)
.background(Color.yellow)
}
}
}
}
struct TestView: View {
var body: some View {
GeometryReader { p in
let plusButton = IconButton(imageName: "plus.circle.fill", color: Color(uiColor: ThemeColor.SeaFoam.color),
imageWidth: p.size.width * 5 / 100, buttonWidth: p.size.width * 5 / 100)
let regularAddButton = Button(action: { log.info("| Regular Add Button pressed") } ) {
plusButton
}
VStack {
regularAddButton
}.frame(width: p.size.width , height: p.size.height, alignment: .top)
.background(Color.yellow)
}
}
}
`
this code produces the following screen:
Any help would be really greatly appreciated!
Thank you!
Frank
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()
}
Hello.
Is there a good SwiftUI approach on getting the TextEditor cursor position?
I have a TextEditor and sometimes when we have a longer text inside it, the cursor is not seen because the keyboard is above covering the bottom of the TextEditor.
I would like to somehow detect the position of the cursor, and if it's on the last line of the TextEditor, scroll to the bottom. I've already checked a bit and didn't find any good method of doing this in SwiftUI.
If you have any ideas on how to do this, or even a different method any help would be highly appreciated.
Thank you!
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!
I am trying to build a text editor that shrinks to its content size. The closest I have been able to get has been to add the .scrollDisabled(true) and .fixedSize(horizontal: false, vertical: true) modifiers.
This almost achieves what I need. There are two problems though:
long single line text gets cut off at the end
creating line breaks causes the text editor to grow vertically as expected (uncovering the cut off text in point 1 above). However, when you delete the line breaks, the TextEditor does not shrink again.
I have had a radar open for some time: FB13292506. Hopefully opening a thread here will get more visibility.
And here is some sample code to easily reproduce the issue:
import SwiftUI
struct ContentView: View {
@State var text = "[This is some long text that will be cut off at the end of the text editor]"
var body: some View {
TextEditor(text: $text)
.scrollDisabled(true)
.fixedSize(horizontal: false, vertical: true)
}
}
#Preview {
ContentView()
}
Here is a gif of the behavior: