Provide views, controls, and layout structures for declaring your app's user interface using SwiftUI.

Posts under SwiftUI tag

200 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

SwiftUI Bug: Clear Navigation Stack when changing to any Tab
Hi, I have a project that uses SwiftUI, where we have a TabView, and in one of the tabs, I have a NavigationStack(path:). And created a logic to clear the NavigationStack path everytime you change to another Tab. But found a bug, that if for some reason when doing a navigation in the NavigationStack, and rapidly tapping to another Tab, the NavigationStack doesn't gets clean up, or even if you have for some reason something allocated in the view you were navigation, doesn't get deinit if you have the logic for deinit a object when dismissing the view. The environment I have is: iPhone 12 Pro Max with iOS 17.6.1 This is the code that I have: struct TabBarView: View { @ObservedObject var tabBarVC = TabBarViewController() var body: some View { TabView(selection: $tabBarVC.selectedTab) { Text("HomeView") .tabItem { Label("Home", systemImage: "house") } .tag(TabBarViewController.Tab.home) SettingsView(settingsVC: tabBarVC.settingsVC) .tabItem { Label("Settings", systemImage: "gear") } .tag(TabBarViewController.Tab.settings) } .onChange(of: tabBarVC.selectedTab) { oldValue, newValue in tabBarVC.settingsVC.clearNavigationPath() } } } class TabBarViewController: ObservableObject { enum Tab { case home case settings } @Published var selectedTab: Tab = .home @Published var settingsVC: SettingsViewController = .init() } class SettingsViewController: ObservableObject { enum Destination { case viewOne case viewTwo case viewThree } @Published var navigationPath: NavigationPath = .init() func navigateTo(destination: Destination) { self.navigationPath.append(destination) } func clearNavigationPath() { self.navigationPath = .init() } } The expected I am looking for is that everytime you change your tab, it cleans up the navigation stack, even if you change the tab when there is a navigation animation in process.
2
1
217
Oct ’24
Family Activity Picker crashes (Connection to plugin invalidated while in use)
Even on iOS 18 (16-17 also repo) we are seeing a crash on the FamilyActivityPicker when users tap on "Other" or just at random times. We see the follow debug message but no other way of identifying the issue in code. [u 3C8AF272-DC4E-55C4-B8C6-34826D2BEB5B:m (null)] [com.apple.FamilyControls.ActivityPickerExtension(1150.1)] Connection to plugin invalidated while in use. Even with the most basic implementation of FamilyActivityPicker (example below) we can repro this crash consistently. Big applications (think Opal) see the same issue but it seems like they see it less, and are able to intercept the disconnect in order to show an error to the user. My two questions are How can we intercept this crash/disconnect in order to alert our user and restart the experience? Is this EVER gonna get fixed properly? Usage Example: var body: some View { NavigationView { ZStack { familyPickerErrorView .opacity(isHidden ? 0 : 1) .onAppear { DispatchQueue.main.asyncAfter(deadline: .now() + 2) { withAnimation { isHidden = false } } } VStack { Color.clear .frame(height: 1) .background(Color(UIColor.systemBackground)) FamilyActivityPicker( headerText: "Select Apps To Be Blocked (Maximum of 50)", footerText: "Want to block Safari? Check our FAQs", selection: $familySelection) .ignoresSafeArea(.all) } } } .toolbar { ToolbarItem(placement: .navigationBarLeading) { Button(action: { isPresented = false }) { Text("Cancel") .foregroundColor(.black) } } ToolbarItem(placement: .navigationBarTrailing) { Button(action: { isPresented = false }) { Text("Done") } } } .navigationBarTitleDisplayMode(.inline) .alert(isPresented: $showAlert) { Alert(title: Text("Family Activity Picker Issue"), message: Text(alertMessage), dismissButton: .default(Text("OK"))) } .onAppear { isPresented = true } }
1
0
189
Oct ’24
Weird vibrancy effects on Mac Catalyst
Hello, my app uses vibrancy effects thanks to SwiftUI's materials and hierarchical shape style. While they work flawlessly on iOS and iPadOS, on Mac Catalyst they seem to be pretty broken. I'm attaching some screenshots. iPad Mac This is the same code, with the same background behind the material. The colors are already pretty different, but my concern is about the text, which clearly looks broken Here a sample code: HStack(spacing: 0) { VStack(alignment: .leading, spacing: 2) { Text(event.label) .font(.subheadline.weight(.semibold)) .foregroundStyle(.secondary) Text(event.info(for: currentDestination)) .font(.system(.title2, design: .rounded, weight: .semibold)) .foregroundStyle(.primary) } Spacer(minLength: 0) InfoIcon(isCustom: event.isCustomIcon, icon: event.icon, renderingMode: .palette, size: iconSize) .font(.body.weight(.semibold)) } .padding(.horizontal, 24) .padding(.vertical, 12) .background(.quaternary, in: .rect(cornerRadius: 16, style: .continuous)) .clipShape(.rect(cornerRadius: 16, style: .continuous)) .padding(.all, 16) .background(.ultraThinMaterial, in: .rect)
0
0
159
Oct ’24
Progressive Blur With List
I'm trying to setup my view so that there's (in order from top of display to bottom) a VStack with some content, followed by a List, followed by another VStack with a couple buttons where progressive blurs separate the list and the two VStack's content. Now, in the current version of my app when the user scrolls up or down, the list just cuts off. I'm having a very difficult time maintaining the entire view's vertical positioning while adding these blurs with ZStack. The code below is the current implementation with an attempted progressive blur. Right now, it's close, but the list is acting exactly how I don't want it - anchoring to the top of the display (its natural position) and causes the toolbar to blur when scrolled under (I can't disable toolbar without losing my toolbarItems either). Any help is appreciated. NavigationStack { VStack { ZStack { List(filteredItems) { item in NavigationLink(destination: ItemDetailView(item: item)) { HStack(spacing: 15) { Image(systemName: item.icon) VStack(alignment: .leading) { Text(item.name) Text("") } .multilineTextAlignment(.leading) } .padding(.vertical, 5) } } .scrollIndicators(.hidden) .scrollContentBackground(.hidden) VStack(spacing: 5) { if #available(iOS 18.0, *) { Image(systemName: "plus.square.on.square.fill") .resizable() .scaledToFit() .frame(maxHeight: 50) .symbolEffect(.bounce.up, options: .nonRepeating) } else { Image(systemName: "plus.square.on.square.fill") .resizable() .scaledToFit() .frame(maxHeight: 50) } Text("Items") .font(.largeTitle.bold()) Text("Create, View, and Manage Your Items") .font(.system(size: 12).weight(.bold)) .multilineTextAlignment(.center) ScrollView(.horizontal) { HStack(spacing: 20) { filterButton(icon: "car.fill", color: .red, label: "Auto") filterButton(icon: "cart.fill", color: .purple, label: "Shopping") filterButton(icon: "laptopcomputer", color: .blue, label: "Tech") filterButton(icon: "airplane", color: .orange, label: "Travel") filterButton(icon: "gamecontroller.fill", color: .green, label: "Entertainment") } .padding(.leading, 25) } .scrollBounceBehavior(.basedOnSize) .scrollIndicators(.hidden) Spacer() } .padding(.top) VStack { Rectangle() .fill(.thinMaterial) .frame(height: 300) .mask { VStack(spacing: 0) { LinearGradient(colors: [Color.black.opacity(0), Color.black.opacity(0.383), Color.black.opacity(0.707), Color.black.opacity(0.924), Color.black], startPoint: .bottom, endPoint: .top) .frame(height: 400) Rectangle() } } Spacer() } .ignoresSafeArea() VStack { Spacer() Rectangle() .fill(.thinMaterial) .frame(height: 200) .mask { VStack(spacing: 0) { LinearGradient(colors: [Color.black.opacity(0), Color.black.opacity(0.383), Color.black.opacity(0.707), Color.black.opacity(0.924), Color.black], startPoint: .top, endPoint: .bottom) .frame(height: 100) Rectangle() } } } .ignoresSafeArea() VStack(spacing: 12) { Spacer() Button { showingAddItemView.toggle() } label: { HStack { Image(systemName: "plus.circle") Spacer() .frame(width: 7) Text("New Item") .padding(.trailing, 3) } #if os(visionOS) .padding(.vertical) #endif } .padding(10) #if os(iOS) .background { Capsule() } #endif NavigationLink("Continue") { } } .padding()
0
0
249
Oct ’24
CoreGraphics: CGPDFPageCopyRootTaggedNode
My app uses PDFKit, but I don't know how to solve this bug at all. Under the same IOS system and device model, some users' devices may experience crashes, while our own devices are functioning normally. The following is the stack information for crashing: 0 libsystem_platform.dylib__os_unfair_lock_recursive_abort + 36 1 libsystem_platform.dylib__os_unfair_lock_lock_slow + 308 2 CoreGraphics_CGPDFPageCopyRootTaggedNode + 56 3 PDFKit-[PDFPageViewAccessibility accessibilityElements] + 76 4 UIAccessibility-[NSObject(AXPrivCategory) _accessibilityElements] + 56 5 UIAccessibility-[NSObjectAccessibility accessibilityElementCount] + 68 6 UIAccessibility-[NSObject(AXPrivCategory) _accessibilityHasOrderedChildren] + 44 7 UIAccessibility-[NSObject(AXPrivCategory) _accessibilityFrameForSorting] + 216 8 UIAccessibility-[NSObject _accessibilityCompareGeometry:] + 116 9 UIAccessibility-[NSObject(AXPrivCategory) accessibilityCompareGeometry:] + 52 10 CoreFoundation___CFSimpleMergeSort + 100 11 CoreFoundation___CFSimpleMergeSort + 248 12 CoreFoundation_CFSortIndexes + 260 13 CoreFoundation-[NSArray sortedArrayFromRange:options:usingComparator:] + 732 14 CoreFoundation-[NSMutableArray sortedArrayFromRange:options:usingComparator:] + 60 15 CoreFoundation-[NSArray sortedArrayUsingSelector:] + 168 16 UIAccessibility___57-[NSObject(AXPrivCategory) _accessibilityFindDescendant:]_block_invoke + 268 17 UIAccessibility___96-[NSObject(AXPrivCategory) _accessibilityEnumerateAXDescendants:passingTest:byYieldingElements:]_block_invoke + 140 18 UIAccessibility-[NSObject _accessibilityEnumerateAXDescendants:passingTest:byYieldingElements:] + 244 19 UIAccessibility-[NSObject _accessibilityFindFirstAXDescendantPassingTest:byYieldingElements:] + 272 20 UIAccessibility-[NSObject(AXPrivCategory) _accessibilityFindDescendant:] + 100 21 UIAccessibility__axuiElementForNotificationData + 276 22 UIAccessibility__massageAssociatedElementBeforePost + 36 23 UIAccessibility__UIAXBroadcastMainThread + 292 24 libdispatch.dylib__dispatch_call_block_and_release + 32 25 libdispatch.dylib__dispatch_client_callout + 20 26 libdispatch.dylib__dispatch_main_queue_drain + 980 27 libdispatch.dylib__dispatch_main_queue_callback_4CF + 44 28 CoreFoundation___CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 16 29 CoreFoundation___CFRunLoopRun + 1996 30 CoreFoundation_CFRunLoopRunSpecific + 572 31 GraphicsServices_GSEventRunModal + 164 32 UIKitCore-[UIApplication _run] + 816 33 UIKitCore_UIApplicationMain + 340 34 SwiftUIclosure #1 (Swift.UnsafeMutablePointer<Swift.UnsafeMutablePointer<Swift.Int8>?>) -> Swift.Never in SwiftUI.(KitRendererCommon in _ACC2C5639A7D76F611E170E831FCA491)(Swift.AnyObject.Type) -> Swift.Never + 168 35 SwiftUI SwiftUI.runApp(A) -> Swift.Never + 100 36 SwiftUI static (extension in SwiftUI):SwiftUI.App.main() -> () + 180
2
2
215
Oct ’24
How can I programmatically have focus in a SwiftUI TextField at launch/load
I thought the following code would allow me to have focus in the TextField when the app loads. Is there something else/different that I need to do? struct ContentView: View { enum FocusField { case password } @State var fieldContent: String = "" @FocusState var focus: FocusField? var body: some View { VStack { TextField("Enter text here", text: $fieldContent) .focused($focus, equals: .password) Text("Hello, world!") } .padding() .defaultFocus($focus, .password) } }
1
0
213
Oct ’24
request review bug
Previously, i create an app and i'm using a userdefault with app group to enable to connect it with extension. But a bug causing me very frustating and so long to solve this, I think it just my code bug, but it was causing by the swiftui itself. Where requestReview environment, causing my navigationlink that pointing to a view that include userdefault that connect to app group is freezing while tapping. Than it just caused in my ios 16 device, and work smoothly in my ios 18 device. struct SettingView: View { @Environment(\.requestReview) var requestReview var body: some View { NavigationStack { List { Section("Configuration") { NavigationLink(destination: WidgetConfigurationView()) { Label("Widget", systemImage: "paintpalette") } } } } } struct WidgetConfigurationView: View { @Environment(\.dismiss) var dismiss @AppStorage("widgetalignment", store: UserDefaults(suiteName: "group.com.my.app")) var alignment: Int = 0 } can anyone explain why this happened? is this my mistake or the swiftui bug?
0
0
160
Oct ’24
How to make changes of text in search filed to cause animated changes in the view?
Following the examples from the official documentation: https://developer.apple.com/documentation/swiftui/adding-a-search-interface-to-your-app When the user types in the text in the search field, the list is updated with filtered results. How do I cause these changes to be animated? I tired to put .animated() after the .searchable modifier, the result was what I am looking for, however it also broke the animation of the search field getting/releasing focus.
1
0
202
Oct ’24
Custom Container View with ForEach(subviews:content:)
Hi, I’m trying to implement a custom horiztonal Picker using the newly introduced API on ForEach like the following: struct ScopeBar<SelectionValue: Hashable, Content: View>: View { // MARK: Initializers @Binding private var selection: SelectionValue @ViewBuilder private var content: () -> Content public init(selection: Binding<SelectionValue>, @ViewBuilder content: @escaping () -> Content) { _selection = selection self.content = content } // MARK: Content var body: some View { ScrollView(.horizontal) { LazyHStack { ForEach(subviews: content()) { subview in Button { // selection = subview.id as! SelectionValue } label: { subview } .tag(subview.id) } } } } } The following implementation is what I’m trying to achieve for the custom container usage: struct MyOtherView: View { enum SomeScopes: String, CaseIterable, Hashable { case first case second case third case fourth case fifth } @State private var selection: SomeScopes = .first var body: some View { ScopeBar(selection: $selection) { ForEach(SomeScopes.allCases, id: \.rawValue) { scope in Text(scope.rawValue) } } } } I’m having some trouble figuring out two things: How can I make my SelectionValue equal to the Subview.ID so that my selection behaves internally like a Picker would? Say I wanted to add an Image(…) in addition to the Text(scope.rawValue), how would I do it in order for the Button { … } label: { … } to use both views, and not each separately…?
2
0
148
Oct ’24
SubscriptionStoreView policy sheet too large
I am using the SubscriptionStoreView in my app including links to the privacy policy and terms of service. However, when clicking the links the displayed sheet is too wide, effectively cutting of the sides (including the done button). This prevents closing the sheet. Am I doing something wrong here, or is this a bug? Minimal example code: import SwiftUI import StoreKit struct SwiftUIView: View { var body: some View { SubscriptionStoreView(groupID: EntitlementManager.subscriptionGroupID) .subscriptionStorePolicyDestination(url: AppConfig.privacyPolicyURL, for: .privacyPolicy) .subscriptionStorePolicyDestination(url: AppConfig.termsOfServiceURL, for: .termsOfService) } } #Preview { SwiftUIView() } Screenshot:
1
1
166
Oct ’24
How SwiftUI Table sorting work with multiple KeyPathComparator ?
Hello everyone, I am new to the Swift and the SwiftUI. Trying to understand how sorting works on SwiftUI Table view. The following code does what I intend to do, but I am not able to understand how does it actually work with multiple key path. Need help with the answers for the questions posted below the code. // MARK: - Student Model struct Student: Codable, Identifiable { let id: String let name: String let gradeHistory: GradeHistory enum CodingKeys: String, CodingKey { case id, name case gradeHistory = "grade_history" } } // MARK: - GradeHistory Model struct GradeHistory: Codable, Identifiable{ let id: String? let semester: String let subjects: Subjects init( id: String? = UUID().uuidString, semester: String, subjects: Subjects ) { self.id = id ?? UUID().uuidString self.semester = semester self.subjects = subjects } } // MARK: - Subjects Model struct Subjects: Codable, Identifiable { let id: String? let math: Int let science: Int let english: Int let physics: Int let computer: Int let socialScience: Int init( id: String? = nil, math: Int, science: Int, english: Int, physics: Int, computer: Int, socialScience: Int ) { self.id = id ?? UUID().uuidString self.math = math self.science = science self.english = english self.physics = physics self.computer = computer self.socialScience = socialScience } enum CodingKeys: String, CodingKey { case id = "id" case math = "Math" case science = "Science" case english = "English" case physics = "Physics" case computer = "Computer" case socialScience = "Social Science" } } let _students: [Student] = [] struct StudentGradeHistoryView: View { @State var students = _students @State private var sortOrder = [KeyPathComparator(\Student.name)] var body: some View { NavigationStack { Table(of: Student.self, selection: students.selectedStudents, sortOrder: $sortOrder) { TableColumn("Index") { student in let index = (students.firstIndex( where: { $0.id == student .id }) ?? 0) Text("No. \(index + 1)") } TableColumn("Id", value: \.id) TableColumn("Name", value: \.name) .width(min: 150) TableColumn("Math") { student in Text("\(student.gradeHistory.subjects.math)") .foregroundStyle( gradeColor(for: student.gradeHistory.subjects.math) ) } .defaultVisibility(.automatic) TableColumn("Science") { student in Text("\(student.gradeHistory.subjects.science)") .foregroundStyle(gradeColor(for: student.gradeHistory.subjects.science)) } TableColumn("English") { student in Text("\(student.gradeHistory.subjects.english)") .foregroundStyle(gradeColor(for: student.gradeHistory.subjects.english)) } TableColumn("Physics") { student in Text("\(student.gradeHistory.subjects.physics)") .foregroundStyle(gradeColor(for: student.gradeHistory.subjects.physics)) } TableColumn("Computer") { student in Text("\(student.gradeHistory.subjects.computer)") .foregroundStyle(gradeColor(for: student.gradeHistory.subjects.computer)) } TableColumn("Social Science") { student in Text("\(student.gradeHistory.subjects.socialScience)") .foregroundStyle(gradeColor(for: student.gradeHistory.subjects.socialScience)) } } .onChange(of: sortOrder) { students.sort(using: sortOrder) } } } } My question is how I can use KeyPathComparator in this model to sort data with multiple comparator paths like @State private var sortOrder = [ KeyPathComparator(\Student.name), KeyPathComparator(\Subjects.math) ] It's not working in this way
1
0
92
Oct ’24
Extra Space at the Bottom of Text in Multiline TextField with Custom Font in SwiftUI
I'm encountering an issue in SwiftUI when using a custom font in a TextField with the axis property set to .vertical. Specifically, there is extra space at the bottom of the text in the TextField. This problem does not occur when the axis is set to .horizontal, nor does it occur when using the system font. Here is my code: VStack(spacing: DSConstants.Spacing.spacing16) { Text("Axis: Horizontal") TextField("", text: $text, axis: .horizontal) .font(.custom("MyCustomFont", size: 14)) .frame(minHeight: 44) .focused($editing) .padding(.horizontal, 16) .padding(.vertical, 4) .background( RoundedRectangle(cornerRadius: 16) .fill(Color.white) ) .overlay( RoundedRectangle(cornerRadius: 16) .stroke(editing ? Color.blue : Color.gray, lineWidth: 1) ) .focused($editing) Text("Axis: Vertical") TextField("", text: $text, axis: .vertical) .font(.custom("MyCustomFont", size: 14)) .frame(minHeight: 44) .focused($editing) .padding(.horizontal, 16) .padding(.vertical, 4) .background( RoundedRectangle(cornerRadius: 16) .fill(Color.white) ) .overlay( RoundedRectangle(cornerRadius: 16) .stroke(editing ? Color.blue : Color.gray, lineWidth: 1) ) .focused($editing) } Screen shot: Has anyone else encountered this issue or have any suggestions on how to resolve it?
0
0
100
Oct ’24
navigationDestination with computed properties from SwiftData queries
I have a Query in my View that brings in some data that I then filter with a few different computed properties. I then use those properties to present the data in a view. This is the view (simplified for clarity). struct FMListView: View { @Query(sort: \FMList.name) var fmLists: [FMList] private var systemTodoLists: [FMList] { fmLists.filter { $0.ownership == Ownership.system } } private var userTodoLists: [FMList] { fmLists.filter { $0.ownership == Ownership.user && $0.parentList == nil} } private var favoriteTodoLists: [FMList] { fmLists.filter { $0.isFavorite } } var body: some View { NavigationStack { List { // MARK: -- System TodoLists ForEach(systemTodoLists) { list in NavigationLink(value: list) { Text(list.name) } } Section(header: Text("Favorites").padding(.top, -24)) { ForEach(favoriteTodoLists) { list in NavigationLink(value: list) { Text(list.name) } } } // MARK: -- User TodoLists Section(header: Text("Lists").padding(.top, -24)) { ForEach(fmLists.filter { $0.ownership == Ownership.user && $0.parentList == nil}) { list in NavigationLink(value: list) { Text(list.name) } } } } .navigationDestination(for: FMList.self) { list in Text(list.name) // MARK: -- ERROR HERE Toggle(isOn: list.isFavorite) { Label("Favorite", systemImage: IconConstants.starIcon) } } } } } The challenge I have here is that I need to represent the queried data in multiple different formats (for the example, I'm just using a Text view). When I navigate to the navigationDestination I want to edit the state on a property within the model but the model in this scope isn't bindable so I can't pass it into the Toggle. I'm not sure if the issue is my use of computed properties, or if it's my not understanding binding misusing the Toggle. I'd appreciate some guidance on this use-case - allowing me to pass a bindable version of the model down the stack once filtered on the app side. On a somewhat related note - I am filtering with computed properties because I can't do this filter within the Query predicate. The following gave me a compiler error because the ownership.user wasn't a constant value. $0.ownership == Ownership.user This is what the enum looks like: enum Ownership: String, CaseIterable, Codable { case system = "SYSTEM" case user = "USER" }
3
0
193
Oct ’24
iPadOS crashes: UpdateCoalescingCollectionView is stuck in a recursive layout loop since iOS 18.0.1
Hello! Since iOS 18.0.1 I receive crash reports for iPadOS only, "Fatal error: <UpdateCoalescingCollectionView 0x30148e7c0> is stuck in a recursive layout loop. The error is not reproducible for me. However, the screen where the user did the last touch event has no CollectionView but just a ScrollView. Can it be possible that this error can happen on a View that is not visible but is on another tab of the active UITabViewController(Representable) but has a UICollectionView? Or can you see somehow from the crash report on which SwiftIUView/UIKItView this error happened? crash_report.crash
0
3
258
Oct ’24
Tap Gesture on Subview disables drag gesture on super view
I have the following two views in SwiftUI. The first view GestureTestView has a drag gesture defined on its overlay view (call it indicator view) and has the subview called ContentTestView that has tap gesture attached to it. The problem is tap gesture in ContentTestView is blocking Drag Gesture on indicator view. I have tried everything including simultaneous gestures but it doesn't seem to work as gestures are on different views. It's easy to test by simply copying and pasting the code and running the code in XCode preview. import SwiftUI struct GestureTestView: View { @State var indicatorOffset:CGFloat = 10.0 var body: some View { ContentTestView() .overlay(alignment: .leading, content: { Capsule() .fill(Color.mint.gradient) .frame(width: 8, height: 60) .offset(x: indicatorOffset ) .gesture( DragGesture(minimumDistance: 0) .onChanged({ value in indicatorOffset = min(max(0, 10 + value.translation.width), 340) }) .onEnded { value in } ) }) } } #Preview { GestureTestView() } struct ContentTestView: View { @State var isSelected = false var body: some View { HStack(spacing:0) { ForEach(0..<8) { index in Rectangle() .fill(index % 2 == 0 ? Color.blue : Color.red) .frame(width:40, height:40) } .overlay { if isSelected { RoundedRectangle(cornerRadius: 5) .stroke(.yellow, lineWidth: 3.0) } } } .onTapGesture { isSelected.toggle() } } } #Preview { ContentTestView() }
1
0
198
Oct ’24
Core Data setting issue
After 7-8 months of intense studying, I'm working on my first App. After a couple of months coding it, I saw that Swift Data wasn't cutting it, I decided to restart the project and implement Core Data. To cut to the chase, I'm using 3 models (entities) in my app. One of those entities has 2 Transformable attributes: an array of strings and an array of doubles. I've implemented a Transformer, made sure it's added to each entity, but no matter what, I'm getting this error with random Entities and Attributes. At first it referenced the entity Quote, but then it referenced the entity MoneyElement (attribute title). This is the error: autonome crashed due to an uncaught exception NSInvalidArgumentException. Reason: -[MoneyElement setTitle:]: unrecognized selector sent to instance 0x600001736c00. I'm attaching screenshots of the different entities, as well as the code for the Entity's class that has both Transformable attributes. If anyone could help me, I'd appreciate it greatly. I'm getting the error not even making a fetch request, just trying to paint a mere and humble Text("Hello, world!") in my canvas. public class Quote: NSManagedObject, Identifiable { @NSManaged public var clientName: String @NSManaged public var quoteNumber: String @NSManaged public var dateOfCreation: Date @NSManaged public var dateOfApproval: Date? @NSManaged public var dateOfCancellation: Date? @NSManaged public var ServicesProvided: [String]? @NSManaged public var servicesCost: [Double]? @NSManaged public var netAmount: Double @NSManaged public var vatTax: Int @NSManaged public var irpfTax: Int @NSManaged public var grossAmount: Double @NSManaged public var currentStatus: String } class QuoteContainer { let persistentContainer: NSPersistentContainer init(forPreview: Bool = false) { ValueTransformer.setValueTransformer(QuoteStringArrayTransformer(), forName: NSValueTransformerName("QuoteStringArrayTransformer")) ValueTransformer.setValueTransformer(QuoteDoubleArrayTransformer(), forName: NSValueTransformerName("QuoteDoubleArrayTransformer")) persistentContainer = NSPersistentContainer(name: "Models") if forPreview { persistentContainer.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null") } persistentContainer.loadPersistentStores { _, _ in} if forPreview { addMockData(moc: persistentContainer.viewContext) } } } class QuoteStringArrayTransformer: NSSecureUnarchiveFromDataTransformer { override class func transformedValueClass() -> AnyClass { return NSData.self } override func transformedValue(_ value: Any?) -> Any? { guard let array = value as? [String] else { return nil } return try? JSONEncoder().encode(array) } override func reverseTransformedValue(_ value: Any?) -> Any? { guard let data = value as? Data else { return nil } return try? JSONDecoder().decode([String].self, from: data) } } class QuoteDoubleArrayTransformer: ValueTransformer { override class func transformedValueClass() -> AnyClass { return NSData.self } override func transformedValue(_ value: Any?) -> Any? { guard let array = value as? [Double] else { return nil } return try? JSONEncoder().encode(array) } override func reverseTransformedValue(_ value: Any?) -> Any? { guard let data = value as? Data else { return nil } return try? JSONDecoder().decode([Double].self, from: data) } }
0
0
165
Oct ’24
Simulating Fn (Globe) + Arrow Key Events Ignoring Fn Modifier
I want to simulate the pressing of Fn (Globe) + Control + arrow keys combo, but I’m encountering an issue where the Fn modifier seems to be ignored, and the system behaves as if only Control + arrow keys are pressed. In macOS, the combination of Fn + Right Arrow (key code 124) is treated as End (key code 119), and even that didn’t have expected behavior. Instead of moving the window to the right edge of the screen on Sequoia, it switches to the next space, which is the default behavior for Control + Right Arrow. Demo: (I included Fn + Control + C to show that centering the window works for example.) import SwiftUI @main struct LittleKeypressDemo: App { var body: some Scene { Window("Keypress Demo", id: "keypress-demo") { ContentView() } .windowStyle(.hiddenTitleBar) .windowResizability(.contentSize) .windowBackgroundDragBehavior(.enabled) } } struct ContentView: View { var body: some View { VStack(spacing: 20) { KeyPressButton(icon: "arrowtriangle.right.fill", keyCode: 124) KeyPressButton(icon: "arrow.down.to.line", keyCode: 119) KeyPressButton(label: "C", keyCode: 8) } .padding() } } struct KeyPressButton: View { let icon: String? let label: String? let keyCode: CGKeyCode init(icon: String? = nil, label: String? = nil, keyCode: CGKeyCode) { self.icon = icon self.label = label self.keyCode = keyCode } var body: some View { Button(action: { simulateKeyPress(keyCode) }) { HStack { Image(systemName: "globe") Image(systemName: "control") if let icon = icon { Image(systemName: icon) } else if let label = label { Text(label) } } } .buttonStyle(.bordered) .controlSize(.large) } } func simulateKeyPress(_ keyCode: CGKeyCode) { let fnKey = VirtualKey(keyCode: 63, flags: .maskSecondaryFn) let controlKey = VirtualKey(keyCode: 59, flags: [.maskControl, .maskSecondaryFn]) let targetKey = VirtualKey(keyCode: keyCode, flags: [.maskControl, .maskSecondaryFn]) [fnKey, controlKey, targetKey].forEach { $0.pressAndRelease() } } struct VirtualKey { let keyCode: CGKeyCode let flags: CGEventFlags func pressAndRelease() { postKeyEvent(keyDown: true) postKeyEvent(keyDown: false) } private func postKeyEvent(keyDown: Bool) { guard let event = CGEvent(keyboardEventSource: nil, virtualKey: keyCode, keyDown: keyDown) else { return } event.flags = flags event.post(tap: .cghidEventTap) } } Expected behavior: Simulating the key combo Fn + Control + Right Arrow on macOS Sequoia should move the current window to the right half of the screen, instead of switching to the next desktop space. Questions: Is CGEventFlags.maskSecondaryFn enough to simulate the Fn key in combination with Control and the arrow keys? Are there alternative approaches or workarounds to correctly simulate this behavior? What’s the obvious thing I missing? (Btw., window management is completely irrelevant here. I’m specifically asking about simulating these key presses.) Any insights or suggestions would be greatly appreciated. Thank you.
4
2
367
Oct ’24
Slow rendering List backed by SwiftData @Query
Hello, I've a question about performance when trying to render lots of items coming from SwiftData via a @Query on a SwiftUI List. Here's my setup: // Item.swift: @Model final class Item: Identifiable { var timestamp: Date var isOptionA: Bool init() { self.timestamp = Date() self.isOptionA = Bool.random() } } // Menu.swift enum Menu: String, CaseIterable, Hashable, Identifiable { var id: String { rawValue } case optionA case optionB case all var predicate: Predicate<Item> { switch self { case .optionA: return #Predicate { $0.isOptionA } case .optionB: return #Predicate { !$0.isOptionA } case .all: return #Predicate { _ in true } } } } // SlowData.swift @main struct SlowDataApp: App { var sharedModelContainer: ModelContainer = { let schema = Schema([Item.self]) let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false) return try! ModelContainer(for: schema, configurations: [modelConfiguration]) }() var body: some Scene { WindowGroup { ContentView() } .modelContainer(sharedModelContainer) } } // ContentView.swift struct ContentView: View { @Environment(\.modelContext) private var modelContext @State var selection: Menu? = .optionA var body: some View { NavigationSplitView { List(Menu.allCases, selection: $selection) { menu in Text(menu.rawValue).tag(menu) } } detail: { DemoListView(selectedMenu: $selection) }.onAppear { // Do this just once // (0..<15_000).forEach { index in // let item = Item() // modelContext.insert(item) // } } } } // DemoListView.swift struct DemoListView: View { @Binding var selectedMenu: Menu? @Query private var items: [Item] init(selectedMenu: Binding<Menu?>) { self._selectedMenu = selectedMenu self._items = Query(filter: selectedMenu.wrappedValue?.predicate, sort: \.timestamp) } var body: some View { // Option 1: touching `items` = slow! List(items) { item in Text(item.timestamp.description) } // Option 2: Not touching `items` = fast! // List { // Text("Not accessing `items` here") // } .navigationTitle(selectedMenu?.rawValue ?? "N/A") } } When I use Option 1 on DemoListView, there's a noticeable delay on the navigation. If I use Option 2, there's none. This happens both on Debug builds and Release builds, just FYI because on Xcode 16 Debug builds seem to be slower than expected: https://indieweb.social/@curtclifton/113273571392595819 I've profiled it and the SwiftData fetches seem blazing fast, the Hang occurs when accessing the items property from the List. Is there anything I'm overlooking or it's just as fast as it can be right now?
3
3
436
Oct ’24