Posts

Post not yet marked as solved
4 Replies
435 Views
I have a complex data model in development mode, with a large amount of data, using CoreData with CloudKit sync. All worked fine, syncing from a Mac to an iPad Pro, until I made some unwise changes to the model and a couple of relationships. I should have known, but was hurrying and not thinking clearly. The App is not on the App Store: it's for my own use. Records are now not synced to CloudKit: _error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _importFinishedWithResult:importer:]- (1371): <PFCloudKitImporter: 0x6000005d8080>: Import failed with error: Error Domain=NSCocoaErrorDomain Code=134421 "Import failed because applying the accumulated changes hit an unhandled exception." UserInfo={NSLocalizedFailureReason=Import failed because applying the accumulated changes hit an unhandled exception., NSUnderlyingException=* -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0]}_** It seems that there's a queue of faulty (non-matching) updates, which I can find no way of purging. Perhaps I could disconnect the CloudKit syncing in the app, use the CloudKit console to reset the development environment, then reconnect CloudKit syncing in the app - but would that invoke a repopulation of the CloudKit data, or cause a deletion of all CoreData data? I can, with a few days' work, reimport all of the data - but that would, I assume, need a newly named app so as to create a new CloudKit container. Any thoughts/solutions would be appreciated. Regards, Michaela
Posted Last updated
.
Post not yet marked as solved
3 Replies
3.7k Views
SwiftUI Map() doesn't provide a way of changing mapType from .standard. Some older (1yr+) StackOverflow posts claim being able to set mapType by using a custom initialiser or an extension, but neither approach seems to work for my needs and set up (Swift 5, iOS 15 beta, Xcode 13). When I use .onAppear() { MKMapView.appearance().mapType = mapStyle}, where mapStyle is a var of the View, the style is set (e.g. to .hybrid) successfully on the first invocation of the view (the map) but not subsequent ones, which are as .standard. I can't think of any way of solving this. I could use MapKit with UIViewRepresentable, which I've done a few times before with other projects, but it'd be nice to use "pure" SwiftUI. Any ideas? Cheers, Michaela PS - the reason for wanting satellite or hybrid is that I often need to return to a location in a forest area with poor, or non existent, trail mapping.
Posted Last updated
.
Post not yet marked as solved
1 Replies
1.5k Views
It seems that a DataFrame (TabularData framework) can be used in CreateML, instead of an MLDataTable - which makes sense, given the description of the TabularData API. However, there are differences. One is that when using a DataFrame, the randomSplit method creates a tuple of DataFrame slices, which cannot then be used in MLLinearRegressor without first converting back to DataFrame (i.e. initialising a new DataFrame with the required slice). Using an MLDataTable as the source data, the output from randomSplit can be used directly in MLLinearRegressor. I'm interested to hear of any other differences and whether the behaviour described above is a feature or a bug. TabularData seems to have more features for data manipulation, although I haven't done any systematic comparison. I'm a bit puzzled as to why there are 2 similar, but separate, frameworks.
Posted Last updated
.
Post not yet marked as solved
1 Replies
1.3k Views
Mac Catalyst treats a SwiiftUI .sheet View as compact, even though there is as much horizontal space in the view as on a physical iPad. The outcome of this is that, with an iPhone, iPad, Catalyst app, abbreviated HStacks that I use for the iPhone version also appear on the Catalyst version, unless I use #if targetEnvironment(macCatalyst) A few months back a Stack Overflow user complained that a Catalyst popover (UIKit) was reporting as .regular and should be .compact. Apple agreed it was a bug. However, in my case (SwiftUI sheet), it doesn't make sense to regard a Catalyst SwiftUI sheet as compact when there is as much space available as on a physical iPad. Regards to all, Michaela
Posted Last updated
.
Post marked as solved
1 Replies
756 Views
For some time now Apple has been referring to iPadOS (eg in https://developer.apple.com/download/ ), but there is no compiler directive in Xcode to check for iPadOS - even though Xcode now has supported destinations for iPhone, iPad and Mac (catalyst). I have a couple of use cases where I'd really prefer to include/exclude large chunks of code (frameworks) based on whether the device is an iPad or an iPhone, not just because of the different user-interface characteristics - which can be accommodated using the UIUserInterfaceIdiom. Regards, Michaela
Posted Last updated
.
Post not yet marked as solved
0 Replies
1.1k Views
I already have a working app, using SwiftUI Canvas, for charting sensor milliVolt data at a frequency of 130Hz, so thought I'd see how SwiftUI Charts compared for ease of implementation. Charts is much easier to implement, saving the tedium of scaling and label context placement. However, creating the AxisMarks.Values was a problem because the stride-by method with Calendar.Component has .second as the smallest unit, and I need deciSecond. I tried some other inbuillt options, e.g. desiredCount, but no joy. After a while I realised that I can create my own values array using a function, so here it is (hoping that this helps someone, somewhere, sometime): struct ChartView: View {     var chartData : [DataPoint] // An array of CoreData objects with timeStamp and milliVolt attributes let xSecStyle = StrokeStyle(lineWidth: 1.0)     let xDeciSecStyle = StrokeStyle(lineWidth: 0.5) ... // The .chartAxis code within Chart in body .chartXAxis {                 AxisMarks(values: deciSecValues) { value in                     if Double(value.index).remainder(dividingBy: 10.0)  == 0.0 { // show the second-gridline as wider and display the time label                         AxisGridLine(stroke:xSecStyle)                                 .foregroundStyle(.orange)                         AxisValueLabel(format: .dateTime.minute().second(),centered: false)                     } else {                         AxisGridLine(stroke:xDeciSecStyle)                                 .foregroundStyle(.orange)                     }                 }             } ..... // The func for creating the X Axis Marks private var deciSecValues : [Date] {         var xDates = [Date]()         if chartData.isEmpty { return xDates }         let deciSecs = (Int(chartData.last!.timeStamp!.timeIntervalSince(chartData.first!.timeStamp!)) + 1) * 10         for i in stride(from: 0, to: deciSecs, by: 1) {             let newTime = Double(i) / 10.0             xDates.append(chartData.first!.timeStamp!.addingTimeInterval(newTime))         }         return xDates     } Regards, Michaela
Posted Last updated
.
Post not yet marked as solved
6 Replies
2.1k Views
When using MKMapView within SwiftUI in MacOS, via NSViewRepresentable and a Coordinator, the are several console messages per second "CVDisplayLinkSetPaused", alternating between [TRUE]and [FALSE] when displaying a poly line and/or annotations. This is possibly preventing NSClickGestureRecognizer from working correctly, although that's probably another, developer (my), issue. These console messages have only occurred in the last two Mac OS beta releases, the last being 21D5039d. Even if these messages are not an indication of a problem, they are very distracting and annoying - taking up so much time and space in the logs. Feedback submitted: FB9845486
Posted Last updated
.
Post not yet marked as solved
3 Replies
1.9k Views
I have a wireless stateless-switch within my private network (LAN) which transmits HTTP posts to a configured URL (e.g. an always-on MacMini) about the switch's state. Upon receipt of a post, my MacOS app will then take appropriate action. No response to the sender is required. The frequency of posts will be minimal ( a few per day), but require immediate attention when received. The LAN is protected from external misuse by a secure gateway. I'd appreciate any suggestions for a lightweight solution (i.e. not a full-blown web-server), either as an overview of methods or sample source (e.g. on GitHub). Regards, Michaela
Posted Last updated
.
Post not yet marked as solved
1 Replies
1.9k Views
I'm developing a SwiftUI multi-platform, multi-user app for family budget management (not for the App Store) using CoreData and iCloud with NSPersistentCloudKitContainer. I use manual Codegen in Xcode to generate the CoreData entity classes, then add extensions for computed properties. These are in my DataModel (ViewModel), which is in an included framework. All data processing is done in the data model. All's working fine in the SwiftUI Views, except for one entity - 'Transaction', which throws a compiler error "'Transaction' is ambiguous for type lookup in this context". Some SO posts say to use the App Name as a prefix to the type, but this doesn't work. What does solve it, in this case, is to use the name of the Framework (Library) holding the type definition: import SwiftUI import OurMoneyLib // my framework holding the DataModel and CoreData entity classes struct TransactionRow: View {     let appAPI = AppAPI()     var transaction : OurMoneyLib.Transaction var body: some View { ...... Why this one entity throws an error, I know not - but it's fixed! I hope this helps someone, somewhere, sometime. Cheers, Michaela
Posted Last updated
.
Post not yet marked as solved
0 Replies
2.4k Views
As a septuagenarian my memory is prone to leaks and I therefore rely on this forum and Stack Overflow for discovering (rediscovering?) solutions to problems. I like to give back when I can, so here goes..... I'm currently doing a project with a variable number of BLE sensors at varying locations and want to display a neat table (grid) of Observations and Locations (in pure SwiftUI) like this: Temperature: Locn1_value, Locn2_value , ..... Locnx_value, obsTime Humidity: Locn1_value, Locn2_value ..... Locnxvalue, obsTime (optionally more sensors) The SwiftUI View is: struct SensorObservationsView: View {     let sensorServer = SensorServer.shared     @State var latestObservations = [ObservationSummary]()     @State var obsColumns = Array(repeating: GridItem(.flexible(),spacing: 20), count: 4)     var body: some View {         VStack{             ForEach(latestObservations,id: \.id) { latestObs in                 HStack{                     LazyVGrid(columns: obsColumns, content: {                         Text(latestObs.id) .foregroundColor(latestObs.colour)                         ForEach(latestObs.summaryRows, id:\.id) { row in                             Text(row.strVal) .foregroundColor(latestObs.colour)                         }                         Text(latestObs.summaryRows.last!.strTime) .foregroundColor(latestObs.colour)                     })                 }             }         }         .onReceive(sensorServer.observationsUpdated, perform: { observationSummaries in             if observationSummaries.isEmpty { return }             latestObservations = observationSummaries             let columns = observationSummaries.last!.summaryRows.count             var newColumns = [GridItem]()             #if os(tvOS)             newColumns.append(GridItem(.fixed(230.0), spacing: 10.0, alignment: .leading))             #else             newColumns.append(GridItem(.fixed(130.0), spacing: 10.0, alignment: .leading))             #endif             for in (0..columns) {                 #if os(tvOS)                 newColumns.append(GridItem(.fixed(170.0), spacing: 10.0, alignment: .trailing))                 #else                 newColumns.append(GridItem(.fixed(70.0), spacing: 10.0, alignment: .trailing))                 #endif             }             #if os(tvOS)             newColumns.append(GridItem(.fixed(190.0), spacing: 10.0, alignment: .trailing))             #else             newColumns.append(GridItem(.fixed(90.0), spacing: 10.0, alignment: .trailing))             #endif             obsColumns = newColumns             })     } } SensorServer collects all required characteristics for all active sensors every few minutes, then publishes the set via SensorServer.observationsUpdated. The View's .onReceive then creates an appropriate array of GridItems based on the number of columns in latestObservations (sadly, I named these as "summaryRows" - because the raw observations are in rows). "latestObs.id" is the observation type e.g. "temperature". The observation time for all is the same and taken from the timestamp of the last item of the summary rows(columns). I also adjust the layout depending on the target platform. PS: SensorServer ensures that there's the same number of location columns, using a default content of "n/a" if there's no valid data from the BLE sensor. The solution is dynamic in that I can add/remove locations (sensors) and not have to recode the View. Sensor data are pre-formatted to strings before sending to the view. I hope this helps someone, somewhere, sometime. Cheers, Michaela
Posted Last updated
.
Post not yet marked as solved
0 Replies
1.5k Views
Most examples, including within documentation, of using CoreML with iOS involve the creation of the Model under Xcode on a Mac and then inclusion of the Xcode generated MLFeatureProvider class into the iOS app and (re)compiling the app.  However, it’s also possible to download an uncompiled model directly into an iOS app  and then compile it (background tasks) - but there’s no MLFeatureProvider class.  The same applies when using CreateML in an iOS app (iOS 15 beta) - there’s no automatically generated MLFeatureProvider.  So how do you get one?  I’ve seen a few queries on here and elsewhere related to this problem, but couldn’t find any clear examples of a solution.  So after some experimentation, here’s my take on how to go about it: Firstly, if you don’t know what features the Model uses, print the model description e.g. print("Model: ",mlModel!.modelDescription). Which gives Model:   inputs: (     "course : String",     "lapDistance : Double",     "cumTime : Double",     "distance : Double",     "lapNumber : Double",     "cumDistance : Double",     "lapTime : Double" ) outputs: (     "duration : Double" ) predictedFeatureName: duration ............ A prediction is created by guard **let durationOutput = try? mlModel!.prediction(from: runFeatures) ** …… where runFeatures is an instance of a class that provides a set of feature names and the value of each feature to be used in making a prediction.  So, for my model that predicts run duration from course, lap number, lap time etc the RunFeatures class is: class RunFeatures : MLFeatureProvider {     var featureNames: Set = ["course","distance","lapNumber","lapDistance","cumDistance","lapTime","cumTime","duration"]     var course : String = "n/a"     var distance : Double = -0.0     var lapNumber : Double = -0.0     var lapDistance : Double = -0.0     var cumDistance : Double = -0.0     var lapTime : Double = -0.0     var cumTime : Double = -0.0          func featureValue(for featureName: String) -> MLFeatureValue? {         switch featureName {         case "distance":             return MLFeatureValue(double: distance)         case "lapNumber":             return MLFeatureValue(double: lapNumber)         case "lapDistance":             return MLFeatureValue(double: lapDistance)         case "cumDistance":             return MLFeatureValue(double: cumDistance)         case "lapTime":             return MLFeatureValue(double: lapTime)         case "cumTime":             return MLFeatureValue(double: cumTime)         case "course":             return MLFeatureValue(string: course)         default:             return MLFeatureValue(double: -0.0)         }     } } Then in my DataModel, prior to prediction, I create an instance of RunFeatures with the input values on which I want to base the prediction: var runFeatures = RunFeatures() runFeatures.distance = 3566.0 runFeatures.lapNumber = 1.0 runFeatures.lapDistance = 1001.0  runFeatures.lapTime = 468.0  runFeatures.cumTime = 468.0  runFeatures.cumDistance = 1001.0  runFeatures.course = "Wishing Well Loop" NOTE there’s no need to provide the output feature (“duration”) here, nor in the featureValue method above but it is required in featureNames. Then get the prediction with guard let durationOutput = try? mlModel!.prediction(from: runFeatures)  Regards, Michaela
Posted Last updated
.
Post not yet marked as solved
2 Replies
2.3k Views
The new TabularData framework in iOS 15, MacOS 12 and watchOS 8 opens up opportunities for easier, more efficient ingestion of data (and for ML possibilities). However, it does not appear to be possible to directly use a DataFrame's rows for a List or ForEach in SwiftUI: the compiler gives an error that the rows do not conform to RandomAccessCollection Protocol. The documentation for Rows does not state compliance with such, even through there are methods which inherit from the protocol. Using a separate iteration to extract each Row (as a DataFrame.Row) from the DataFrame into a new array works. I make this array identifiable by using the row.index as the id. However, if the DataFrame is large this adds considerably to storage and processing overheads. Any thoughts on directly using the DataFrame's Rows in SwiftUI?
Posted Last updated
.
Post not yet marked as solved
0 Replies
575 Views
I have a Multiplatform app using a PersistentCloudKitContainer Model that has a complex object graph and which is still in Development mode (including in CloudKit). An integer attribute of one of the entities needs to be changed to double, for reasons that were not obvious on first analysis of data. According to the Core Data Migration documentation , which is 10 years old, this case would not be Lightweight Migration and so I would need to create a Migration Policy and Process. Although I've only recently imported a few legacy records that set the Int attribute (now required to be Double), there are several hundred entities (imported legacy data) with a default Int value (0). Tempting though it is to just change the attribute type from Int to Double and see what happens, recreating the model and hundreds (thousands?) of records if things go wrong would be a real pain in the derriere. So, given the complexity of my model and the use of CloudKit for multi-device synching, I'm thinking I'll create a new Double attribute and reimport data into that, then when all's fine delete the original Int attribute. This way both sets of changes are Lightweight. Advice? Thoughts? Regards, Michaela
Posted Last updated
.
Post not yet marked as solved
2 Replies
821 Views
I'm doing some summarising of dated data from Coredata using @SectionedFetchRequest and SwiftUI List with Section headers. Summary options are by week, month, quarter and year, with processing by Calendar Component. All works fine (with a bit of extra processing for the week period description) except for quarter, which always returns zero instead of 1 to 4. When I finally decided to look at the documentation https://developer.apple.com/documentation/foundation/calendar/component/quarter there's an Important note saying "The quarter unit is largely unimplemented, and is not recommended for use.". So why have that enumeration if it's known not to work? OK, so I now get the month and then determine the quarter with a switch statement.......
Posted Last updated
.
Post not yet marked as solved
6 Replies
1.1k Views
According to the documentation for DateComponentsFormatter UnitsStyle .abbreviated https://developer.apple.com/documentation/foundation/datecomponentsformatter/unitsstyle, this style (abbreviated) should create a string like “9h 41m 30s”. In some circumstances, eg MacOS target with import Foundation, the result is "9h 41min. 30s.", which is a sort-of mix between .brief and .abbreviated. In my SwiftUI multi-platform app (MacOS & iOS) the incorrect (mixed) style is generated for both platforms. Using Playground, the mixed formatting occurs when the platform is set to MacOS, but not iOS with either import UIKit or import Foundation. Is this a bug, or a "featured" difference between MacOS and iOS? My multi-platform function is import Foundation public func strDuration(_ duration: TimeInterval, style: DateComponentsFormatter.UnitsStyle = .abbreviated) -> String {         let formatter = DateComponentsFormatter()         formatter.allowedUnits = [.hour, .minute, .second]         formatter.unitsStyle = style         formatter.maximumUnitCount = 3         return formatter.string(from: duration) ?? "n/a"     } Regards, Michaela
Posted Last updated
.