When an iOS 14 beta device is connected to my MacBook running Big Sur 11 beta 10, files can be transferred to the iOS device via Finder, but not from iOS to the MacBook. No error is given and the transfer drag-and-drop appears to have worked as normal, except the file doesn't get transferred. It worked in the previous beta of Big Sur, although was problematic in earlier betas.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
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
DataFrame(contentsOfJSONFile:url) (and it's MLDataTable equivalent) assumes that the rows to be imported are at the root level of the JSON structure. However, I'm downloading a fairly large dataset that has "header" information, such as date created and validity period, with the targeted array at a subsidiary level. The DataFrame initialiser has JSONReadingOptions, but these don't apply to this situation (i.e. there's nothing that helps).
It seems that I'm faced with the options of 1) stripping the extraneous data from the JSON file, to leave just the array or 2) decoding the JSON file into a bespoke struct then converting its array into a DataFrame - which removes a lot of the benefits of using DataFrame in the first place.
Any thoughts?
Cheers, Michaela
I had a Big Sur MacMini update (non Beta) get stuck and nothing would fix it, so I then decided to go to Monterey (beta). After some initial problems, related to a Big Sur update waiting in the wings, the Monterey installation started - and then got stuck. The same problem: got so far then no further, time after time. I tried Safe Mode start-ups, but to no avail.
During a shutdown, which also seemed to be blocked, I became aware of HDD noise from the networked backup drive. A backup was in progress! When I turned off automatic backups in TimeMachine (and disconnected the drive), the Monterey install worked - and I suspect the Big Sur update would have done also.
I'm currently rewriting an app developed over many years in Objective-C, Swift, SwiftUI, and an SQLIte database. Until now, I'd avoided CoreData because I'd been using SQL databases for decades (so was comfortable) and had concerns with CoreData's use of NS types. However, the new app will be multi-platform and share/sync data via CloudKit - which will be a pain in the derriere with SQLite (though not insurmountable). So, I'm going to do a test import of two related entities, 1,000 records and 4,500 records, to see how things go. There are more tables, but this will be just a test.
My intended process is:
Export the SQLite tables, "main" and "details", separately, to CSV. There are linking IDs.
In the new app, load each CSV file into DataFrames using the TabularData framework.
For each row in the "main" DataFrame, filter the "details" DataFrame rows on the "main"'s ID, then create Core Data's "main" entity along with the associated "detail" entities.
Do a context.save() - after each "main" or in batches?
Is there a better (less coding?) way?
My understanding is that I can't just populate each set of entities separately and then expect an automatic creation of the relationships. I've seen reference on the Web of Core Data "linking attributes", rather like joins in SQL, but I see no mention of such in the Xcode DataModel builder, nor class definitions. Am I correct in this understanding?
Regards, Michaela
I'm currently developing a multi-platform app where a standalone Watch app collects data, summarises it, then stores the summary in CoreData. The summary gets synchronised across all devices by CloudKit. However, the raw data (e.g. RR interval data from a Polar H10 heart rate monitor) are important from an historical perspective: forming the basis of further analysis, perhaps via AI. Given the limited storage, battery and processing resources on the Watch, it would be inappropriate to persistently store, or perform complex analysis of, the raw data on the Watch.
My preferred solution would be to transfer the raw data to a Mac and, once successfully received, delete it from the Watch (also from CloudKit?). The Mac would then perform further analysis and propagate an additional summary to all other devices. The problem I foresee is that, if using CoreData/CloudKit synchronisation, deleting from the Watch would delete from all other devices. With my currently limited understanding of such synchronisation, I don't see a way of not then automatically deleting the Mac's CoreData records.
Perhaps the solution is to have a separate CoreData container on the watch for the raw data, a separate CloudKit raw data container, and a separate Mac raw data container - then perform the deletes upon receipt of CloudKit update notifications (i.e. not via automatic syncs). The raw data are immutable, so there's no need to deal with updates.
I'd appreciate advice/suggestions on a workable solution.
Regards, Michaela
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.......
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
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
There are some reliable and affordable Polar H10 ECG reader apps available on the App Store: I’ve been using one for a couple of years. However, I recently needed to incorporate an ECG capability into an app that already uses the Polar H10 for RR Interval monitoring,
but the documentation online for Polar ECG is scarce and sometimes incorrect. Polar provides an SDK, but this covers many different devices and so is quite complex. Also, it’s based on RxSwift - which I prefer not to use given that my existing app uses native Swift async and concurrency approaches. I therefore offer this description of my solution in the hope that it helps someone, somewhere, sometime.
The Polar H10 transmits ECG data via Bluetooth LE as a stream of frames. Each frame is length 229 bytes, with a 10 byte leader and then 73 ECG data points of 3 bytes each (microvolts as little-endian integer, two’s complement negatives). The leader’s byte 0 is 0x00, bytes 1 - 8 are a timestamp (unknown epoch) and byte 9 is 0x00. The H10’s sampling rate is 130Hz (my 2 devices are a tiny fraction higher), which means that each frame is transmitted approximately every half second (73/130). However, given the latencies of bluetooth transmission and the app’s processing, any application of a timestamp to each data point should be based on a fixed time interval between each data point, i.e. milliseconds interval = 1000 / actual sampling rate. From my testing, the time interval between successive frame timestamps is constant and so the actual sampling interval is that interval divided by 73 (the number of samples per frame).
I’ve noticed, with both the 3rd party app and my own coding, that for about a second (sometimes more) the reported voltages are very high or low before settling to “normal” oscillation around the isoelectric line. This is especially true when the sensor electrode strap has only just been placed on the chest. To help overcome this, I use the Heart Rate service UUID “180D” and set notify on characteristic "2A37" to get the heart rate and RR interval data, of which the first byte contains flags including a sensor contact flag (2 bits - both set when sensor contact is OK, upon which I setNotifyValue on the ECG data characteristic to start frame delivery).
Having discovered your Polar H10, connected to it and discovered its services you need to discover the PMD Control Characteristic within the PMD Service then use it to request Streaming and to request the ECG stream (there are other streams). Once the requests have been accepted (didWriteValueFor Characteristic) then you start the Stream. Thereafter, frames are delivered by the delegate callback func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) for the characteristic.uuid == pmdDataUUID
The following code snippets, the key aspects of the solution, assume a working knowledge of CoreBluetooth. Also, decoding of data (code not provided) requires a knowledge of byte and bit-wise operations in Swift (or Objective-C).
// CBUUIDs and command data
let pmdServiceUUID = CBUUID.init( string:"FB005C80-02E7-F387-1CAD-8ACD2D8DF0C8" )
let pmdControlUUID = CBUUID.init( string:"FB005C81-02E7-F387-1CAD-8ACD2D8DF0C8" )
let pmdDataUUID = CBUUID.init( string:"FB005C82-02E7-F387-1CAD-8ACD2D8DF0C8" )
let reqStream = Data([0x01,0x02])
let reqECG = Data([0x01,0x00])
let startStream = Data([0x02, 0x00, 0x00, 0x01, 0x82, 0x00, 0x01, 0x01, 0x0E, 0x00])
// Request streaming of ECG data
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?)
if service.uuid == pmdServiceUUID {
for pmdChar in service.characteristics! {
if pmdChar.uuid == pmdControlUUID {
peripheral.setNotifyValue(true, for: pmdChar)
peripheral.writeValue(reqStream, for: pmdChar, type: .withResponse)
peripheral.writeValue(reqECG, for: pmdChar, type: .withResponse)
}
}
}
}
// Request delivery of ECG frames - actual delivery subject to setNotify value
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
// this responds to the reqStream and reqECG write values
if error != nil {
print("**** write error")
return
}
if ecgStreamStarted { return } // I use a flag to prevent extraneous stream start commands
guard let charVal = characteristic.value else { return }
if charVal[0] == 0xF0 && charVal[1] == 0x01 {
peripheral.writeValue(startStream, for: characteristic, type: .withResponse)
ecgStreamStarted = true
}
}
For “live” charting, I create an array of data points, appending each frame’s set on arrival, then provide those points to a SwiftUI View with a TimeLineView(.periodic(from: .now, by:actual sampling interval)) and using Path .addlines with the Y value scaled appropriately using GeometryReader. So far, I’ve found no way of cancelling such a TimeLineView period, so any suggestions are welcome on that one. An alternative approach is to refresh a SwiftUI Chart View on receipt and decoding of each frame, but this creates a stuttered appearance due to the approximately half-second interval between frames.
Regards, Michaela
In an under-development MacOS & iOS app, I need to identify various measurements from OCR'ed text: length, weight, counts per inch, area, percentage. The unit type (e.g. UnitLength) needs to be identified as well as the measurement's unit (e.g. .inches) in order to convert the measurement to the app's internal standard (e.g. centimetres), the value of which is stored the relevant CoreData entity.
The use of NLTagger and NLTokenizer is problematic because of the various representations of the measurements: e.g. "50g.", "50 g", "50 grams", "1 3/4 oz."
Currently, I use a bespoke algorithm based on String contains and step-wise evaluation of characters, which is reasonably accurate but requires frequent updating as further representations are detected.
I'm aware of the Python SpaCy model being capable of NER Measurement recognition, but am reluctant to incorporate a Python-based solution into a production app. (ref [https://developer.apple.com/forums/thread/30092])
My preference is for an open-source NER Measurement model that can be used as, or converted to, some form of a Swift compatible Machine Learning model. Does anyone know of such a model?
A functioning Multiplatform app, which includes use of Continuity Camera on an M1MacMini running Sequoia 15.5, works correctly capturing photos with AVCapturePhoto. However, that app (and a test app just for Continuity Camera) crashes at delegate callback when run on a 2017 MacBookPro under MacOS 13.7.5. The app was created with Xcode 16 (various releases) and using Swift 6 (but tried with 5). Compiling and running the test app with Xcode 15.2 on the 13.7.5 machine also crashes at delegate callback.
The iPhone 15 Continuity Camera gets detected and set up correctly, and preview video works correctly. It's when the CapturePhoto code is run that the crash occurs.
The relevant capture code is:
func capturePhoto() {
let captureSettings = AVCapturePhotoSettings()
captureSettings.flashMode = .auto
photoOutput.maxPhotoQualityPrioritization = .quality
photoOutput.capturePhoto(with: captureSettings, delegate: PhotoDelegate.shared)
print("**** CameraManager: capturePhoto")
}
and the delegate callbacks are:
class PhotoDelegate: NSObject, AVCapturePhotoCaptureDelegate {
nonisolated(unsafe) static let shared = PhotoDelegate()
// MARK: - Delegate callbacks
func photoOutput(
_ output: AVCapturePhotoOutput,
didFinishProcessingPhoto photo: AVCapturePhoto,
error: (any Error)?
) {
print("**** CameraManager: didFinishProcessingPhoto")
guard let pData = photo.fileDataRepresentation() else {
print("**** photoOutput is empty")
return
}
print("**** photoOutput data is \(pData.count) bytes")
}
func photoOutput(
_ output: AVCapturePhotoOutput,
willBeginCaptureFor resolvedSettings: AVCaptureResolvedPhotoSettings
) {
print("**** CameraManager: willBeginCaptureFor")
}
func photoOutput(_ output: AVCapturePhotoOutput, willCapturePhotoFor resolvedSettings: AVCaptureResolvedPhotoSettings) {
print("**** CameraManager: willCaptureCapturePhotoFor")
}
}
The crash report significant parts are.....
Crashed Thread: 3 Dispatch queue: com.apple.cmio.CMIOExtensionProviderHostContext
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000000
Exception Codes: 0x0000000000000001, 0x0000000000000000
Termination Reason: Namespace SIGNAL, Code 11 Segmentation fault: 11
Terminating Process: exc handler [30850]
VM Region Info: 0 is not in any region. Bytes before following region: 4296495104
REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL
UNUSED SPACE AT START
--->
__TEXT 100175000-10017f000 [ 40K] r-x/r-x SM=COW ...tinuityCamera
Thread 0:: Dispatch queue: com.apple.main-thread
0 libsystem_kernel.dylib 0x7ff803aed552 mach_msg2_trap + 10
1 libsystem_kernel.dylib 0x7ff803afb6cd mach_msg2_internal + 78
2 libsystem_kernel.dylib 0x7ff803af4584 mach_msg_overwrite + 692
3 libsystem_kernel.dylib 0x7ff803aed83a mach_msg + 19
4 CoreFoundation 0x7ff803c07f8f __CFRunLoopServiceMachPort + 145
5 CoreFoundation 0x7ff803c06a10 __CFRunLoopRun + 1365
6 CoreFoundation 0x7ff803c05e51 CFRunLoopRunSpecific + 560
7 HIToolbox 0x7ff80d694f3d RunCurrentEventLoopInMode + 292
8 HIToolbox 0x7ff80d694d4e ReceiveNextEventCommon + 657
9 HIToolbox 0x7ff80d694aa8 _BlockUntilNextEventMatchingListInModeWithFilter + 64
10 AppKit 0x7ff806ca59d8 _DPSNextEvent + 858
11 AppKit 0x7ff806ca4882 -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 1214
12 AppKit 0x7ff806c96ef7 -[NSApplication run] + 586
13 AppKit 0x7ff806c6b111 NSApplicationMain + 817
14 SwiftUI 0x7ff90e03a9fb 0x7ff90dfb4000 + 551419
15 SwiftUI 0x7ff90f0778b4 0x7ff90dfb4000 + 17578164
16 SwiftUI 0x7ff90e9906cf 0x7ff90dfb4000 + 10340047
17 ContinuityCamera 0x10017b49e 0x100175000 + 25758
18 dyld 0x7ff8037d1418 start + 1896
Thread 1:
0 libsystem_pthread.dylib 0x7ff803b27bb0 start_wqthread + 0
Thread 2:
0 libsystem_pthread.dylib 0x7ff803b27bb0 start_wqthread + 0
Thread 3 Crashed:: Dispatch queue: com.apple.cmio.CMIOExtensionProviderHostContext
0 ??? 0x0 ???
1 AVFCapture 0x7ff82045996c StreamAsyncStillCaptureCallback + 61
2 CoreMediaIO 0x7ff813a4358f __94-[CMIOExtensionProviderHostContext captureAsyncStillImageWithStreamID:uniqueID:options:reply:]_block_invoke + 498
3 libxpc.dylib 0x7ff803875b33 _xpc_connection_reply_callout + 36
4 libxpc.dylib 0x7ff803875ab2 _xpc_connection_call_reply_async + 69
5 libdispatch.dylib 0x7ff80398b099 _dispatch_client_callout3 + 8
6 libdispatch.dylib 0x7ff8039a6795 _dispatch_mach_msg_async_reply_invoke + 387
7 libdispatch.dylib 0x7ff803991088 _dispatch_lane_serial_drain + 393
8 libdispatch.dylib 0x7ff803991d6c _dispatch_lane_invoke + 417
9 libdispatch.dylib 0x7ff80399c3fc _dispatch_workloop_worker_thread + 765
10 libsystem_pthread.dylib 0x7ff803b28c55 _pthread_wqthread + 327
11 libsystem_pthread.dylib 0x7ff803b27bbf start_wqthread + 15
Of course, the MacBookPro is an old device - but Continuity Camera works with the installed Photo Booth app, so it's possible.
Any thoughts on solving this situation would be appreciated.
Regards, Michaela
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?
The TabularData DataFrame writeCSV method formats Double (and possibly Integer) numbers that are >= 1000 with a comma thousands separator and surrounds the output in double quotes. Numbers less than 1000 are not double-quoted. If the resulting CSV file is then read by DataFrame contentsOfCSVFile an error is thrown, i.e. a type mismatch. This happens irrespective of whether the types option is set in the CSV read, or not.
There is no option in DataFrame writeCSV to specify no thousands separator, nor any other obvious way of preventing the double-quoting.
Currently, I "fix" the problem by reading the CSV in Numbers, setting the faulty column(s) to Numeric then exporting back to CSV.
Any thoughts on preventing the issue in the first place?
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.