Hi,
I have created an AppIntent in which there is a parameter called price, I have set the default value as 0.
@Parameter(title: "Price", default: 0)
var price: Int
Problem
When the shortcut is run this parameter is skipped
Aim
I still want to price to be asked however it needs to be pre-filled with 0
Question
What should I do that the shortcut can still ask the price but be pre-filled with 0?
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Created
Overview
I have a custom type Statistics that has 3 properties inside it
I am trying to return this as part of the AppIntent's perforrm method
struct Statistics {
var countA: Int
var countB: Int
var countC: Int
}
I would like to implement the AppIntent to return Statistics as follows:
func perform() async throws -> some IntentResult & ReturnsValue<Statistics> {
...
...
}
Problem
It doesn't make much sense to make Statistics as an AppEntity as this is only computed as a result.
Statistics doesn't exist as a persisted entity in the app.
Questions
How can I implement Statistics?
Does it have to be AppEntity (I am trying to avoid this)? (defaultQuery would never be used.)
What is the correct way tackle this?
Problem
When a List / Form is added inside a TabView and navigationTitle is set, then switching between tabs causes the navigation title to flicker.
Feedback:
FB21436493
Environment
Xcode: 26.2 (17C52)
iOS: 26.2 (23C55)
Reproducible on: Both simulator and device
Root cause
When List / Form is commented out, issue doesn't occur
Steps to Reproduce
Run app on iOS
Switch between tabs
Notice that the navigation title flickers
Code
ContentView
import SwiftUI
struct ContentView: View {
@State private var selectedTab = TabItem.red
var body: some View {
NavigationStack {
TabView(selection: $selectedTab) {
ForEach(TabItem.allCases, id: \.self) { tab in
Tab(tab.rawValue, systemImage: tab.systemImageName , value: tab) {
// Problem occurs with a List / Form
// Commenting out list works without flickering title
List {
Text(tab.rawValue)
}
}
}
}
.navigationTitle(selectedTab.rawValue)
}
}
}
TabItem
enum TabItem: String, CaseIterable {
case red
case green
case blue
var systemImageName: String {
switch self {
case .red:
"car"
case .green:
"leaf"
case .blue:
"bus"
}
}
}
Screen recording:
Topic:
UI Frameworks
SubTopic:
SwiftUI
Problem
For a mac app, when the Settings view that uses @Environment(\.dismiss) it causes the subview's models to be created multiple times.
Environment
macOS: 26.2 (25C56)
Feedback
FB21424864
Code
App
@main
struct DismissBugApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
Settings {
SettingsView()
}
}
}
ContentView
struct ContentView: View {
var body: some View {
Text("Content")
}
}
SettingsView
struct SettingsView: View {
@Environment(\.dismiss) private var dismiss
var body: some View {
VStack {
Text("Settings")
SectionAView()
}
}
}
SectionAView
struct SectionAView: View {
@State private var model = SectionAViewModel()
var body: some View {
Text("A")
.padding(40)
}
}
SectionAViewModel
@Observable
class SectionAViewModel {
init() {
print("SectionAViewModel - init")
}
deinit {
print("SectionAViewModel - deinit")
}
}
Steps to reproduce (refer to the attached video)
1 - Run the app on the mac
2 - Open app's Settings
3 - Notice the following logs being printed in the console:
SectionAViewModel - init
SectionAViewModel - init
4 - Tap on some other app, so that the app loses focus
5 - Notice the following logs being printed in the console:
SectionAViewModel - init
SectionAViewModel - deinit
6 - Bring the app back to focus
7 - Notice the following logs being printed in the console:
SectionAViewModel - init
SectionAViewModel - deinit
Refer to screen recording
Topic:
UI Frameworks
SubTopic:
SwiftUI
Problem
On the macOS when Settings view is closed, the @State model is not deallocated
Feedback
FB21393010
Environment
macOS: 26.2 (25C56)
Xcode: 26.2 (17C52)
Steps to reproduce
Run the project
Open app's 'Settings
Look at the console logs
When model is created SettingsModel - init gets printed
When Settings window is closed SettingsModel - deinit is not printed, meaning it is not deallocated
Code
SettingsModel
import SwiftUI
@Observable
class SettingsModel {
init() {
print("SettingsModel - init")
}
deinit {
print("SettingsModel - deinit")
}
}
SettingsView
import SwiftUI
struct SettingsView: View {
@State var model = SettingsModel()
var body: some View {
Text("Settings")
.font(.largeTitle)
.padding(200)
}
}
App
import SwiftUI
@main
struct SettingsBugApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
Settings {
SettingsView()
}
}
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
Hi,
Overview
I have a Mac app with a settings window. When I add a button it is added to the center.
I want it on the trailing edge, I even tried adding it as confirmationAction but doesn’t work.
Screenshot
Feedback
FB21374186
Steps to reproduce
Run the project on mac
Open the app's settings by pressing ⌘ ,
Notice that the Save button is in the center instead of the trailing edge
Code
App
import SwiftUI
@main
struct SettingsToolbarButtonBugApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
Settings {
SettingsView()
.frame(width: 300, height: 400)
}
}
}
SettingsView
import SwiftUI
struct SettingsView: View {
var body: some View {
NavigationStack {
Form {
Text("Settings window")
}
.toolbar {
ToolbarItem(placement: .confirmationAction) {
// Save button is the center instead of trailing edge
Button("Save") {}
}
}
.navigationTitle("Settings")
}
}
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
Hi,
Problem
When playing videos on the Developer app on the Mac, there is no full screen button for the video.
So it is not possible to play the video in full screen.
Note
I am not referring to the app going into full screen, the issue is with there is no option to play the video in full screen.
Environment
OS: macOS 26.2 (25C56)
Developer app: Version 10.8.3 (1083.3.1)
Feedback
FB21343934
Recording
Question
Are others also facing this issue?
Is there a workaround?
Suggestion
This seems to be recurring problem that seems get broken with app / OS releases.
Please write some UI tests to ensure the full screen button is present.
Would really appreciate if this gets fixed.
Topic:
Developer Tools & Services
SubTopic:
General
Overview
Tapping on ShareLink crashes the app when ShareLink is added in the toolbar with the placement of secondaryAction
Feedback
FB21337385
Note: Apple engineers please priorities this is a blocker and affects production apps and prevents us from going live.
Environment
Xcode: 26.2 (17C52)
iOS: 26.2
iPadOS: 26.2
Reproduce
Able to reproduce 100% both on Simulator and Device
Isolation of the crash
The crash happens only when the ShareLink is used with the placement .secondaryAction
The crash doesn't 'happen when the ShareLink is used with the placement .primaryAction
Code
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationStack {
Text("Hello, world!")
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button("Dummy") {
print("dummy")
}
}
// Tapping on share button will cause it to crash
// Crash only happens when the ShareLink is used with placement .secondaryAction
// It doesn't crash when placement is primaryAction
ToolbarItem(placement: .secondaryAction) {
ShareLink(item: "Some string")
}
}
}
}
}
Crash stack trace
*** Terminating app due to uncaught exception 'NSGenericException', reason: 'UIPopoverPresentationController (<_UIActivityViewControllerPresentationController: 0x105a3b580>) should have a non-nil sourceView or barButtonItem set before the presentation occurs.'
*** First throw call stack:
(
0 CoreFoundation 0x00000001804f71d0 __exceptionPreprocess + 172
1 libobjc.A.dylib 0x000000018009c094 objc_exception_throw + 72
2 UIKitCore 0x0000000185a5b17c -[UIPopoverPresentationController presentationTransitionWillBegin] + 2712
3 UIKitCore 0x0000000185a65de0 -[UIPresentationController _presentationTransitionWillBegin] + 28
4 UIKitCore 0x0000000185a6523c __80-[UIPresentationController _initViewHierarchyForPresentationSuperview:inWindow:]_block_invoke + 1928
5 UIKitCore 0x0000000185a633ec __77-[UIPresentationController runTransitionForCurrentStateAnimated:handoffData:]_block_invoke_3 + 296
6 UIKitCore 0x00000001868b2950 -[_UIAfterCACommitBlock run] + 64
7 UIKitCore 0x00000001868b2d64 -[_UIAfterCACommitQueue flush] + 164
8 UIKitCore 0x0000000186354f04 _runAfterCACommitDeferredBlocks + 256
9 UIKitCore 0x0000000186346bec _cleanUpAfterCAFlushAndRunDeferredBlocks + 76
10 UIKitCore 0x0000000186346cb4 _UIApplicationFlushCATransaction + 68
11 UIKitCore 0x0000000186263c48 __setupUpdateSequence_block_invoke_2 + 372
12 UIKitCore 0x000000018582f378 _UIUpdateSequenceRunNext + 120
13 UIKitCore 0x00000001862640a4 schedulerStepScheduledMainSectionContinue + 56
14 UpdateCycle 0x00000002501912b4 _ZN2UC10DriverCore18continueProcessingEv + 80
15 CoreFoundation 0x000000018041a4ac __CFMachPortPerform + 164
16 CoreFoundation 0x0000000180456aa8 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 56
17 CoreFoundation 0x00000001804560c0 __CFRunLoopDoSource1 + 480
18 CoreFoundation 0x0000000180455188 __CFRunLoopRun + 2100
19 CoreFoundation 0x000000018044fcec _CFRunLoopRunSpecificWithOptions + 496
20 GraphicsServices 0x0000000192a669bc GSEventRunModal + 116
21 UIKitCore 0x0000000186348574 -[UIApplication _run] + 772
22 UIKitCore 0x000000018634c79c UIApplicationMain + 124
23 SwiftUI 0x00000001da58d620 $s7SwiftUI17KitRendererCommon33_ACC2C5639A7D76F611E170E831FCA491LLys5NeverOyXlXpFAESpySpys4Int8VGSgGXEfU_ + 164
24 SwiftUI 0x00000001da58d368 $s7SwiftUI6runAppys5NeverOxAA0D0RzlF + 180
25 SwiftUI 0x00000001da31b42c $s7SwiftUI3AppPAAE4mainyyFZ + 148
26 ShareLinkSecondaryPlacementDemo.deb 0x0000000104d82b0c $s31ShareLinkSecondaryPlacementDemo0abcdE3AppV5$mainyyFZ + 40
27 ShareLinkSecondaryPlacementDemo.deb 0x0000000104d82bb8 __debug_main_executable_dylib_entry_point + 12
28 dyld 0x0000000104cc53d0 start_sim + 20
29 ??? 0x0000000104ff0d54 0x0 + 4378791252
)
libc++abi: terminating due to uncaught exception of type NSException
Overview
I have an iOS project where I have a list with sections.
Each cell in the section can be swiped to have some action
What needs to be done
When swipe button is pressed the cell needs to move from one section to the other without a UI glitch.
Problem
When I press the swipe action button, there is a UI glitch and some warnings are thrown.
UICollectionView internal inconsistency: unexpected removal of the current swipe occurrence's mask view. Please file a bug against UICollectionView. Reusable view: <SwiftUI.ListCollectionViewCell: 0x10700c200; baseClass = UICollectionViewListCell; frame = (16 40.3333; 370 52); hidden = YES; layer = <CALayer: 0x600000c12fa0>>; Collection view: <SwiftUI.UpdateCoalescingCollectionView: 0x106820800; baseClass = UICollectionView; frame = (0 0; 402 874); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x600000c13330>; backgroundColor = <UIDynamicSystemColor: 0x60000173a9c0; name = systemGroupedBackgroundColor>; layer = <CALayer: 0x600000c3a070>; contentOffset: {0, -62}; contentSize: {402, 229}; adjustedContentInset: {62, 0, 34, 0}; layout: <UICollectionViewCompositionalLayout: 0x10590edb0>; dataSource: <_TtGC7SwiftUI31UICollectionViewListCoordinatorGVS_28CollectionViewListDataSourceOs5Never_GOS_19SelectionManagerBoxS2___: 0x106822a00>>; Swipe occurrence: <UISwipeOccurrence: 0x103c161f0; indexPath: <NSIndexPath: 0xab1f048608f3828b> {length = 2, path = 0 - 0}, state: .triggered, direction: left, offset: 0>
Test environment:
Xcode 26.0.1 (17A400)
iOS 26 Simulator (iPhone 17 Pro)
Feedback filed:
FB20890361
Code
I have pasted below the minimum reproducible code
ContentView
import SwiftUI
struct ContentView: View {
@State private var dataStore = DataStore()
var body: some View {
List {
ToDoSection(status: .notStarted, toDos: notStartedToDos)
ToDoSection(status: .inProgress, toDos: inProgressToDos)
ToDoSection(status: .completed, toDos: completedTodos)
}
}
var notStartedToDos: [Binding<ToDoItem>] {
$dataStore.todos.filter { $0.wrappedValue.status == .notStarted }
}
var inProgressToDos: [Binding<ToDoItem>] {
$dataStore.todos.filter { $0.wrappedValue.status == .inProgress }
}
var completedTodos: [Binding<ToDoItem>] {
$dataStore.todos.filter { $0.wrappedValue.status == .completed }
}
}
ToDoSection
import SwiftUI
struct ToDoSection: View {
let status: ToDoItem.Status
let toDos: [Binding<ToDoItem>]
var body: some View {
if !toDos.isEmpty {
Section(status.title) {
ForEach(toDos) { toDo in
Text(toDo.wrappedValue.title)
.swipeActions(edge: .trailing) {
if status == .notStarted {
Button("Start") {
toDo.wrappedValue.status = .inProgress
}
}
if status != .completed {
Button("Complete") {
toDo.wrappedValue.status = .completed
}
Button("Move back") {
toDo.wrappedValue.status = .notStarted
}
}
}
}
}
}
}
}
ToDoItem
import Foundation
struct ToDoItem: Identifiable {
let id: UUID
let title: String
var status: Status
}
extension ToDoItem {
enum Status: Equatable {
case notStarted
case inProgress
case completed
var title: String {
switch self {
case .notStarted:
"Not Started"
case .inProgress:
"In Progress"
case .completed:
"Completed"
}
}
}
}
DataStore
import Foundation
@Observable
class DataStore {
var todos: [ToDoItem]
init() {
todos = [
ToDoItem(id: UUID(), title: "aaa", status: .notStarted),
ToDoItem(id: UUID(), title: "bbb", status: .notStarted),
ToDoItem(id: UUID(), title: "ccc", status: .notStarted)
]
}
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
My observations:
Passing a FocusState.Binding using focusedSceneValue seems to work only when the app uses a WindowGroup.
When the app uses a Window (single window) passing the FocusState.Binding in focusedSceneValue doesn't seem to work.
When app uses Window passing FocusState.Binding using focusedValue and receiving it in @FocusedValue seems to work.
Question:
Is this expected behaviour? (should focusedSceneValue only work for WindowGroup and not for Window?)
Problem
The following code doesn't work:
let predicate = #Predicate<Car> { car in
car.size == size //This doesn't work
}
Console Error
Query encountered an error: SwiftData.SwiftDataError(_error: SwiftData.SwiftDataError._Error.unsupportedPredicate)
Root cause
Size is an enum, #Predicate works with other type such as String however doesn't work with enum
Enum value is saved however is not filtered by #Predicate
Environment
Xcode: 15.0 (15A240d) - App Store
macOS: 14.0 (23A339) - Release Candidate
Steps to reproduce
Run the app on iOS 17 or macOS Sonoma
Press the Add button
Notice that the list remains empty
Expected behaviour
List should show the newly created small car
Actual behaviour
List remains empty inspite of successfully creating the small car.
Feedback
FB13194334
Code
Size
enum Size: String, Codable {
case small
case medium
case large
}
Car
import SwiftData
@Model
class Car {
let id: UUID
let name: String
let size: Size
init(
id: UUID,
name: String,
size: Size
) {
self.id = id
self.name = name
self.size = size
}
}
ContentView
struct ContentView: View {
var body: some View {
NavigationStack {
CarList(size: .small)
}
}
CarList
import SwiftUI
import SwiftData
struct CarList: View {
let size: Size
@Environment(\.modelContext)
private var modelContext
@Query
private var cars: [Car]
init(size: Size) {
self.size = size
let predicate = #Predicate<Car> { car in
car.size == size //This doesn't work
}
_cars = Query(filter: predicate, sort: \.name)
}
var body: some View {
List(cars) { car in
VStack(alignment: .leading) {
Text(car.name)
Text("\(car.size.rawValue)")
Text(car.id.uuidString)
.font(.footnote)
}
}
.toolbar {
Button("Add") {
createCar()
}
}
}
private func createCar() {
let name = "aaa"
let car = Car(
id: UUID(),
name: name,
size: size
)
modelContext.insert(car)
}
}
Problem
When copyable is used with NavigationSplitView then it doesn't work
The menu Edit > Copy is disabled
Note
When copyable is not used with a NavigationSplitView and used only with a plain List then it works.
Question
Is there anything I am missing?
Feedback
FB12990593
Platform
macOS 14.0 Beta (23A5312d)
Xcode 15.0 beta 6 (15A5219j)
Steps to reproduce
Run the app on mac
Select some cars
Press Command C
Expected Behaviour
Menu Edit > Copy should be enabled
Pressing Command C should allow user to copy selected cars
Actual Behaviour
Menu Edit > Copy is disabled
Pressing Command C doesn't allow user to copy selected cars
Code
struct ContentView: View {
@State private var dataStore = DataStore()
var body: some View {
NavigationSplitView {
Color.brown
} detail: {
CarListView(dataStore: dataStore)
}
}
}
struct CarListView: View {
let dataStore: DataStore
@State private var selectedCarIDs = Set<UUID>()
var body: some View {
List(selection: $selectedCarIDs) {
ForEach(dataStore.cars) { car in
CarCell(car: car)
.draggable(car)
}
}
.copyable(selectedCars())
}
private func selectedCars() -> [Car] {
dataStore.cars.filter { selectedCarIDs.contains($0.id) }
}
}
struct CarCell: View {
let car: Car
var body: some View {
VStack(alignment: .leading) {
Text(car.name)
Text("\(car.price)")
}
}
}
@Observable
class DataStore {
var cars = [
Car(name: "aaa", price: 10),
Car(name: "bbb", price: 20),
Car(name: "ccc", price: 30),
Car(name: "ddd", price: 40)
]
}
struct Car: Codable, Transferable, Identifiable {
let id: UUID
let name: String
let price: Int
init(name: String, price: Int) {
self.id = UUID()
self.name = name
self.price = price
}
static var transferRepresentation: some TransferRepresentation {
CodableRepresentation(contentType: .car)
}
}
extension UTType {
static let car = UTType("com.example.car")!
}
Problem
When app is run on iPhone 14 pro simulator running iOS 17 tapping on the EditButton shows the text "No folder selected"
Feedback
Feedback ID: FB12953838
Steps to reproduce:
Run the app on iOS 17 iPhone simulator
Tap on the "Edit" Button
Expected Behaviour
The view should show the car list in the edit mode
Actual Behaviour
The view shows the text "No folder selected"
Note: Problem happens only the first time, subsequently EditButton works fine.
Environment:
iOS: 17
Platform: iPhone 14 pro simulator
Xcode: 15.0 beta 6 (15A5219j)
Code
ContentView
import SwiftUI
struct ContentView: View {
@State private var selectedFolderID: Int?
@StateObject private var dataStore = DataStore()
var body: some View {
NavigationSplitView {
FolderListView(
selectedFolderID: $selectedFolderID,
dataStore: dataStore
)
} detail: {
if let selectedFolderID {
CarListView(
selectedFolderID: selectedFolderID,
dataStore: dataStore
)
} else {
Text("No folder selected")
}
}
}
}
FolderListView
import SwiftUI
struct FolderListView: View {
@Binding var selectedFolderID: Int?
@ObservedObject var dataStore: DataStore
var body: some View {
List(dataStore.folders, selection: $selectedFolderID) { folder in
NavigationLink(value: folder.id) {
Text(folder.name)
}
}
.task {
selectedFolderID = dataStore.folders.first?.id
}
}
}
CarListView
import SwiftUI
struct CarListView: View {
let selectedFolderID: Int
@ObservedObject var dataStore: DataStore
@State private var selectedCarIDs = Set<Int>()
var body: some View {
List(
dataStore.cars(withFolderID: selectedFolderID),
selection: $selectedCarIDs
) { car in
Text(car.name)
}
.toolbar {
//Tapping on the EditButton on the iPhone, shows the text "No folder selected".
EditButton()
}
}
}
DataStore
import Foundation
class DataStore: ObservableObject {
@Published var folders = [Folder(id: 0, name: "Folder 1"),
Folder(id: 1, name: "Folder 2"),
Folder(id: 2, name: "Folder 3"),
Folder(id: 3, name: "Folder 4"),
Folder(id: 4, name: "Folder 5")]
@Published var carIDsInFolder: [Folder.ID : [Car.ID]] = [0: [0, 1],
1: [2, 3],
2: [4, 5],
3: [6, 7],
4: [8, 9]]
@Published var cars = [Car(id: 0, name: "aaa", price: 100),
Car(id: 1, name: "bbb", price: 110),
Car(id: 2, name: "ccc", price: 120),
Car(id: 3, name: "ddd", price: 130),
Car(id: 4, name: "eee", price: 140),
Car(id: 5, name: "fff", price: 150),
Car(id: 6, name: "iii", price: 160),
Car(id: 7, name: "jjj", price: 170),
Car(id: 8, name: "***", price: 180),
Car(id: 9, name: "lll", price: 190)]
func cars(withFolderID folderID: Folder.ID) -> [Car] {
let carIDs = carIDsInFolder[folderID] ?? []
return carIDs.compactMap { car(withID: $0) }
}
func car(withID carID: Car.ID) -> Car? {
cars.first { $0.id == carID }
}
}
Car
import Foundation
struct Car: Identifiable {
var id: Int
var name: String
var price: Int
}
Folder
import Foundation
struct Folder: Identifiable {
var id: Int
var name: String
}
Problem:
On macOS, unable to drag multiple car items from FolderDetail List
Single items from a list are draggable but multiple items are not draggable.
Feedback FB10128110
I am really saddened that this is not fixed for over a year. Please look into this.
Platform
macOS 14 (beta 3), macOS 13
Steps to reproduce
Run the code provided below
Tap the sidebar button to show the sidebar
Select "Folder 0" from the sidebar
Drag "car a" into "Folder 1" (Go to Folder 2 to notice this happened successfully, you will be able to see "car a" in Folder 1)
Select "Folder 0" from the sidebar
Select "car a" and "car b" and try to drag them to "Folder 2"
Expected Behaviour
"car a" and "car b" must be both draggable (multiple items should be draggable).
The entire cell needs to be draggable not just the Text.
Actual Behaviour
Though “car a” and “car b” are selected, when dragged only one of the 2 items is dragged
You also can drag them only when dragging the Text unlike in iOS where you can drag the cell.
Note:
Same code works on iOS
Code:
UTType
extension UTType {
static var car = UTType(exportedAs: "com.example.DragAndDropListDemo.car")
}
Car
import Foundation
import CoreTransferable
struct Car: Identifiable {
var id: Int
var name: String
}
//extension Car: Codable {}
extension Car: Codable, Transferable {
static var transferRepresentation: some TransferRepresentation {
CodableRepresentation(contentType: .car)
}
}
Folder
struct Folder: Identifiable, Hashable {
var id: Int
var name: String
}
DataStore
class DataStore: ObservableObject {
var folders = (0..<100).map { Folder(id: $0, name: "folder \($0)")}
var cars = [0: [Car(id: 0, name:"car a"), Car(id: 1, name:"car b")],
1: [Car(id: 2, name:"car c"), Car(id: 3, name:"car d")]]
}
Views
ContentView
struct ContentView: View {
@StateObject private var dataStore = DataStore()
@State private var selectedFolder: Folder?
var body: some View {
NavigationSplitView {
FolderList(selectedFolder: $selectedFolder,
dataStore: dataStore)
} detail: {
FolderDetail(folder: selectedFolder,
dataStore: dataStore)
}
}
}
FolderList
struct FolderList: View {
@Binding var selectedFolder: Folder?
@ObservedObject var dataStore: DataStore
var body: some View {
List(dataStore.folders, selection: $selectedFolder) { folder in
NavigationLink(value: folder) {
Text(folder.name)
.dropDestination(for: Car.self) { cars, location in
print("cars = \(cars) location = \(location)")
if let existingCars = dataStore.cars[folder.id] {
dataStore.cars[folder.id] = existingCars + cars
} else {
dataStore.cars[folder.id] = cars
}
return true
}
}
}
}
}
FolderDetail
struct FolderDetail: View {
let folder: Folder?
@ObservedObject var dataStore: DataStore
@State private var selectedCarIDs = Set<Int>()
var body: some View {
if let folder {
List(dataStore.cars[folder.id] ?? [], selection: $selectedCarIDs) { car in
Text(car.name)
.draggable(car)
}
} else {
Text("no folder selected")
}
}
}
Overview
I have 2 models: Deparment and Student
Each Department can contain multiple students
Each Student can only be in one Department
I have DepartmentList, tapping on the department should take it to the StudentList which lists all students in the department
Problem
When I use Query in StudentList to filter only students for a specific department id, no students are shown.
Questions:
What should I do to list the students in a department? (see complete code below).
let filter = #Predicate<Student> { student in
student.department?.id == departmentID
}
let query = Query(filter: filter, sort: \.name)
_students = query
Complete code
App
@main
struct SchoolApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(for: [Department.self, Student.self])
}
}
Department
import Foundation
import SwiftData
@Model
class Department {
var id: UUID
var name: String
var students: [Student]
init(
id: UUID,
name: String,
students: [Student] = []
) {
self.id = id
self.name = name
self.students = students
}
}
Student
import Foundation
import SwiftData
@Model
class Student {
var id: UUID
var name: String
@Relationship(inverse: \Department.students)
var department: Department?
init(
id: UUID,
name: String,
department: Department? = nil
) {
self.id = id
self.name = name
self.department = department
}
}
ContentView
import SwiftUI
struct ContentView: View {
@State private var selectedDepartment: Department?
var body: some View {
NavigationSplitView {
DepartmentList(selectedDepartment: $selectedDepartment)
} detail: {
if let department = selectedDepartment {
StudentList(department: department)
} else {
Text("no department selected")
}
}
.task {
printStoreFilePath()
}
}
private func printStoreFilePath() {
let urls = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)
if let path = urls.map({ $0.path(percentEncoded: false) }).first {
print("Storage: \(path)")
}
}
}
DepartmentList
import SwiftUI
import SwiftData
struct DepartmentList: View {
@Binding
var selectedDepartment: Department?
@Query(sort: \.name)
private var departments: [Department]
@Environment(\.modelContext)
private var modelContext
var body: some View {
List(selection: $selectedDepartment) {
ForEach(departments) { department in
NavigationLink(value: department) {
Text(department.name)
}
}
}
.toolbar {
ToolbarItem {
Button {
addDepartment()
} label: {
Label("Add", systemImage: "plus")
}
}
}
}
private func addDepartment() {
guard let index = (1000..<10000).randomElement() else {
return
}
let department = Department(id: UUID(), name: "Department \(index)")
modelContext.insert(department)
}
}
StudentList
import SwiftUI
import SwiftData
struct StudentList: View {
var department: Department
@Query
private var students: [Student]
@Environment(\.modelContext)
private var modelContext
init(department: Department) {
self.department = department
let departmentID = department.id
let filter = #Predicate<Student> { student in
student.department?.id == departmentID
}
let query = Query(filter: filter, sort: \.name)
_students = query
}
var body: some View {
List {
ForEach(students) { student in
Text(student.name)
}
}
.toolbar {
ToolbarItem {
Button {
addStudent()
} label: {
Label("Add", systemImage: "plus")
}
}
}
}
private func addStudent() {
guard let index = (1000..<10000).randomElement() else {
return
}
let student = Student(
id: UUID(),
name: "Student \(index)",
department: department
)
modelContext.insert(student)
}
}