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.
SwiftUI
RSS for tagProvide 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
Does anyone know any workaround for this? FB15522331
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
}
}
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)
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()
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
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)
}
}
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?
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.
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…?
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:
Can we access a Vision pro's spatial persona in application's view without using SharePlay or group activity like any other 3d Avatar?
I want to use that persona in app and without live rendering I just want to pass some voice commands like Avatar is speaking.
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
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?
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"
}
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
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()
}
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)
}
}
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.
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?