Post

Replies

Boosts

Views

Activity

Reply to How to make a list with a filter field in SwiftUI on Mac
Now you mention it Mussau, I vaguely remember having problems with UUID as the List's ID in iOS apps. The integer ID approach (as per my example) works fine without specifically specifying the id: parameter in List - although sometimes the compiler complains in iOS if the View is complex, then I have to specify. It looks like the UUID situation might be a bug, unless it's because the UUID is automatically generated by the system whereas my Int isn't. Anyhow, well done! Good luck and best wishes, Michaela
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Mar ’21
Reply to How to make a list with a filter field in SwiftUI on Mac
To make a List selectable, the binding must be to the id of the items, in your case UUID. So, you would need @State private var selectedItem: UUID? In MacOS, there's no Selection marker (as there is in iOS), so clicking on a row in a selectable list in MacOS highlights the row. At that point the ID of the row (Item) is in selectedItem as the UUID. To do anything further with the selected Item (row) you would need to retrieve it from the sourceList by filtering on the selected UUID. I normally create a sequential Integer ID, starting from 0, when setting up the source data for a list so that I can use that as an index to the source data, provided I don't ever delete any item(s) - otherwise I would have to filter on the integer ID. I also usually use a singleton, class based, data model that is an Observable Object with Published vars and perform all data processing in that model, with changes reflected in the SwiftUI views by a binding to the shared Data Model. For your example the SwiftUI View would be: *** In my example, the user can select an Item without searching, just by clicking on a row. struct ContentView: View {     @ObservedObject var dataModel = DataModel.shared     var body: some View {         VStack() {             TextField("Filter", text: $dataModel.searchString)             Spacer()             List(dataModel.filteredList, selection: $dataModel.selectedEntry) { entry in                 HStack{                     Text(entry.code)                     Text(entry.name)                     Text(entry.other)                 }             }             Text("Selected Item is " + String(dataModel.selectedEntry ?? -1)). // negative means no current selection         }     } } The Data Model would be: struct RegistryEntry: Identifiable, Hashable {     var id = 0     var code = ""     var name = ""     var other = "" } class DataModel : ObservableObject {     static let shared = DataModel()     var sourceList = [RegistryEntry]()     @Published var searchString = "" {         didSet {             if searchString == "" {                 filteredList = sourceList                 return             }             filteredList = sourceList.filter { $0.name.localizedCaseInsensitiveContains(searchString) }         }     }     @Published var selectedEntry : Int?     @Published var filteredList = [RegistryEntry]()     init() {       // set up sourceList by hardcoding or importing // then set initial filtered list to source list         filteredList = sourceList     } } Regards, Michaela
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Mar ’21
Reply to TabularData Framework: DataFrame as a List in SwiftUI
Ah, fixed it :). All I needed to do was add protocol compliance in an extension for DataFrame.Rows extension DataFrame.Rows : RandomAccessCollection { }. Then use the index property of rows as the id in the SwiftUI ForEach (or List) with yourDataFrame.rows as the source, handling the optionals as required. Cheers, Michaela
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jun ’21
Reply to Create Instance of class
products is created as an empty array of type ProductModel, I.e. no product (ProductModel) has yet been instantiated. You will need to look at the definition of ProductModel to see what is required for initiation. You can do this in Xcode (jump to Definition), or autocomplete will probably prompt for the required/available parameters.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jun ’21
Reply to swift ui
Best to start at this Developer document https://developer.apple.com/documentation/swiftui When I started with SwiftUI, my biggest challenge was in rethinking state and data flow, i.e. creation and manipulation of data, which is now well covered here https://developer.apple.com/documentation/swiftui/state-and-data-flow Although SwiftUI has a lot of inbuilt management of state changes, for complex data models I now use Combine to control what gets published from the data model and when, picking up changes by an onReceive in SwiftUI views. To my mind, the key to SwiftUI is a well designed data model, where all data creation and manipulation is done in the model (using Swift) and SwiftUI only presents data, from a single source of truth data model, to the user. Where the user enters data in SwiftUI, this is handed off to the model, by bindings, for processing. Good luck! Michaela
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jul ’21
Reply to Activity recognition using core motion
Here's some sample code using a Data Model and SwiftUI **** The Data Model import Foundation import CoreMotion class DataModel : ObservableObject {     var activityManager : CMMotionActivityManager?     @Published var activities = [CMMotionActivity] () // (remove the space before the ()     init() {         if !CMMotionActivityManager.isActivityAvailable() {             print("Activity Monitoring not available")             return         }         activityManager = CMMotionActivityManager()         if activityManager == nil {  // check just to be sure initialised OK             print("Unable to initialise Activity Manager")             return         }         activityManager!.startActivityUpdates(to: OperationQueue.main) { (motion) in             guard let newMotion = motion else { return }             self.activities.append(newMotion)         }     } } extension CMMotionActivity {     func activityString() -> String {         // returns a compound string of activities e.g. Stationary Automotive         var output = ""         if stationary { output = output + "Stationary "}         if walking { output = output + "Walking "}         if running { output = output + "Running "}         if automotive { output = output + "Automotive "}         if cycling { output = output + "Cycling "}         if unknown { output = output + "Unknown "}         return output     } } **** The Main App (if generated in Xcode 12+) import SwiftUI @main struct Activity_TrackerApp: App {     @StateObject var dataModel = DataModel()     var body: some Scene {         WindowGroup {             ContentView()                 .environmentObject(dataModel)         }     } } **** The Content View import SwiftUI struct ContentView: View {     @EnvironmentObject var dataModel: DataModel     var body: some View {         ScrollView {             ForEach(dataModel.activities, id:\.startDate) {activity in                 HStack{                     Text(activity.startDate, style: .date)                     Text(activity.startDate, style: .time)                     Text(activity.activityString())                 }             }         }     } } You must also add a Plist key for Privacy - Motion Usage Description and say why you're recording activity. This is a very rough UI, but it should get you started. You'll also need (??) to turn off monitoring at some point and deal with entering and exiting background mode. Good luck and regards, Michaela
Topic: App & System Services SubTopic: Hardware Tags:
Jul ’21
Reply to How to develop the server of app ?
I'm not sure if I've understood you correctly (maybe you're after App Store Server information), but here goes: SwiftUI apps typically consist of a number of Views (i.e. the User Interface) and a single Data Model, which handles all of the data processing logic. The Data Model might also interact with a server to store and/or retrieve data. One of my complex apps has servers for SQLite, iCloud, BlueTooth devices and Home Appliances. The Data Model handles all of these servers, consolidating data as required for use by the SwftUI View(s). The Data Model acts as the single point of truth throughout the app: all SwiftUI Views should normally get their UI output from the Data Model and provide UI input (e.g. keyboard input) to the Data Model for processing. SwiftUI monitors for changes to the Data Model, according to developer specified configuration, in order to update the relevant View(s). A simple example of this arrangement is in my answer to this post https://developer.apple.com/forums/thread/685018, which uses Core Motion data to report user activity. The @StateObject var dataModel = DataModel() line in the App View ensures that there's only one copy of dataModel throughout the app, provided conventions for .environmentObject(dataModel) are followed. This Developer document https://developer.apple.com/documentation/swiftui/managing-model-data-in-your-app describes how to manage Model Data. Regards, Michaela
Jul ’21
Reply to CreateML on iOS
As of iOS 15 (beta), CreateML can be used within an app to create (or replace) a model within the app, with access to prediction accuracy to determine whether the latest training improves on a previous model.  This requires Xcode 13 (beta) and Mac OS Monterey (beta).  There's also a new TabularData framework that works similarly to CreateML for data input (e.g. from CSV), but appears to have expanded features (not that I've explored them all). CreateML is a set of types and methods for ingesting data, preprocessing those data (e.g. filtering, mapping, transforming), then using the data for training models. Typically, a user would not be aware that these actions are taking place, so it's not, strictly speaking, a UI (i.e there's nothing on-screen). TabularData is an alternative to CreateML's ingestion and preprocessing features, although there are some annoying issues (beta??). I'm trying this out (e.g. time prediction) with a running app that I've developed over the years, and for which I have a lot of historical data. It makes sense to retrain the model after running a new course and also every few weeks as the user improves (or, in my case, degrades). Good luck and regards, Michaela
Topic: Machine Learning & AI SubTopic: General Tags:
Jul ’21
Reply to User Activity Recognition
With your activityManager (CMMotionActivityManager instance in your Data Model) do a query when an app is restarted ref https://developer.apple.com/documentation/coremotion/cmmotionactivitymanager/1615929-queryactivitystarting HOWEVER, only the last 7 days of activity are available - and you'd need to know when the app was terminated or suspended so as not to double count. It might also be possible to schedule a batch background task (e.g. at night) to run the query and place results in permanent data storage. Check out this reference https://developer.apple.com/documentation/backgroundtasks/choosing_background_strategies_for_your_app particularly"Wake Your App with a Background Push". I've never done this, only knowing about it from the documentation. Good luck and regards, Michaela
Topic: App & System Services SubTopic: Hardware Tags:
Jul ’21
Reply to Is it possible to connect my headphones from swift code?
It’s possible to connect to non-BLE devices in iOS with Swift using the External Accessory framework. However, to interact with the device and send/receive data requires detailed knowledge of the manufacturer’s device specifications - which are usually not available. For example, I wanted to connect to a blood pressure monitor via a Swift app, but the device required a sign-in process and the manufacturer refused to provide documentation - probably because their own app collected and stored user data on the company’s server. good luck and regards, Michaela
Topic: App & System Services SubTopic: Core OS Tags:
Jul ’21
Reply to TabularData: DataFrame - parsing JSON array that is not at the root level
I decided to go with stripping the extraneous data, so created a String extension: extension String {     func midString(from: String, to: String) -> String {         guard let firstChar = firstIndex(of: "[") else { return "" }         guard let lastChar = lastIndex(of: "]") else { return ""}         return String(self[firstChar...lastChar])     } } get the JSON array with: let newJSON = jsonStr?.midString(from: "[", to: "]") This function is useful whenever there are header and footer surrounding a delimited array e.g. delimiters "{" and "}" NOTE: I use lastIndex(of: "]" ) in the hope that Swift is smart enough to scan from the end backwards towards the start of the array. Cheers, Michaela
Topic: Programming Languages SubTopic: Swift Tags:
Jul ’21
Reply to Why Store
I presume that the "Store" they refer to is in fact the App's Data Model. SwiftUI apps typically consist of a number of Views (i.e. the User Interface) and a single Data Model ("Store"), which handles all of the data processing logic. The Data Model might also interact with a server, local or external, to store and/or retrieve data. The Data Model is usually a class that adopts the ObservableObject protocol. Properties within the DataModel that change and which the User Interface (SwiftUI View(s)) needs to display, upon change, need a @Published attribute. Then, in the SwiftUI view you can monitor for changes with an @ObservedObject reference to your data model, or to a specific property of it. There are other ways of SwiftUI monitoring for changes. I also use the Data Model as an interface to an SQLite database, with SwiftUI calling a Data Model function to retrieve data from SQL, format as required, then make the data available to the SwiftUI View e.g. as an array to use in a List. This approach does not rely on monitoring for changes and works best with mostly static data. The function call is made to the Data Model within the List struct and returns the required array. This Developer reference is useful https://developer.apple.com/documentation/swiftui/managing-model-data-in-your-app Regards, Michaela
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Aug ’21
Reply to Multiple environmentObject
I would have a single DataModel class (ObservableObject), which has your published vars for users and product. It then has functions to (e.g. getUsers) to set/update your published vars. The network call is done within the DataModel class. To promulgate a single version of the DataModel in your app, throughout the View hierarchy, you need to put @StateObject var dataModel = DataModel() in your ProjectNameApp instead of var network... Then have .environmentObject(dataModel) after ContentView() In subsequent views (e.g. ContentView) where you want to have access to dataModel put @EnvironmentObject var dataModel: DataModel after the struct definition. Within your SwiftUI Views, you can then use references to your model vars, e.g. dataModel.product If you always need to get the users, and before anything else happens, then you can put a call to getUsers() in the DataModel init(). If you don't do it this way then you'll need a call to dataModel.getUsers() somewhere else. Regards, Michaela
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Aug ’21