Posts

Post not yet marked as solved
0 Replies
786 Views
I have a Multiplatform app for iOS and macOS targets written 100% SwiftUI. I'd prefer to keep it that way, although will consider view representable options. Its a Core Data driven app, also implementing NSPersistentCloudKitContainer, I have a three column view, the first a List with style .sidebar, the second a List of items for an Entity in my Core Data model object graph, the third a detail view for the selected item in the second column List. I have begun to implement @SceneStorage to persist selected rows/cells in the lists (and sidebar), which works very well. However, if a selected row or cell is half way down the list => off screen, then the user cannot see the selection and for some reason the detail view does not show the details of the selected item, until the user manually scrolls down to the item in the list. When the selected item is revealed on screen via the manual scroll action, it is shown as selected item in the list and the detail data is only then populated. I want to be able to programmatically scroll to the selected row/cell when that Entity List is chosen (via the sidebar list). I'm struggling to make this work... I suspect because scrollTo(_:anchor:) takes as its first argument an ID. From the Apple Documentation... func scrollTo<ID>(_ id: ID, anchor: UnitPoint? = nil) where ID : Hashable Unless I'm mistaken, @SceneStorage does not accept an ObjectIdentifier ... it takes the same types as any normal property list because as far as I can tell that is the underlying technology upon when it is based (i.e. UserDefaults). So here's my efforts to date which I might add include trawling through blogs and Q&A sites for a solution. Note: meal.uuID is an attribute of the meal instance of type UUID. struct MealsList: View {     @SectionedFetchRequest var meals: SectionedFetchResults<String, Meal> ... @SceneStorage("Meals.selected.meal") private var selectedMeal: String? ...    var body: some View {         ZStack(alignment: .bottom) {             ScrollViewReader { proxy in                 List() {                     ForEach(meals) { section in                         Section(header: Text(section.id)) {                             ForEach(section) { meal in                                 NavigationLink(destination: MealDetail(...) tag: meal.uuID!.uuidString, selection: $selectedMeal                                 ) {                                     MealRow(meal: meal, selected: meal.uuID?.uuidString == selectedMeal)                                 }                                 .swipeActions(edge: .leading) {...}                                 .swipeActions(edge: .trailing) {...}                             }                         }                     }                 }                 .onAppear() {                     proxy.scrollTo(selectedMeal, anchor: .center) // also tried...                     proxy.scrollTo(Optional(selectedMeal), anchor: .center)                 }             }             ListFooter(...)         }         .searchable(text: query) // query not shown in this sample code } } I've attempted to place the .onAppear modifier at every level of the hierarchy without effect. Any thoughts or hints or suggestions on how I might make this work?
Posted Last updated
.
Post not yet marked as solved
3 Replies
1.3k Views
I receive the following error in terminal in my macOS and iOS targets that crashes a universal app written entirely in swiftUI. [General] -[NSAlert runModal] may not be invoked inside of transaction begin/commit pair, or inside of transaction commit (usually this means it was invoked inside of a view's -drawRect: method.) App structure is Sidebar Menu + Master List + Details using Core Data for persistence and Cloudkit NSPersistentCloudKitContainer for backup / mirroring. There seems to be a lot of activity prior to the crash relating to IMKInputSession CFRunLoopObserver. The crash seems to be associated with a Picker view within the detail view and whether it is "First Responder" at the time another item in the list is selected or a new item is added to the list (from the toolbar). Apple has suggested that... It seems that the app is presenting an alert in response to SwiftUI updating views. That use of -presentError: should be deferred outside of that immediate update (e.g. adding an observer block to the main run loop to present it on the next turn) ... however I have no alerts in the views that crash. Has anyone else experienced this and if so do you have any suggestions on what worked for you?
Posted Last updated
.
Post marked as solved
1 Replies
1.3k Views
Background Core Data driven app, successfully using NSPersistentCloudKitContainer for some time. App is written 100% SwiftUI, currently targeting iOS and macOS targets. Development only, no production release yet. Error... ... Fatal error: Unresolved error Error Domain=NSCocoaErrorDomain Code=134110 "An error occurred during persistent store migration." ... reason=Cannot migrate store in-place: CloudKit integration forbids renaming 'foodServes' to 'foodPortions'. Older devices can't process the new relationships. An unusual problem for me... the renaming occurred between version 7 and version 8 of the Core Data model and this is version 13. So if I revert back to version 12, there is no issue. It is only when I add the new Entity in model version 13 that the error occurs. The new entity incudes a relationship back to two other existing entities, but not the Food entity that contains the foodServes -> foodPortions renamingID. To be clear, the error relates to a renamingID that was implemented in the transition to model version 8. Its only now that I have added a new entity in model version 13 that Xcode is complaining. I'm not in production, but I still don't want to mess up my extensive test data set and frankly I feel like its good practice to solve these problems as if I were in production. So what do I do now? Any suggestions?
Posted Last updated
.
Post not yet marked as solved
1 Replies
1.1k Views
I am using the new SwiftUI Table() structure available for macOS. This structure takes a selection of multiple rows as a Set<Object.ID> and can be stored in a state property wrapper like so... @State private var selectedPeople = Set<Person.ID>() (per the example in the Apple documentation) Table() doesn't take any other type of identifier (that I am aware of), so I am constrained to use the ObjectIdentifier unique identifier. I am using Table() to present a list of NSManagedObjects. These NSManagedObjects are sourced from a Core Data Entity relationship property, in this case via a @FetchRequest. I want to be able to add new instances of the entity and also delete existing instances of the entity. I have worked out how to add a new instance - this is relatively easy. What I am struggling to work out is how to delete an NSManagedObject from the Table() by using the Object.ID that is used to track row selection. I have attempted this...     @State private var tableSelection = Set<Action.ID>() ... for actionID in tableSelection { let context = event.managedObjectContext let actionToDelete = context?.object(with: actionID) print(actionToDelete) context?.delete(actionToDelete) } but of course I have a type mismatch here and the compiler complains... Cannot convert value of type 'Action.ID' (aka 'ObjectIdentifier') to expected argument type 'NSManagedObjectID' So how I do grab a reference to the selected NSManagedObject from the set of Action.ID?
Posted Last updated
.
Post not yet marked as solved
4 Replies
3.0k Views
I'm no enum expert but I enjoy playing around with them to make my project code easier to read and type safe. I've written a simple enum to track the selected type (a To-Many relationship property) for a CoreData entity and provide some formatting. enum Taxon {     case common(name: String)     case genus(name: String)     case species(name: String)     case subspecies(name: String)     case group(name: String)     case cultivar(name: String)     case variety(name: String)     case extended(name: String)     var typeName: String {         switch self {         case .common:       return "Common"         case .genus:        return "Genus"         case .species:      return "Species"         case .subspecies:   return "Subspecies"         case .group:        return "Group"         case .cultivar:     return "Cultivar"         case .variety:      return "Variety"         case .extended:     return "Taxonomny"         }     }     var formatted: String {         switch self {         case .common(let name):       return name.capitalized         case .genus(let name):        return name.capitalized         case .species(let name):      return name.lowercased()         case .subspecies(let name):   return String(format: "ssp. %@", name)         case .group(let name):        return String(format: "(%@ Group)", name)         case .cultivar(let name):     return String(format: "cv. %@", name)         case .variety(let name):      return String(format: "var. %@", name)         case .extended(let name):     return name.capitalized         }     } I could make the enum an associated type String but then I lose the ability to include arguments... Error message - Enum with raw type cannot have cases with arguments I can parse a Set of entity instance name as follows and this provides a perfectly formatted string, based on the var .formatted in the enum Taxon.     for name in setSorted {         let nameComp: String = name.component!         let nameType: String = name.type!.name!         var nameFormatted = String()         switch nameType {         case Taxon.common(name: nameType).typeName:     nameFormatted = Taxon.common(name: nameComp).formatted         case Taxon.genus(name: nameType).typeName:      nameFormatted = Taxon.genus(name: nameComp).formatted         case Taxon.species(name: nameType).typeName:    nameFormatted = Taxon.species(name: nameComp).formatted         case Taxon.subspecies(name: nameType).typeName: nameFormatted = Taxon.subspecies(name: nameComp).formatted         case Taxon.group(name: nameType).typeName:      nameFormatted = Taxon.group(name: nameComp).formatted         case Taxon.cultivar(name: nameType).typeName:   nameFormatted = Taxon.cultivar(name: nameComp).formatted         case Taxon.variety(name: nameType).typeName:    nameFormatted = Taxon.variety(name: nameComp).formatted         case Taxon.extended(name: nameType).typeName:   nameFormatted = Taxon.extended(name: nameComp).formatted         default: nameFormatted = "E R R O R : Taxon : switch"         }         stringNames.append(nameFormatted)         if setSorted.last != name {             stringNames.append("\(stringBetween)")         }      } However seems clunky to me. Surely there is more concise / better code? Elsewhere I have whittled this type of enumeration down to a one liner (to be clear, without the switch statement), but those one liners were based upon an enum with an associated type and also did not have (arguments). For example... let calendarComponent = EntityDate(rawValue: format)?.calendarComponent (where EntityDate is the enum of type NSNumber and format is the var of type NSNumber, inserted by a func and used to identify the appropriate calendarComponent.) So if I attempt a line code like this... let test = Taxon(rawValue: nameType) I am provided with a compiler message... 'Taxon' cannot be constructed because it has no accessible initializers I've attempted a few ways to prepare an initialiser by copying patterns I have for other enum but nothing has worked so far and I'd prefer to keep the enum pure (of its own type) so that I can include the argument (name: String). I've wasted a little too much time on this frankly unnecessary obsession, so I am wondering what I am missing?
Posted Last updated
.
Post not yet marked as solved
2 Replies
1.6k Views
I am working on a couple of Multiplatform apps that use a very similar 3 column layout - sidebar menu (or tabs for sizeClassHorizontal == .compact), with a master list under each menu option and detail view based upon master list selection. The apps use Core Data framework and NSPersistentCloudKitContainer for backup and syncing across a user's devices. The apps use Codegen = Class Definition and I write extensions for each entity to prepare convenience methods, properties, comply with generic protocol conformance. I am learning how to retrofit sectioned fetch requests into each master List. Generally this is straightforward and I'm really happy with the result. However, one particular master list is based upon an hierarchical data structure and I have investigated using the children: parameter in List to successfully create an hierarchical list. So to be clear, the following code is based upon @FetchRequest var gardens: FetchedResults<Garden> (not a sectioned fetch request) and works well... extension Garden {     var arrayGardenChildren: [Garden]? {         let setGardenChildren = self.children as? Set<Garden> ?? []         return setGardenChildren.sorted(by: { $0.name ?? " NO NAME" < $1.name ?? " NO NAME" })     } } and @FetchRequest(sortDescriptors: [ SortDescriptor(\.name, order: .forward), SortDescriptor(\.timeStampCreated, order: .reverse)           ],           animation: .default ) var gardens: FetchedResults<Garden> and private func arrayGardens() -> [Garden] {     return Array(gardens) } and List(arrayGardens(), children: \.arrayGardenChildren) { garden in NavigationLink(destination: GardenDetail(...),                    tag: garden.uuID!.uuidString,                    selection: $appData.selectedGardens ) { GardenRow(garden: garden,                   selected: garden.uuID?.uuidString == appData.selectedGardens) } } ... perhaps obviously from this code, I am forced to convert the FetchedResults to an Array and the entity's children from an NSSet to a sorted Array - no big deal - a little extra code but it works fine and I'm happy. On first impressions, the lists look great on macOS and iOS, however there are a few downsides to this implementation: expansion state cannot be set as @SceneStorage or therefore controlled as per the sidebar menu in the Apple Developer "Garden" sample app for the WWDC21 code-along "Building a Great Mac App with SwiftUI"; for both iOS and macOS, there are no section headers, which are my preference when the list becomes longer; for both iOS and macOS, the bottom level items in each hierarchy tree include a disclosure chevron despite that those items have no children; on iOS, due to the navigation link for the detail view, there are double chevrons at the trailing edge of each row... the inner chevron is the link to the detail view and the outer chevron is the disclosure indicator. This appearance is not ideal and there are a few of ways I can adjust the UI to suit, but include the raw / unedited constraint here for clarity. So I have continued experimenting with a sectioned fetch request. As a starting point, the following code works well... extension Garden {     @objc var sectionNameParentNil: String {         return self.name?.filter({ _ in self.parent == nil }) ?? "NO NAME"     } } where each instance of the entity Garden has two relationships that allow the parent child arrangement, a To-One relationship named parent and a To-Many relationship named children (both with destination = Garden). ...and... SectionedFetchRequest(sectionIdentifier: \.sectionNameParentNil, sortDescriptors: [ SortDescriptor(\.name, order: .forward), SortDescriptor(\.timeStampCreated, order: .reverse) ], animation: .default) ) var gardens: SectionedFetchResults<String, Garden> ...and... List { ForEach(gardens) { section in Section(header: Text(section.id)) { ForEach(section) { garden in NavigationLink(destination: GardenDetail(...),                      tag: garden.uuID!.uuidString,                      selection: $appData.selectedGardens                 ) {                     GardenRow(garden: garden,                         selected: garden.uuID?.uuidString == appData.selectedGardens)                 }         } } } } This is a good start and works well but only presents the top level elements of the hierarchical data set (where parent = nil). I want to be able to include all children for each top level "Garden" and also mimic the expandable / collapsable function demonstrated in the above noted sample app. I've done some googling and read a few articles, including "Displaying recursive data using OutlineGroup in SwiftUI" by one of my favourite SwiftUI bloggers. Based upon my research and reading, I begun by replacing the second ForEach line in the above block with... OutlineGroup(section, children: \Garden.children ?? nil) { garden in The compiler complains "Cannot convert value of type 'ReferenceWritableKeyPath<Garden, NSSet?>?' to expected argument type 'KeyPath<SectionedFetchResults<String, Garden>.Section.Element, SectionedFetchResults<String, Garden>.Element?>' (aka 'KeyPath<Garden, Optional<SectionedFetchResults<String, Garden>.Section>>')". My compiler interpretation skills are intermediate at best, but this is beyond me. I've attempted a few different combinations to attempt to provide a suitable type, but all my attempts to date have caused compiler errors that I am not able to resolve. I'll try to include a few more below. OutlineGroup(section, children: \.arrayGardenChildren) { garden in causes the following compiler error Key path value type '[Garden]?' cannot be converted to contextual type 'SectionedFetchResults<String, Garden>.Element?' (aka 'Optional<SectionedFetchResults<String, Garden>.Section>') So from these messages I somehow need to provide a key path for SectionedFetchResults<String, Garden>.Element. The question for me is how? Any suggestions please?
Posted Last updated
.
Post not yet marked as solved
2 Replies
1.2k Views
My project is a universal app with iOS 15 and macOS 12 targets, to attempt to take advantage of latest technologies, including SwiftUI and Table. I let Xcode take care of the CodeGen by selecting type "Class Definition" and then write Extensions for custom properties. I have an entity named Event with a class name PTG_Event. Each Event can have a number of actions and so each Event also has a one-to-many relationship with Action (class PTG_Action). I am attempting to use Table to display the actions for each event... but this doesn't work... struct ActionTable: View {     @ObservedObject var event: PTG_Event     @FetchRequest(entity: PTG_Action.entity(),                   sortDescriptors: []     ) var eventActions: FetchedResults<PTG_Action>     @State var sortOrder: [SortDescriptor<PTG_Action>] = [         .init(\.dateCommences, order: SortOrder.forward)     ]     var body: some View {         let events = eventActions.filter { $0.event == event }         Text("Action Table")         Table(events, sortOrder: $sortOrder) {             TableColumn("Ref", value: \.reference)             { action in                 Text(action.reference ?? "NO REF")             }             TableColumn("Date", value: \.dateCommences)             { action in                 Text(action.dateCommences?.formatted(date: .abbreviated, time: .omitted) ?? "NO DATE")             }         }     } } I have attempted many variations on this. Any suggestions?
Posted Last updated
.
Post marked as solved
2 Replies
1.4k Views
I am learning how to implement the new @SectionedFetchRequest with my Core Data object graph. Here is my call...     @SectionedFetchRequest(         sectionIdentifier: \.sectionDay,         sortDescriptors: [             SortDescriptor(\.dateCommences, order: .reverse),             SortDescriptor(\.timeStampCreated, order: .reverse)],         animation: .default)     private var events: SectionedFetchResults<String, PTG_Event> where PTG_Event is the Core Data entity of results that I am expecting to be returned, sectionDay is a convenience method that is prepared in an extension to PTG_Event. I have a user setting to display archived records (or not) using the entity attribute isArchived and I am attempting to take advantage of the @AppStorage wrapper as follows...     @AppStorage("preference_displayArchived") var kDisplayArchived = true I cannot include a predicate in my sectioned fetch request, e.g.         predicate: NSPredicate(format: "isArchived == %@", NSNumber(booleanLiteral: kDisplayArchived)), ... because I receive the error ... Cannot use instance member 'kDisplayArchived' within property initializer; property initializers run before 'self' is available I understand this, but how do I create a dynamic reference to the app storage wrapper? I am determined to figure out an easy method to use the user setting value preference_displayArchived in the sectioned fetch request, so I have also attempted to hack a solution together using the method shown in #wwdc21-10017 for preparing a query for the .searchable modifier, but have been so far unsuccessful in figuring out how to squeeze that into my List code.     @State private var displayArchived = false     var queryArchived: Binding<Bool> {         Binding {             displayArchived         } set: { newValue in             displayArchived = newValue             events.nsPredicate = newValue == false ? nil : NSPredicate(format: "isArchived == %@", NSNumber(booleanLiteral: kDisplayArchived))         }     } Any suggestions?
Posted Last updated
.
Post marked as solved
1 Replies
1k Views
I am using a @SectionedFetchRequest with some success. This sectioned fetch request feeds data to a List(). I want to include a footer to the list that provides a count of the managed objects returned from the sectioned fetch request. Previously I have used .count. This still works but only returns the number of sections. A sectioned fetch request provides this result... SectionedFetchResults<String, CoreDataEntityClass> So how do I iterate through this unusual collection to determine a count?
Posted Last updated
.
Post marked as solved
3 Replies
1.4k Views
NumberFormatter does not function as expected under Xcode 13 betas or macOS 12 betas (currently up to beta 5 for both). I've logged feedback to Apple FB9423179. I'm writing a SwiftUI universal app with macOS and iOS targets using Core Data and NSPersistentCloudKitContainer. A Core Data Entity is an Observed Object in the code for a detail View. e.g. @ObservedObject var account: Account where Account is the class. NumberFormatter currently does not function in a TextField on macOS 12, so as a workaround I am currently using with great success: TextField("Sort Order", text: Binding( get: { String(account.sortOrder) },         set: { account.sortOrder = Int64($0.filter{"0123456789".contains($0)})! } ) ) where sortOrder an entity attribute of type Optional<Int64>. This works well for number entry and in my humble opinion is elegant in that it is immediately obvious what the TextField is expected to do to get the information it displays and set the information provided by the user. The only issue is that when the user makes a mistake entering a number, then backspaces or deletes the number such that the current value of the textfield is nil, then the application crashes because of the force unwrap in the setter. How can I make this accept a temporary value of nil? I have tried a number of workarounds, including the use of temporary property contained in a @State wrapper and loading and saving this temporary value using the .onAppear and .onDisappear modifiers, but that doesn't seem very SwiftUI to me and the downside is that the app no longer updates its UI dynamically.
Posted Last updated
.
Post not yet marked as solved
4 Replies
1.6k Views
My experience implementing Core Data + CloudKit has frankly been relatively easy and I feel very positive about the new NSPersistentCloudKitContainer.Introduction and ThanksHonestly, I approached the new implementation of Core Data + CloudKit with some trepidation.My fears and anxiety were unfounded and I quickly learned just how (unsettlingly) easy it is to implement a CloudKit backed persistent store using NSPersistentCloudKitContainer.The new Core Data documentation is the best I've read by Apple for many years, so a huge and sincere thank you to the Core Data team.A couple of good posts on SO and a good blog by Andrew Bancroft helped close out my preliminary education... https://www.andrewcbancroft.com/blog/ios-development/data-persistence/getting-started-with-nspersistentcloudkitcontainer/The sample app provided by Apple (per WWDC session 202: Using Core Data with CloudKit) is madness for a beginner, however I really appreciate the effort that has gone into demonstrating SO MANY capabilities of the frameworks and expect that in the future, I will refer to it more often.BackgroundSo I've successfully set up a couple of simple sample projects to begin to learn how this new service works.With overwhelming relief and happiness, I've watched these sample projects run perfectly on Simulator (after I signed into iCloud using my developer Apple ID) and on device (using a different Apple ID).To me this is extraordinary.In the past, I have laboured for days in my unsuccessful and clumsy efforts to implement syncing across devices.I'm developing an app, for some time now, but not yet released to the app store - so still in development but close to public testing. In other words... it was easy for me to target iOS 13 and not have to concern myself with backward compatibility.I've even successfully implemented NSPersistentCloudKitContainer on this project... after I stripped out all my mostly failed previous attempts at CloudKit integration - pre iOS 13.ProblemMy Simulator and on device testing, cross referenced with CloudKit Dashboard, has shown that only new NSManagedObjects added to the NSPersistentCloudKitContainer are synced to the iCloud container as a CKRecord. Any existing local data remains in the persistent store, but is not pushed up.My app uses a large existing test data set that I'd much prefer to keep.I'd prefer to learn how to manage the process of loading an existing data set into the iCloud container for any possible future issues I might face.So... I'm curious to know how to properly load a local store of existing data (NSMAnagedObjects) into the new NSPersistentCloudKitContainer so these are synced as CKRecords to the iCloud container?Any advice please?
Posted Last updated
.
Post not yet marked as solved
0 Replies
626 Views
When writing for iOS, I can easily set the autocapitalisation for a TextField by using the .autocapitalisation view modifier. This takes a  UITextAutocapitalizationType and I often use the type .words for my TextField controls in iOS apps. e.g. &#9;&#9;TextField("enter a name", text: $object.name) &#9;&#9;&#9;&#9;.autocapitalization(.words) Being a part of UIKit, this modifier is not available for macOS 11. I am writing an app using SwiftUI for macOS and iOS targets. I want to apply a view modifier to my universal app TextFields that works on both platforms. I could write a function that iterates through every word and use the .textCase view modifier to change the first letter of each word but that seems like a lot of work and also very clunky. Any ideas how to implement something like UIKit .autocapitalization(.words) using SwiftUI for a macOS target? (Without resorting to UIViewRepresentable?)
Posted Last updated
.
Post not yet marked as solved
3 Replies
1.4k Views
Using the new .toolbar modifier, I have successfully created a toolbar for my macOS 11 target. I have all my buttons laid out within a ToolbarItem, with placement set as .primaryAction. ToolbarItem(placement: .primaryAction) {     ToolbarButtons() }&#9;&#9;&#9;&#9; By using the following Label and Spacer() I can hard code a "star" systemImage further to the left of the ToolbarButtons... .toolbar { &#9;&#9;ToolbarItem(placement: .primaryAction) {    &#9;&#9; HStack {        &#9;&#9; Label("Text", systemImage: "star")        &#9;&#9; Spacer(minLength: 60)        &#9;&#9; ToolbarButtons()    &#9;&#9; } &#9;&#9;} }&#9;&#9;&#9;&#9; I can improve the complexity by adding in a separate ToolbarItem with placement set as .navigation... .toolbar { &#9;&#9;ToolbarItem(placement: .navigation) { &#9;&#9;&#9;&#9;ToolbarButtonToLeadingEdge() &#9;&#9;} &#9;&#9;ToolbarItem(placement: .primaryAction) {    &#9;&#9; HStack {        &#9;&#9; Label("Text", systemImage: "star")        &#9;&#9; Spacer(minLength: 60)        &#9;&#9; ToolbarButtons()    &#9;&#9; } &#9;&#9;} }&#9;&#9;&#9;&#9; ...but I still do not have the control over placement that I am hoping for. So is anyone able to please explain how I achieve the complex layout included in many of Apple's Apps (my example would be Notes), that include separators between the master and detail views, that resize with the window as it resizes?
Posted Last updated
.
Post marked as solved
2 Replies
1.3k Views
I’ve a project that is in development and not yet released so I can adopt new tech without having to worry about existing releases and users. It’s a Core Data app, originally targeted iOS. I’m writing a macOS target using as much SwiftUI as possible. I understand - maybe incorrectly - I cannot adopt the new Window in SwiftUI because I must use AppDelegate for my Core Data stack - or do I? Maybe this is a part of the problem? I’d like to build a new toolbar for my macOS target that matches the styling of toolbars already used throughout macOS Bog Sur. I’m struggling to figure out how I implement this larger toolbar and add Toolbar items. I’ve watched the talk on What’s New In SwiftUI and attempted to drop some of the toolbar sample code into my project but, while it compiles, the code is ineffective. any help please?
Posted Last updated
.
Post not yet marked as solved
1 Replies
878 Views
Problem: Present an array of UnitMass values, to present to my app user in a simple table view, to facilitate a user selection.The intention is that this selectedUnit could then be used in conjunction with the Measurementframework, in the following manner:let measureWeight = Measurement(value: tempMeasure.value, unit: selectedUnit)Essentially I want to build an array of available UnitMass... for example:let arrayUnitMass: [UnitMass] = [.carats, .centigrams, .decigrams, .grams, .kilograms, etc...]But I want to do this dynamically and from the UnitMass units available in Foundation.I could write an extension on UnitMass to conform to CaseIterable, but then, as far as I understand, I'd have to implement my own definition of .allCases. (Based on "Enumerating enum cases in Swift", an article written by Ole Bergemann).So maybe I'd be better off writing my own Enum for UnitMass...enum SelectUnitMass { case carats, centigrams, decigrams, grams, kilograms//, etc... }Frankly I'm too lazy to maintain this enum myself and so, as mentioned above, I want to do this dynamically from the UnitMass units available in Foundation. The benefit for this choice will IMHO ensure parity with any future additions (but maybe not deletions).This SO "Get all enum values as an array" is informative, however it does not seem to provide any hints to a solution.Are you aware of some way to prepare an array of all UnitMass units available in Foundation?
Posted Last updated
.