https://github.com/apple/sample-food-truck
Hi! I'm following along with the sample-food-truck application from WWDC 2022. I'm seeing some weird navigation issues when building the app for iPadOS.
The Table component displays a Select Button for selecting elements and a Done Button disabling that state. These buttons seem to be breaking something about navigation on iOS 18.4.1. It's a nondeterministic issue… but tapping the buttons seems to lead to some corrupt state where the app transitions out of OrdersView and back to TruckView.
This code from FoodTruckModel seems to be making a difference:
Task(priority: .background) {
var generator = OrderGenerator.SeededRandomGenerator(seed: 5)
for _ in 0..<20 {
try? await Task.sleep(nanoseconds: .secondsToNanoseconds(.random(in: 3 ... 8, using: &generator)))
Task { @MainActor in
withAnimation(.spring(response: 0.4, dampingFraction: 1)) {
self.orders.append(orderGenerator.generateOrder(number: orders.count + 1, date: .now, generator: &generator))
}
}
}
}
Commenting out that code and disabling the new Order values coming in seems to fix the issue.
Is there any public documentation for me to learn about the Select and Done buttons? I don't see anywhere for me to learn about how these work and what my ability is to customize their behavior.
Any ideas? I can repro from device and simulator.
SwiftUI
RSS for tagProvide views, controls, and layout structures for declaring your app's user interface using SwiftUI.
Posts under SwiftUI tag
200 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
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.
Using the native SwiftUI.Picker to set a @State which is then used to render different child views based on the selected state (using a switch-case inside body) seems to cause those child views to be unresponsive.
The following code below is a replicates the issue. The solution I am currently using is to build my own custom Picker that relies on SwiftUI.Buttons to set the state. This works.
enum PickerSelection: Hashable {
case binding, ownState
}
struct MainApp: View {
@State private var pickerSelection: PickerSelection? = nil
@State private var isToggled: Bool = false
var body: some View {
VStack(alignment: .leading) {
/// Changing `pickerSelection` via `SwiftUI.Picker` causes child views' toggles to be unresponsive.
Picker("Picker", selection: $pickerSelection) {
Text("No Option").tag(Optional<PickerSelection>(nil))
Text("Binding").tag(PickerSelection.binding)
Text("Own state").tag(PickerSelection.ownState)
}
/// Changing `pickerSelection` via a custom `Button`-based picker works as expected.
CustomPickerWithButtonBased(pickerSelection: $pickerSelection)
switch pickerSelection {
case .binding:
ChildViewWithBinding(isToggled: $isToggled)
case .ownState:
ChildViewManagingOwnState()
case .none:
EmptyView()
}
Spacer()
}
.padding()
}
}
struct ChildViewWithBinding: View {
@Binding var isToggled: Bool
var body: some View {
Toggle("ChildViewWithBinding", isOn: $isToggled)
}
}
struct ChildViewManagingOwnState: View {
@State private var isToggled: Bool = false
var body: some View {
Toggle("ChildViewManagingOwnState", isOn: $isToggled)
}
}
struct CustomPickerWithButtonBased: View {
@Binding var pickerSelection: PickerSelection?
var body: some View {
HStack {
Button {
pickerSelection = .binding
} label: {
Text("Binding")
}
Button {
pickerSelection = .ownState
} label: {
Text("OwnState")
}
}
}
}
Am I missing something with Picker?
Without developer mode, I was able to get Password AutoFill to work in my SwiftUI app with my local Vapor server using ngrok and adding the Associated Domains capability with the value webcredentials:....ngrok-free.app and the respective apple-app-site-association file on my local server in /.well-known/. (works on device, but not in the simulator).
However, if I use the developer mode (webcredentials:....ngrok-free.app?mode=developer) it only works halfway when running from Xcode: I get asked to save the password, but the saved passwords are not picked up, when I try to login again. Neither on device, nor in the simulator. If I remove the ?mode=developer it seems to work as expected.
Is this by design, or am I missing something?
var body: some View {
...
Section(header: Text("Email")) {
TextField("Email", text: $viewModel.credentials.username)
.textContentType(.username)
.autocapitalization(.none)
.keyboardType(.emailAddress)
}
Section(header: Text("Passwort")) {
SecureField("Passwort", text: $viewModel.credentials.password)
.textContentType(.password)
}
...
}
Topic:
Privacy & Security
SubTopic:
General
Tags:
SwiftUI
Universal Links
Authentication Services
Autofill
I'm building a SwiftUI app with a UITextView subclass, and it seems that the software keyboard doesn't trigger the pressesBegan or pressesEnded functions of UITextView. With a hardware keyboard, pressesBegan works as expected, allowing us to intercept key presses in our subclass.
I can't find any documentation about this, or any other forum posts (here or on Stack Overflow) that talk about a discrepancy between software and hardware keyboard behaviors, and I can't believe this is an intended behavior. Our app is a SwiftUI app, in case that's relevant.
Does anyone have any guidance? Is this a bug or am I not understanding this API? Any information or work arounds would be greatly appreciated.
I've made a sample project that demonstrates this issue, which you can grab from GitHub at https://github.com/nyousefi/KeyPressSample. To see this in action, run the sample project and start pressing keys. The hardware keyboard will print the key press at the top of the screen (above the text view), while the software keyboard won't.
I have a TextEditor, to the constructor of which in addition to the text I pass an object of the TextSelection? type. I check on the Simulator with iOS 18.2. An attempt to clear the text leads to a crash with the message "Thread 1: Fatal error: String index is out of bounds" in Xcode.
More about the error:
libswiftCore.dylib`_swift_runtime_on_report:
-> 0x194f32024 <+0>: ret
More about the reproduction conditions:
struct MyView: View {
@Bindable private var viewModel = MyViewModel()
@State var myTextSelection: TextSelection? = nil
var body: some View {
ZStack {
// Some other code
myEditor
// Some other code
}
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button {
viewModel.clear()
} label: {
Label("Clear", systemImage: "eraser")
}
}
}
}
var myEditor: some View {
ZStack(alignment: .topLeading) {
TextEditor(text: $viewModel.text, selection: $myTextSelection)
.disableAutocorrection(true)
.autocapitalization(.sentences)
}
// Some other code
}
}
MyViewModel:
@Observable
final class MyViewModel: ObservableObject {
var text: String = ""
func clear() {
text = ""
}
}
While trying the new ScrollPosition API I noticed that scrollTo(id: anchor:) behaves different than ScrollViewProxy.scrollTo(_: anchor:).
Consider the following example:
struct ContentView: View {
@State private var position = ScrollPosition(edge: .top)
var body: some View {
NavigationStack {
ScrollViewReader { proxy in
ScrollView {
VStack(spacing: 8) {
ForEach(1..<100) { index in
Text(verbatim: index.formatted())
.frame(maxWidth: .infinity)
.background(.gray)
.id(index)
}
}
}
.scrollPosition($position)
.toolbar {
ToolbarItemGroup(placement: .bottomBar) {
Spacer()
Button("50 (T)") {
withAnimation {
position.scrollTo(id: 50, anchor: .top)
// proxy.scrollTo(50, anchor: .top)
}
}
Button("50 (B)") {
withAnimation {
position.scrollTo(id: 50, anchor: .bottom)
// proxy.scrollTo(50, anchor: .bottom)
}
}
Spacer()
}
}
}
}
}
}
The position methods don't align top and bottom edges, but the proxy ones do.
Is this expected or is it a bug?
In the AVP project, a selector pops up, only wanting to filter spatial videos. When selecting the material of one of the spatial videos, the selection result returns empty. How can we obtain the video selected by the user and get the path and the URL of the file
The code is as follows:
PhotosPicker(selection: $selectedItem, matching: .videos) {
Text("Choose a spatial photo or video")
}
func loadTransferable(from imageSelection: PhotosPickerItem) -> Progress {
return imageSelection.loadTransferable(type: URL.self) { result in
DispatchQueue.main.async {
// guard imageSelection == self.imageSelection else { return }
print("加载成功的图片集合:(result)")
switch result {
case .success(let url?):
self.selectSpatialVideoURL = url
print("获取视频链接:(url)")
case .success(nil):
break
// Handle the success case with an empty value.
case .failure(let error):
print("spatial错误:(error)")
// Handle the failure case with the provided error.
}
}
}
}
In iOS 18, using .highPriorityGesture does not interfere with Button tap detection. However, on iOS 17 and earlier, setting a .highPriorityGesture causes the Button's tap action to stop responding.
I am using .highPriorityGesture in an attempt to support both tap and long-press gestures on a Button, which works as expected in iOS 18. However, the same implementation prevents taps on earlier versions.
Is using .highPriorityGesture on a Button not recommended in this case? Or is this an issue specific to how .highPriorityGesture behaves on iOS 17 and earlier?
Below is a sample code:
struct SampleButton: View {
let title: String
let action: () -> Void
var body: some View {
Button {
NSLog("Tapped")
action()
} label: {
Text(title)
}.highPriorityGesture(LongPressGesture(minimumDuration: 0.5).onEnded { _ in
NSLog("Long press.")
action()
})
}
}
struct ContentView: View {
var body: some View {
VStack {
SampleButton(title: "Tap or LongPress") {}
}
}
}
Environment:
Xcode: Version 16.3 (16E140)
iOS: iOS 18.4(simulator), iOS 17.5, iOS 16.4, iOS 15.2
Looking to start developing at Swift. What is the best way to get started with a job related to Swift development? Is there any specific demanded certification I could pursue?
Thank you.
I noticed that when using .searchable inside a NavigationStack thats inside a TabView, the searchbar briefly overlays the content before disappearing. After that, it is hidden and appears as expected when swiping down.
This only happens when the .searchable is inside the NavigationStack, there is at least one navigationTitle and the NavigationStack is inside a TabView.
Tested on simulator and real device.
I would appreciate any help.
Thanks!
struct FirstScreen: View {
var body: some View {
TabView {
Tab("Tab", systemImage: "heart") {
NavigationStack {
NavigationLink {
SecondScreen()
} label: {
Text("Go to second screen")
}
.navigationTitle("First Screen")
}
}
}
}
}
struct SecondScreen: View {
@State private var text: String = ""
var body: some View {
List {
Text("Some view that extends all the way to the top")
}
.searchable(text: $text)
.navigationTitle("Second Screen")
}
}
Without using a custom preview, you can set .contentShape(RoundedRectangle(cornerRadius: 30)) so that in the "zoomed in" preview of the contextMenu you can have a custom cornerRadius. However, this does not work if you create a custom preview, because then the ContentShape gets applied only to the LIFT PREVIEW, and not to the FINAL PREVIEW state. Heres a sample code - I'd love some support! :)
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
Rectangle()
.fill(Color.blue)
.frame(width: 300, height: 300)
.cornerRadius(30)
.contentShape(.contextMenuPreview, RoundedRectangle(cornerRadius: 30))
.contextMenu {
Button("Hello") {}
Button("Goofy") {}
} preview: {
Rectangle()
.fill(Color.blue)
.frame(width: 300, height: 300)
.cornerRadius(30)
//.contentShape(RoundedRectangle(cornerRadius: 30))
//.contentShape(.contextMenuPreview, RoundedRectangle(cornerRadius: 30))
}
Text("contextMenu item with large cornerRadius is not working as expected... No way to set contentShape to custom corner radius for final preview - not the lift preview")
}
}
}
Introduction
Hello,
As part of our ongoing migration to SwiftUI, we are currently managing navigation using UIKit. Our SwiftUI views are embedded in UIHostingController instances and pushed or presented via UINavigationController.
We’ve encountered an issue that causes either a UI glitch on iOS 18 or a crash on iOS 17 when using the .refreshable modifier in a SwiftUI view that is added to a UINavigationController via setViewControllers(_:animated:).
To reproduce the issue, we’re using the following simple SwiftUI view:
struct TestView: View {
var body: some View {
List {
ForEach(0...100, id: \.self) {
Text("Number: \($0)")
}
}
.refreshable {
// No action needed — the presence of this modifier alone triggers the issue
}
}
}
Problematic Scenario
The following code causes the issue:
class ViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let initialNav = self.navigationController
let hostingController = UIHostingController(rootView: TestView())
let newNav = UINavigationController()
// This causes a freeze (iOS 18) or crash (iOS 17)
newNav.setViewControllers([hostingController], animated: true)
initialNav?.present(newNav, animated: true)
}
}
After presenting the navigation controller, our app is freezing on iOS 18 or crashing on iOS 17.
Working scenario
When using pushViewController(_:animated:), the issue does not occur:
class ViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let initialNav = self.navigationController
let hostingController = UIHostingController(rootView: TestView())
let newNav = UINavigationController()
// This works without issue
newNav.pushViewController(hostingController, animated: true)
initialNav?.present(newNav, animated: true)
}
}
Conclusion
We would like to better understand the root cause of this behavior. While using pushViewController is a viable workaround, there are scenarios where we must rely on setViewControllers, and currently, that approach breaks the experience or crashes the app.
Is this a known issue, or are we missing something about how UIHostingController interacts with .refreshable in this context?
Thanks for your time — we look forward to any insights you can share.
Hi everyone,
Something didn't work in my environment so I wrote some demo code:
import SwiftUI
@main
struct DemoApp: App {
var body: some Scene {
WindowGroup {
Color.accentColor.opacity(1/4)
.frame(idealWidth: 800, idealHeight: 800)
}
.windowIdealSize(.fitToContent)
}
}
I expected a 800*800 window (then +28pt top) using .windowIdealSize(.fitToContent). Otherwise I can't control these views that use up available space such as Color, Spacer, GeometryReader, etc.
Was I missing something? Or this is a problem or intended framework design?
Environments:
macOS 15.4.1 (24E263) and 15.5 beta 4 (24F5068b)
Xcode 16.3 (16E140)
I am using a LayzVStack embedded into a ScrollView. The list items are fetched from a core data store by using a @FetchResult or I tested it also with the new @Query command coming with SwiftData.
The list has one hundred items 1, 2, 3, ..., 100.
The user scrolled the ScrollView so that items 50, 51, ... 60 are visible on screen.
Now new data will be fetched from the server and updates the CoreData or SwiftData model. When I add new items to the end of the list (e.g 101, 102, 103, ...) then the ScrollView is keeping its position.
Opposite to this when I add new items to the top (0, -1, -2, -3, ...) then the ScrollView scrolls down.
Is there a way with the new SwiftData and SwiftUI ScrollView modifiers to update my list model without scrolling like with UIKit where you can query and set the scroll offset pixel wise?
I have find out that a UIViewRepresentable, even with a simples UIView, seems to never be dismantled when deleted from a ForEach and this can cause serious crashes.
In the following example you can observe this behavior by deleting a row from the list. The dismantleUIView function of SomeUIViewRepresentable or the deinit of SomeUIView are never called.
Has anyone faced this and found a solution for it?
I have also filled a Feedback: FB11979117
class SomeUIView: UIView {
deinit {
print(#function)
}
}
struct SomeUIViewRepresentable: UIViewRepresentable {
func makeUIView(context: Context) -> SomeUIView {
let uiView = SomeUIView()
uiView.backgroundColor = .systemBlue
return uiView
}
func updateUIView(_ uiView: SomeUIView, context: Context) { }
static func dismantleUIView(_ uiView: SomeUIView, coordinator: Coordinator) {
print(#function)
}
}
struct Model: Identifiable {
let id = UUID()
}
struct ContentView: View {
@State var models = [Model(), Model(), Model(), Model(), Model()]
var body: some View {
List {
ForEach(models) { _ in
SomeUIViewRepresentable()
}
.onDelete {
models.remove(atOffsets: $0)
}
}
}
}
Seeing this magical sand table, the unfolding and folding effects are similar to spreading out cards, which is very interesting. But I don't know how to achieve it. I want to see if there are any ways to achieve this effect and give some ideas. May I ask if this effect can be achieved under the existing API
https://github.com/apple/sample-food-truck
Hi! I'm seeing what looks like some weird navigation issue in the Food Truck app. It's from the Live Activity that should deep link to a specific point in the app. There seems be some state where the app is not linking to the correct component. Here are my repro steps on iPhone:
Start live activity from OrderDetailView.
Navigate to Sidebar component.
Tap the Live Activity.
App opens TruckView.
The App should be opening the OrderDetailView for the Order that was passed to the Live Activity. This seems to work when the app is not currently on Sidebar.
Any ideas? I'm testing this on iPhone OS 18.4.1. Is this an issue inside NavigationSplitView? Is this an issue with how Food Truck handles deeplinking?
Hi! I develop an iOS library and I met an issue with SwiftUI previews in iOS app project with my library integrated. After I open preview, build for preview finishes successfully, but preview itself never appears. I failed to find any error messages or any other indicators of what went wrong or how to fix it. Switching to legacy preview execution seems to fix problem, but I think that is not ideal. Could you help fixing this?
Xcode 16.2, Simulator iPhone 16, iOS 18.2
Project to reproduce -
https://drive.google.com/file/d/1cU6JKwshK_wQfe9YIqcMg3UGWq45OYlx/view?usp=sharing
Preview diagnostics - https://drive.google.com/file/d/1kPcgVSSqreiepGuqhdIoCW2rLSicgsWr/view?usp=sharing
This text is cut off for some unknown reason, but if you explicitly specify the default font, it is displayed correctly.
Various solutions like .fixedSize(horizontal:,), frame(maxWidth:), lineLimit() do not solve the problem.
Any other text does not have such problems.
The bug is reproduced on iPhone 12 (iOS 18.4.1)
public var body: some View {
Text("Включите уведомления, чтобы первыми узнавать о новых коллекциях, эксклюзивных предложениях и статусе доставки")
.padding(.horizontal)
// .font(.system(size: 17)) // it works correctly with this
}