Post

Replies

Boosts

Views

Activity

Reply to CloudKit - How to use Configurations to properly segregate public and private data
hi Chris, i did this separation of local and cloud configurations some time ago, and as i recall, the 2 problems that needs fixin' are: you cannot have a Core Data relationship between objects in the different configurations, so you have to implement any such relationship yourself; and you must designate that your cloud-based configuration attaches itself to the cloudkit container (while the local configuration does not). the second requires a setting in the Core Data .xcdatamedeld file: tap on a configuration and check "Used with CloudKit in the Data Model Inspector. the first is very cleverly, if not secretly, handled in CoreDataFetchedProperty in that there is a FetchRequest defined that makes it easy for objects in the local configuration to find associated objects in the cloud configuration by a UUID look-up (or it may be vice-versa, i can't remember right now). that is, instead of a one-to-one relationship from A (local) to B (cloud) being defined in the Core Data model, assume that all A and B objects have been assigned UUIDs and that each object has an attribute maybe called associate containing the other object's UUID. given an A, you find the associated B by doing a fetchRequest on all Bs to find the one that matches the UUID you saved in A.associate. you do the same to find any A associated with a given B. you can do either of these directly in code, maybe by adding a computing property as an extension to each; but in CoreDataFetchedProperty they pre-define such a Fetch directly in the Core Data model that can be called directly using an aggregate/computed property with a @fetch syntax. i'm sorry i can't recall the exact syntax, but examine the pre-define Fetch and the properties of the objects carefully to find the syntax for this. hope this helps, DMG
Oct ’22
Reply to SwiftUI with escaping closures?
hi lucid, i think it a good thing to provide actions to Buttons from outside; you probably do not want to define a Button that already knows exactly what it's supposed to do when tapped, since that makes it not all that reusable. as for syntax, your ChildView2 uses an explicit initializer, so you are required to use @escaping in the parameter list. your ChildView1 uses a default or synthesized initializer, which i'm guessing is in fact recognizing that the function being passed in is @escaping. hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Oct ’22
Reply to How to save the ".onMove" rearrangement of the list in this code so it won't revert back to the original upon quit?
hi, i would first change the definition of your formulas array into a fixed dictionary to look up a navigation destination based on a string; so something like let formula: [ String : AnyView ] = [ "Unit Conversions" : AnyView(UnitConversion()), // and everything else ... ] and with this in place, your ContentView would have: @State private var names: [String] = [ "Unit Conversions", /* everything else */ ] // most other stuff as before, except change the ForEach to iterate over the names array ForEach(names) { name in NavigationLink (name, destination: formula[name]!) } this gets you to the point that you only need to save the array of strings for formula names. you will have to change the .onMove modifier now to move positions in the names array. now it's easy to save/restore the names array to retain order. Core Data seems like overkill for this (unless you already use Core Data in your app elsewhere), so i would suggest the simplest option: keep the array formula names in AppStorage and replace the @State property wrapper with @AppStorage. hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Dec ’22
Reply to Core Data relationship counts not updating in view
hi pocket, whenever you make a change to a ToDo that could affect how a ToDoList is displayed in some view (in your case, the number of uncompleted todo items?), simply add the line toDo.toDoList?.objectWillChange.send() // .toDoList is the relationship to the associated toDoList that should trigger an update in any view that holds the associated ToDoList as an @ObservedObject. hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Dec ’22
Reply to SwiftUI: reference types leaks memory when used in State property wrapper.
hi, how SwiftUI handles the initialization @State private var simple = SimpleClass() is not exactly what you expect; this SimpleClass instance is created for SwiftUI's internal use (i.e., you don't own it) and eventually space in the heap will be created for you that is a reference to it ... you are free to change that reference if you wish to something else, but SwiftUI still has ownership of what it created. when you replace what you think is the value of simple with a new instance of SimpleClass in .onAppear, you are updating the heap reference that you own to a second instance of a SimpleClass object; but SwiftUI still holds on to the SimpleClass object that it owns. your concern about "leaking memory" will eventually be taken care of by SwiftUI when ContentView goes away (remember, SwiftUI frequently discards and recreates View structs and thus does a lot of its own memory management). in your case, you only have one view at the main level and it is likely the view is never discarded; when the app quits, whatever memory SwiftUI owns will be cleaned up. so, consider the following code experiment: (1) it would help if you knew exactly when objects of type SimpleClass come and go, so i will add an id as well as an initializer. final class SimpleClass { let id = UUID() init() { print("initialize SimpleClass, id = \(id.uuidString.prefix(8))") } deinit { print("deinit SimpleClass, id = \(id.uuidString.prefix(8))") } } (2) suppose your ContentView is not the main view of the app. try this, where the main view is a list of one item, with a navigation link to open your view, which is now renamed to be LeakyView: struct ContentView: View { var body: some View { NavigationStack { List { NavigationLink(value: "LeakyView") { Text("Show LeakyView") } } .navigationDestination(for: String.self) {_ in LeakyView() } } } } struct LeakyView: View { @State private var simple = SimpleClass() init() { print("called init of LeakyView") } var body: some View { Text("Empty") .onAppear { print("on appear occurs") simple = .init() } } } (3) run the app. you'll see that when you navigate to and then back from LeakyView to the main ContentView, all SimpleClass instances will have been released. in my case, the output i received is (a) tap on navigation link. navigation occurs (yes, SwiftUI created a view struct, discarded it, then created a new one) initialize SimpleClass, id = 106EB234 called init of LeakyView deinit SimpleClass, id = 106EB234 initialize SimpleClass, id = 9646766A called init of LeakyView on appear occurs initialize SimpleClass, id = C9026337 (b) tap on Back button. even though it looks like the object with id 9646766A has been orphaned, SwiftUI will give it back when the view goes away. deinit SimpleClass, id = C9026337 deinit SimpleClass, id = 9646766A all is in order (!) hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Feb ’23
Reply to Type '()' cannot conform to 'view'
hi, what you list inside an HStack must be Views. the function viewModel.showCard() does not return a View (its signature is () -> Void). and your viewModel should not be in the business of creating Views anyway what you want is something like this for your higher-level View: ScrollView(.horizontal, showsIndicators: false){ ForEach(wallet.cards, id:\ .self) { card in CardView(card: card) .onTapGesture { viewModel.selectCard(card) } } } then add the function viewModel.selectCard to update the isSelected property of the cards it maintains in its wallet.cards array. hope that helps, DMG
Topic: Programming Languages SubTopic: Swift Tags:
Feb ’23
Reply to Update View when viewModel is modified
hi, each of TagViewPhone and WordView2 has its own WordViewModel. changing one does not change the other. you should create the WordViewModel as a @StateObject in MainView2, and make it available to the TagViewPhone and WordView2 subviews, either as a parameter (reference the model passed in as an @ObservedObject) or through the environment. should you still have updating problems ... my guess is that you will ... then you may want to explicitly precede any change to a Word or Tag by telling all associated objects (Tags associated with a Word, or Word associated a Tag) to initiate an objectWillChange.send() message. changing attributes of a Tag/Word at one end of a relationship is not seen as a change of any attributes on the other Word/Tag end of the relationship. hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Apr ’23
Reply to Core Data Plus CloudKit - Potential Issue / Question about Binary Data w/ External Storage
hi, as long as you're OK with "I will never manipulate the CloudKit data directly," then i don't see what the problem is. i doubt that the NSPersistentCloudKitContainer designers ever intended for users to be interacting directly in code with CKRecords and making an end run around what NSPersistentCloudKitContainer does for you automatically. however, that aside, i do recall reading at one point that Core Data does not necessarily use external storage just because you checked "Allows External Storage." it could be the case that Core Data made such decisions about your data at some point; if so, the CloudKit representation of what NSPersistentCloudKitContainer does for you would probably respect that decision. hope that helps, DMG
Apr ’23
Reply to Core Data Plus CloudKit - Potential Issue / Question about Binary Data w/ External Storage
hi SpaceMan, the best reference i can find on this is in the developer documentation on Reading CloudKit records for Core Data. this documents how Core Data is encoded in CloudKit. in short, String, Binary Data, and Transformable attributes can be automatically converted to external assets during serialization. it looks like this happens when you begin approaching 1 MB, but there seems to be no hard-and-fast rule. however, you can certainly work with the CKRecords directly and determine whether data is in the record or farmed out to a CKAsset, as described in the article above: "When inspecting a CloudKit record directly, check the length of the original field’s value; if it is zero, look in the asset field." hope that helps, DMG
Apr ’23
Reply to SwiftUI Core Data crash when deleting an object
hi, in many cases when you delete the Core Data object, SwiftUI may try to execute the body property of a view in which you reference the object as @ObservedObject. i recall checking the .isDeleted property and it did not always seem to return the right value ... but something that is true about the deleted object will be that all its attributes will be zeroed out. so, all optional properties will be nil, all numeric values will be 0, a date will be back in 1970 somewhere, all relationships will be nil, and so forth. if you have nil-coalesced all properties of the Core Data object, then everything should pretty much just work. for example: Text(myObject.name ?? "No Name") will not crash your app, but Text(myObject.name!) will certainly crash. i usually add an extension to a Core Data object so that every property is nil-coalesced. e.g., if i have a name_ attribute defined in the Core Data model, then i add var name: String { get { name_ ?? "No Name" } set { name_ = newValue } } as an extension to the entity, and now i can freely write myObject.name throughout SwiftUI views and not have to continually nil-coalesce everything when i use it. you might want to check out my "build and fail in public" ShoppingList16 app, which is where i found this problem back in iOS 13, and i have not had crashes with this strategy after finding out what was happening. there's plenty of commentary in the source code on this very point. hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Apr ’23
Reply to Swift - Map two elements from an array to a new array
hi, the expression allClosingValues.map { [$0.timeStamp! , $0.vooClose] } results in something that would have data looking something like [ [a date, a double], [a date, a double], [a date, a double] , ... ] i.e., where each element of the array is a two-element array of a date and a double, which has type [Any], and so the expression's result has type [[Any]]. however, you have defined closingValues as a dictionary of type [Date:Double], with keys being dates and values being doubles. that explains the error message. if you're happy with a result of 2-tuples, where the result is more like [ (a date, a double), (a date, a double), (a date, a double), ... ] then you could use closingValues = allClosingValues.map { ($0.timeStamp! , $0.vooClose) } where you define var closingValues: [ (Date, Double) ] to print out such a result, this should work: for closingValue in closingValues { print(closingValue.0, closingValue.1) } if you really do want closingValues to be a dictionary, let us know. hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Apr ’23
Reply to SwiftData Aggregation
hi, if you only need to count people within a certain age range, provide a predicate and use .fetchCount, rather than using .fetch and counting what comes back. no records are pulled for this and the operation should be pretty speedy. if you need to average out the ages of all people, you can specify the .propertiesToFetch in the FetchDescriptor to return only the age property values (not whole records) and then add and divide. at least that's what the documentation suggests right now (i am looking at beta 7, and Core Data already supports these). hope that helps, DMG
Aug ’23
Reply to SwiftData - What is Best Practice for returning an object from a sheet
hi Richard, i'll answer this from the Core Data perspective, where a list is driven with a @FetchRequest. from all that i've read, it should work the same with SwiftData, where a list is driven by @Query. my simple answer is: do nothing. in your "Add New Object view", the outcomes are: Cancel = dismiss and do nothing. Save = Create and save a new object to Core Data (SwiftData) and then dismiss. but do nothing else! the @FetchRequest (@Query) in your list view will pick up that a new object has been added, and redraw the list. if your list view wanted to use what was the new object created in your list view, then i would have the "Add New Object view" take a closure as a parameter with signature (NewObject) -> Void that is defined in your list view, and have the save routine invoke that closure. hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Aug ’23
Reply to List with subsections and deletable Elements.
hi, when the delete function is called, the indices handed to the delete function are relative to the array indices in the section where the .onDelete modifier is attached ... for example, splitArray(schueler)[3] has chunkSize (or possibly fewer) elements with indices in the range 0 ... chunkSize - 1 ; yet your 'delete function removes elements in the main schueler array using those indices directly, without regard to which section triggered the deletion call. if you can pass the section/group number information along to your delete function, you can first adjust the incoming indices by section. for example, in the third group with a chunkSize of 7, adjust the incoming indices 0 ... 6 to instead be 14 ... 20, and then delete from the main schueler array using the adjusted indices. first, make a simple syntax modification to the .onDelete invocations in each section, so that your delete function will also receive section/group information. for example, in the third section: Section("Group 3") { ForEach(splitArray(schueler)[2], id: \.self) { SchuelerName in Text(SchuelerName) } .onDelete { indexSet in delete(indexSet: indexSet, inGroup: 3) } } update your delete function's signature to handle a second parameter, and begin by adjusting the incoming indices accordingly to determine matching indices in the main schueler array. then do the appropriate deletions. func indexSet in delete(indexSet: IndexSet, inGroup group: Int) { // this is your code to write ... i would think indices in the indexSet would have to be // offset by (group - 1) * chunkSize first before doing any deletions. } hope that helps, DMG
Topic: Programming Languages SubTopic: Swift Tags:
Sep ’23
Reply to CloudKit - How to use Configurations to properly segregate public and private data
hi Chris, i did this separation of local and cloud configurations some time ago, and as i recall, the 2 problems that needs fixin' are: you cannot have a Core Data relationship between objects in the different configurations, so you have to implement any such relationship yourself; and you must designate that your cloud-based configuration attaches itself to the cloudkit container (while the local configuration does not). the second requires a setting in the Core Data .xcdatamedeld file: tap on a configuration and check "Used with CloudKit in the Data Model Inspector. the first is very cleverly, if not secretly, handled in CoreDataFetchedProperty in that there is a FetchRequest defined that makes it easy for objects in the local configuration to find associated objects in the cloud configuration by a UUID look-up (or it may be vice-versa, i can't remember right now). that is, instead of a one-to-one relationship from A (local) to B (cloud) being defined in the Core Data model, assume that all A and B objects have been assigned UUIDs and that each object has an attribute maybe called associate containing the other object's UUID. given an A, you find the associated B by doing a fetchRequest on all Bs to find the one that matches the UUID you saved in A.associate. you do the same to find any A associated with a given B. you can do either of these directly in code, maybe by adding a computing property as an extension to each; but in CoreDataFetchedProperty they pre-define such a Fetch directly in the Core Data model that can be called directly using an aggregate/computed property with a @fetch syntax. i'm sorry i can't recall the exact syntax, but examine the pre-define Fetch and the properties of the objects carefully to find the syntax for this. hope this helps, DMG
Replies
Boosts
Views
Activity
Oct ’22
Reply to SwiftUI with escaping closures?
hi lucid, i think it a good thing to provide actions to Buttons from outside; you probably do not want to define a Button that already knows exactly what it's supposed to do when tapped, since that makes it not all that reusable. as for syntax, your ChildView2 uses an explicit initializer, so you are required to use @escaping in the parameter list. your ChildView1 uses a default or synthesized initializer, which i'm guessing is in fact recognizing that the function being passed in is @escaping. hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Oct ’22
Reply to How to save the ".onMove" rearrangement of the list in this code so it won't revert back to the original upon quit?
hi, i would first change the definition of your formulas array into a fixed dictionary to look up a navigation destination based on a string; so something like let formula: [ String : AnyView ] = [ "Unit Conversions" : AnyView(UnitConversion()), // and everything else ... ] and with this in place, your ContentView would have: @State private var names: [String] = [ "Unit Conversions", /* everything else */ ] // most other stuff as before, except change the ForEach to iterate over the names array ForEach(names) { name in NavigationLink (name, destination: formula[name]!) } this gets you to the point that you only need to save the array of strings for formula names. you will have to change the .onMove modifier now to move positions in the names array. now it's easy to save/restore the names array to retain order. Core Data seems like overkill for this (unless you already use Core Data in your app elsewhere), so i would suggest the simplest option: keep the array formula names in AppStorage and replace the @State property wrapper with @AppStorage. hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Dec ’22
Reply to Core Data relationship counts not updating in view
hi pocket, whenever you make a change to a ToDo that could affect how a ToDoList is displayed in some view (in your case, the number of uncompleted todo items?), simply add the line toDo.toDoList?.objectWillChange.send() // .toDoList is the relationship to the associated toDoList that should trigger an update in any view that holds the associated ToDoList as an @ObservedObject. hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Dec ’22
Reply to SwiftUI: reference types leaks memory when used in State property wrapper.
hi, how SwiftUI handles the initialization @State private var simple = SimpleClass() is not exactly what you expect; this SimpleClass instance is created for SwiftUI's internal use (i.e., you don't own it) and eventually space in the heap will be created for you that is a reference to it ... you are free to change that reference if you wish to something else, but SwiftUI still has ownership of what it created. when you replace what you think is the value of simple with a new instance of SimpleClass in .onAppear, you are updating the heap reference that you own to a second instance of a SimpleClass object; but SwiftUI still holds on to the SimpleClass object that it owns. your concern about "leaking memory" will eventually be taken care of by SwiftUI when ContentView goes away (remember, SwiftUI frequently discards and recreates View structs and thus does a lot of its own memory management). in your case, you only have one view at the main level and it is likely the view is never discarded; when the app quits, whatever memory SwiftUI owns will be cleaned up. so, consider the following code experiment: (1) it would help if you knew exactly when objects of type SimpleClass come and go, so i will add an id as well as an initializer. final class SimpleClass { let id = UUID() init() { print("initialize SimpleClass, id = \(id.uuidString.prefix(8))") } deinit { print("deinit SimpleClass, id = \(id.uuidString.prefix(8))") } } (2) suppose your ContentView is not the main view of the app. try this, where the main view is a list of one item, with a navigation link to open your view, which is now renamed to be LeakyView: struct ContentView: View { var body: some View { NavigationStack { List { NavigationLink(value: "LeakyView") { Text("Show LeakyView") } } .navigationDestination(for: String.self) {_ in LeakyView() } } } } struct LeakyView: View { @State private var simple = SimpleClass() init() { print("called init of LeakyView") } var body: some View { Text("Empty") .onAppear { print("on appear occurs") simple = .init() } } } (3) run the app. you'll see that when you navigate to and then back from LeakyView to the main ContentView, all SimpleClass instances will have been released. in my case, the output i received is (a) tap on navigation link. navigation occurs (yes, SwiftUI created a view struct, discarded it, then created a new one) initialize SimpleClass, id = 106EB234 called init of LeakyView deinit SimpleClass, id = 106EB234 initialize SimpleClass, id = 9646766A called init of LeakyView on appear occurs initialize SimpleClass, id = C9026337 (b) tap on Back button. even though it looks like the object with id 9646766A has been orphaned, SwiftUI will give it back when the view goes away. deinit SimpleClass, id = C9026337 deinit SimpleClass, id = 9646766A all is in order (!) hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Feb ’23
Reply to Type '()' cannot conform to 'view'
hi, what you list inside an HStack must be Views. the function viewModel.showCard() does not return a View (its signature is () -> Void). and your viewModel should not be in the business of creating Views anyway what you want is something like this for your higher-level View: ScrollView(.horizontal, showsIndicators: false){ ForEach(wallet.cards, id:\ .self) { card in CardView(card: card) .onTapGesture { viewModel.selectCard(card) } } } then add the function viewModel.selectCard to update the isSelected property of the cards it maintains in its wallet.cards array. hope that helps, DMG
Topic: Programming Languages SubTopic: Swift Tags:
Replies
Boosts
Views
Activity
Feb ’23
Reply to Update View when viewModel is modified
hi, each of TagViewPhone and WordView2 has its own WordViewModel. changing one does not change the other. you should create the WordViewModel as a @StateObject in MainView2, and make it available to the TagViewPhone and WordView2 subviews, either as a parameter (reference the model passed in as an @ObservedObject) or through the environment. should you still have updating problems ... my guess is that you will ... then you may want to explicitly precede any change to a Word or Tag by telling all associated objects (Tags associated with a Word, or Word associated a Tag) to initiate an objectWillChange.send() message. changing attributes of a Tag/Word at one end of a relationship is not seen as a change of any attributes on the other Word/Tag end of the relationship. hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Apr ’23
Reply to Core Data Plus CloudKit - Potential Issue / Question about Binary Data w/ External Storage
hi, as long as you're OK with "I will never manipulate the CloudKit data directly," then i don't see what the problem is. i doubt that the NSPersistentCloudKitContainer designers ever intended for users to be interacting directly in code with CKRecords and making an end run around what NSPersistentCloudKitContainer does for you automatically. however, that aside, i do recall reading at one point that Core Data does not necessarily use external storage just because you checked "Allows External Storage." it could be the case that Core Data made such decisions about your data at some point; if so, the CloudKit representation of what NSPersistentCloudKitContainer does for you would probably respect that decision. hope that helps, DMG
Replies
Boosts
Views
Activity
Apr ’23
Reply to Core Data Plus CloudKit - Potential Issue / Question about Binary Data w/ External Storage
hi SpaceMan, the best reference i can find on this is in the developer documentation on Reading CloudKit records for Core Data. this documents how Core Data is encoded in CloudKit. in short, String, Binary Data, and Transformable attributes can be automatically converted to external assets during serialization. it looks like this happens when you begin approaching 1 MB, but there seems to be no hard-and-fast rule. however, you can certainly work with the CKRecords directly and determine whether data is in the record or farmed out to a CKAsset, as described in the article above: "When inspecting a CloudKit record directly, check the length of the original field’s value; if it is zero, look in the asset field." hope that helps, DMG
Replies
Boosts
Views
Activity
Apr ’23
Reply to SwiftUI Core Data crash when deleting an object
hi, in many cases when you delete the Core Data object, SwiftUI may try to execute the body property of a view in which you reference the object as @ObservedObject. i recall checking the .isDeleted property and it did not always seem to return the right value ... but something that is true about the deleted object will be that all its attributes will be zeroed out. so, all optional properties will be nil, all numeric values will be 0, a date will be back in 1970 somewhere, all relationships will be nil, and so forth. if you have nil-coalesced all properties of the Core Data object, then everything should pretty much just work. for example: Text(myObject.name ?? "No Name") will not crash your app, but Text(myObject.name!) will certainly crash. i usually add an extension to a Core Data object so that every property is nil-coalesced. e.g., if i have a name_ attribute defined in the Core Data model, then i add var name: String { get { name_ ?? "No Name" } set { name_ = newValue } } as an extension to the entity, and now i can freely write myObject.name throughout SwiftUI views and not have to continually nil-coalesce everything when i use it. you might want to check out my "build and fail in public" ShoppingList16 app, which is where i found this problem back in iOS 13, and i have not had crashes with this strategy after finding out what was happening. there's plenty of commentary in the source code on this very point. hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Apr ’23
Reply to Swift - Map two elements from an array to a new array
hi, the expression allClosingValues.map { [$0.timeStamp! , $0.vooClose] } results in something that would have data looking something like [ [a date, a double], [a date, a double], [a date, a double] , ... ] i.e., where each element of the array is a two-element array of a date and a double, which has type [Any], and so the expression's result has type [[Any]]. however, you have defined closingValues as a dictionary of type [Date:Double], with keys being dates and values being doubles. that explains the error message. if you're happy with a result of 2-tuples, where the result is more like [ (a date, a double), (a date, a double), (a date, a double), ... ] then you could use closingValues = allClosingValues.map { ($0.timeStamp! , $0.vooClose) } where you define var closingValues: [ (Date, Double) ] to print out such a result, this should work: for closingValue in closingValues { print(closingValue.0, closingValue.1) } if you really do want closingValues to be a dictionary, let us know. hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Apr ’23
Reply to confirmationDialog re-appears for one second while closing
same behavior here: console message is "Presenting view controller <SwiftUI.PlatformAlertController: 0x1059dfe00> from detached view controller <TtGC7SwiftUI32NavigationStackHostingControllerVS_7AnyView: 0x10902da00> is discouraged."
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Jul ’23
Reply to SwiftData Aggregation
hi, if you only need to count people within a certain age range, provide a predicate and use .fetchCount, rather than using .fetch and counting what comes back. no records are pulled for this and the operation should be pretty speedy. if you need to average out the ages of all people, you can specify the .propertiesToFetch in the FetchDescriptor to return only the age property values (not whole records) and then add and divide. at least that's what the documentation suggests right now (i am looking at beta 7, and Core Data already supports these). hope that helps, DMG
Replies
Boosts
Views
Activity
Aug ’23
Reply to SwiftData - What is Best Practice for returning an object from a sheet
hi Richard, i'll answer this from the Core Data perspective, where a list is driven with a @FetchRequest. from all that i've read, it should work the same with SwiftData, where a list is driven by @Query. my simple answer is: do nothing. in your "Add New Object view", the outcomes are: Cancel = dismiss and do nothing. Save = Create and save a new object to Core Data (SwiftData) and then dismiss. but do nothing else! the @FetchRequest (@Query) in your list view will pick up that a new object has been added, and redraw the list. if your list view wanted to use what was the new object created in your list view, then i would have the "Add New Object view" take a closure as a parameter with signature (NewObject) -> Void that is defined in your list view, and have the save routine invoke that closure. hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Aug ’23
Reply to List with subsections and deletable Elements.
hi, when the delete function is called, the indices handed to the delete function are relative to the array indices in the section where the .onDelete modifier is attached ... for example, splitArray(schueler)[3] has chunkSize (or possibly fewer) elements with indices in the range 0 ... chunkSize - 1 ; yet your 'delete function removes elements in the main schueler array using those indices directly, without regard to which section triggered the deletion call. if you can pass the section/group number information along to your delete function, you can first adjust the incoming indices by section. for example, in the third group with a chunkSize of 7, adjust the incoming indices 0 ... 6 to instead be 14 ... 20, and then delete from the main schueler array using the adjusted indices. first, make a simple syntax modification to the .onDelete invocations in each section, so that your delete function will also receive section/group information. for example, in the third section: Section("Group 3") { ForEach(splitArray(schueler)[2], id: \.self) { SchuelerName in Text(SchuelerName) } .onDelete { indexSet in delete(indexSet: indexSet, inGroup: 3) } } update your delete function's signature to handle a second parameter, and begin by adjusting the incoming indices accordingly to determine matching indices in the main schueler array. then do the appropriate deletions. func indexSet in delete(indexSet: IndexSet, inGroup group: Int) { // this is your code to write ... i would think indices in the indexSet would have to be // offset by (group - 1) * chunkSize first before doing any deletions. } hope that helps, DMG
Topic: Programming Languages SubTopic: Swift Tags:
Replies
Boosts
Views
Activity
Sep ’23