I have a sensor that communicates via BLE periodically. The intention is for it to be a set it and forget it kind of thing. The user will check the app periodically but won't be doing so frequently.
I need the app to be able to still receive the BLE data from the sensor even if it's running in the background so that when the user does check the app, they can see everything that's been happening.
I've read a lot from 2020 - 2021 where it seems many developers are struggling with the same issue.
Is there a supported way to do this now? How to have my app run in the background and still be able to receive BLE data?
Delve into the world of built-in app and system services available to developers. Discuss leveraging these services to enhance your app's functionality and user experience.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
When I am trying Write Virtual NFC from my iOS app the wallet app is open everytime. I just want to write the NFC tag data to RFID reader please help me with that.
Hi.
Background:
We have an app acting as central, keeping a persistent connection to a peripheral body worn sensor, in order to ensure that the sensor behaves as expected.
We've managed make a robust system, that stays connected while the peripheral is in range. When the peripheral gets out of range we're fine with the app being suspended, as long as it's revived when the sensor gets back in range. This works fine using the Restoration Identifier
This revival works also works fine after a phone restart.
Now for the question:
It doesn't work when upgrading the app. (tested in testflight)
As the App Upgrade case isn't specified in:
https://developer.apple.com/library/archive/qa/qa1962/_index.html
we'd like to know if this case is supported.
If it is supported, we'd be happy if you could provide some additional insights.
Best Regards
Rasmus Tønnesen
UNEEG medical
We have a financial application where we want to use NFC to broadcast a Payment URL to another iPhone or Android device when initiating a payment transaction. This will then open the banking application installed on the recipient’s device, allowing the transaction to be completed.
We have already made the necessary requests to Apple and configured the entitlements file as follows:
<key>aps-environment</key>
<string>development</string>
<key>com.apple.developer.nfc.hce</key>
<true/>
<key>com.apple.developer.nfc.hce.iso7816.select-identifier-prefixes</key>
<array>
<string>D2760000850101</string>
</array>
<key>com.apple.developer.nfc.readersession.formats</key>
<array>
<string>TAG</string>
<string>NDEF</string>
</array>
</dict>
I've tried to use CardSession with the sample code provided by Apple on their site: Card Session
The connection between the devices (two iPhones, OS is above iOS 17.4) is established, the event stream's case .received(let cardAPDU): works, however, when I send the response, nothing really happens
Initial APDU response:
CLA | 0x00
INS | 0xA4
P1 | 0x04
P2 | 0x00
DATA | 0x7D2760000850101 (guess this is the AID)
Le | 00
Sending the apdu response in the event stream via:
do {
guard let request = APDUUtil.createAPDURequest(from: paymentUrl) else { return }
try await cardAPDU.respond(response: request)
await cardSession.stopEmulation(status: .success)
}
static func createAPDURequest(from paymentUrl: URL?) -> Data? {
guard let paymentUrl else { return nil }
let ndefMessage = APDUUtil.createNDEFMessage(from: paymentUrl)
APDUUtil.updateNdefRecordFile(ndefMessage: ndefMessage)
let data = Data(mNdefRecordFile)
let apdu = NFCISO7816APDU(instructionClass: 0x00,
instructionCode: 0xA4,
p1Parameter: 0x04,
p2Parameter: 0x00,
data: data,
expectedResponseLength: -1) // Tried with different values
return apdu.data
}
static func createNDEFMessage(from url: URL?) -> NFCNDEFMessage? {
guard let url,
let payload = NFCNDEFPayload.wellKnownTypeURIPayload(url: url) else {
return nil
}
return NFCNDEFMessage(records: [payload])
}
static func updateNdefRecordFile(ndefMessage: NFCNDEFMessage?) {
guard let ndefMessage else {
return
}
// Convert the NFCNDEFMessage to Data
let ndefMessageData = ndefMessage.records.reduce(Data()) { result, record -> Data in
var result = result
result.append(record.payload)
return result
}
let nlen = ndefMessageData.count
mNdefRecordFile = [UInt8](repeating: 0, count: nlen + 2)
// Store the length in the first two bytes (big-endian format)
mNdefRecordFile[0] = UInt8((nlen & 0xFF00) >> 8)
mNdefRecordFile[1] = UInt8(nlen & 0xFF)
// Copy the NDEF message data into the data starting at index 2
mNdefRecordFile.replaceSubrange(2..<mNdefRecordFile.count, with: ndefMessageData)
}
Could someone please help?
I also tried to send the payment url as Data made from url.
We have a working Android application, which uses HCE too (they use NDEF message and byte arrays in communication).
As I've seen, the NFCNDEFReaderSessionDelegate and NFCTagReaderSessionDelegate is not suitable for communication between two iOS devices...
In iPadOS 17.7 my driver shows up in settings just fine. After recompiling with Xcode 16 and installing my app (containing my driver) on iPadOS 18, the app shows up in settings but the driver-enable button is missing from Settings. When I plug-in my custom USB device, the app cannot detect it and I am left with no way to manually enable the driver, as I did in the previous version of iPadOS.
Whilst all current answers to this question indicate the depreciation of CKModifyBadgeOperation, all of them had advised up until 2022 that it could still be used due to Apple not having a replacement Api. Upon running the following code:
badgeReset.modifyBadgeCompletionBlock = { (error) -> Void in
if error != nil {
print("Error resetting badge: \(error!)")
}
}
CKContainer.default().add(badgeReset)
When run I receive the following error:
Error resetting badge: <CKError 0x3001ddf50: "Invalid Arguments" (12/1017); "CKModifyBadgeOperation is no longer supported">
And from testing following this, the badge count incrementation issue continues, indicating that this has been completely invalidated and cannot be used at all.
Even with UNUserNotificationCenter.current().setBadgeCount(0) this only clears the badge count temporarily.
I'm aware of the proposed "workaround" of creating an extension that manually keeps track of notification count & sets the badge accordingly when a notification is received. However I'm trying to ascertain if as of this current point in time there is now no way whatsoever to clear the badge count on the Cloudkit sever level?
I'm building a SwiftUI social photo-sharing app that uses CloudKit, where user profiles (including a CKAsset for profile pictures) are displayed throughout the app. To reduce redundant fetching of profiles across multiple views, I’m trying to implement a cache for the profile CKRecord into a custom model. (Important for handling the CKAsset for a user’s profile picture, ensuring it’s moved from the CloudKit fileURL staging area)
Here's my current approach:
struct UserProfileModel: Identifiable {
let id: String
let displayUsername: String
var profilePicture: UIImage? = nil
}
class UserProfileCache: ObservableObject {
static let shared = UserProfileCache()
@Published var cache: [UserProfileModel] = []
}
Is this a solid approach for caching CKRecords, or is there a more efficient way to structure this for performance and memory management?
I'd appreciate any input or advice on improving this architecture for performance, memory management, and handling profile updates.
Thanks in advance for your help!
Hi there
I have a large codebase with many dependencies. I have a bug which I suspect is caused by accessing the keychain when the app has launched for pre-warming and as a result the keychain is inaccessible.
Are there any recommendations for simulating or testing this app state, and for identifying any static initialisers in my dependencies that could be contributing to my issue?
Thanks
Topic:
App & System Services
SubTopic:
General
I just switched back to Apple Watch from Garmin, and in the time away I got both work and personal vehicles with CarPlay. I've noticed that my AW10 does not get ANY notifications pushed to it while I am using CarPlay, which is annoying because only texts and calls get pushed to my CarPlay screen, so i miss everything else.
Additionally, and this may be a bug issue with iOS18, but I also just noticed that my phone (16) does not light up/make sounds for notifications while using CarPlay - so it doesn't light up, nor do the vehicle speakers make sound with IG/snapchat/etc notifications, and even the screen "lock" sound doesn't audibly go off. I've only had CarPlay for a few months, but I typically keep my phone on Silent anyway, so maybe I'm just noticing this now and its not necessarily a new issue? it does make the sound when i get a text, so logically everything else should make a noise.
I've made sure that my general focus and car focus modes are OFF. Sound is ON. Sound volume setting is all the way up. Have also restarted both phone and watch, and “forgot“ the phone from the vehicle and reconnected
Am I doing something wrong here? is there a solution for either problem? From what I've seen, some people say that the AW not getting notifications at the same time as Carplay is a built-in safety feature, which most people do not want... maybe its the same with the phone not alerting to non-text/call notifications?
When a workout session is being recovered, if it is paused, the elapsed time will be incorrect. It will seem like that workout never was paused.
The recovery works fine if the workout was never paused.
Steps to reproduce:
Implement recoverActiveWorkoutSession
Start workout
Pause session and print the elapsed time
Stop simulator / cause crash
When recoverActiveWorkoutSession is called the elapsed time will not equal the elapsed time when the session was paused.
Here is my implementation. I haven't seen any examples online.
guard let recovered = try? await healthStore.recoverActiveWorkoutSession() else {return}
self.session = recovered
self.builder = recovered.associatedWorkoutBuilder()
self.session?.delegate = self
self.builder?.delegate = self
self.builder?.dataSource = HKLiveWorkoutDataSource(healthStore: healthStore, workoutConfiguration: recovered.workoutConfiguration)
self.sessionState = recovered.state
Hi, we are trying out AccessorySetupKit on our app for pairing with an IoT device via Bluetooth. I can see from this WWDC2024 talk Meet AccessorySetupKit that ASK supports BLE pairing methods with a PIN code.
Is that enabled through this bluetoothPairingLE option on ASAccessory.SupportOptions?
Is it correctly understood that this is referring to the Secure Simple Pairing feature in the BLE specs?
This might be due to my unfamiliarity with Secure Simple Pairing, but does it require the PIN code again after it has been paired but disconnected and then re-connected?
Any help here would be greatly appreciated.
I'm using Healthkit with the following H/W specs:
Apple Watch, series 8, OS: 10.6.1 (21U580)
iPhone 11 Pro, OS: 17.6.1
Mac Studio M1
Xcode ver: 16.0 (16A242d)
I am trying to get Apple Watch to report heart rate, HRV, respiratory rate, and body temperature using Healthkit's HKLiveWorkoutBuilder implementing HKLiveWorkoutBuilderDelegate's workoutBuilder method. However, the only reported value that is found from the workoutBuilder method's collectedTypes (a Set of HKSampleType objects) is HKQuantityTypeIdentifierHeartRate. Nothing for HRV, respiratory rate, or body temperature. All entitlements are set up, the plist filled in, and capabilities in place. Not sure why only the heart rate is reported from the watch but nothing else.
I've scoured StackOverflow, Apple developer forums, even ChatGPT but none of the solutions work.
Any help most appreciate!
The model code is:
import Foundation
import HealthKit
class WatchModel: NSObject, HKLiveWorkoutBuilderDelegate, HKWorkoutSessionDelegate {
private let healthStore = HKHealthStore()
private var workoutSession: HKWorkoutSession!
private var workoutBuilder: HKLiveWorkoutBuilder!
override init() {
super.init()
requestAuthorization()
startWorkoutSession()
}
private func requestAuthorization() {
let heartRateType = HKQuantityType.quantityType(forIdentifier: .heartRate)!
let respiratoryRateType = HKQuantityType.quantityType(forIdentifier: .respiratoryRate)!
let HRVRateType = HKQuantityType.quantityType(forIdentifier: .heartRateVariabilitySDNN)!
let temperatureRateType = HKQuantityType.quantityType(forIdentifier: .bodyTemperature)!
let healthDataTypes: Set = [heartRateType, respiratoryRateType, HRVRateType, temperatureRateType]
healthStore.requestAuthorization(toShare: healthDataTypes, read: healthDataTypes) { (success, error) in
if !success {
print("Authorization failed")
}
}
}
func workoutSession(_ workoutSession: HKWorkoutSession, didChangeTo toState: HKWorkoutSessionState, from fromState: HKWorkoutSessionState, date: Date) {
}
func workoutSession(_ workoutSession: HKWorkoutSession, didFailWithError error: any Error) {
}
func workoutBuilderDidCollectEvent(_ workoutBuilder: HKLiveWorkoutBuilder) {
}
func startWorkoutSession() {
let configuration = HKWorkoutConfiguration()
configuration.activityType = .other
configuration.locationType = .indoor
do {
workoutSession = try HKWorkoutSession(healthStore: healthStore, configuration: configuration)
workoutBuilder = workoutSession.associatedWorkoutBuilder()
workoutBuilder.delegate = self
workoutBuilder.dataSource = HKLiveWorkoutDataSource(healthStore: healthStore, workoutConfiguration: configuration)
let dataSource = HKLiveWorkoutDataSource(healthStore: healthStore, workoutConfiguration: configuration)
let respiratoryRate = HKQuantityType(.respiratoryRate)
dataSource.enableCollection(for: respiratoryRate, predicate: nil)
let bodyTemp = HKQuantityType(.bodyTemperature)
dataSource.enableCollection(for: bodyTemp, predicate: nil)
let hrv = HKQuantityType(.heartRateVariabilitySDNN)
dataSource.enableCollection(for: hrv, predicate: nil)
workoutSession.delegate = self
workoutSession.startActivity(with: Date())
workoutBuilder.beginCollection(withStart: Date(), completion: { (success, error) in
if let error = error {
print("Error starting collection: \(error.localizedDescription)")
}
})
} catch {
print("Failed to start workout session: \(error.localizedDescription)")
}
}
func workoutBuilder(_ workoutBuilder: HKLiveWorkoutBuilder, didCollectDataOf collectedTypes: Set<HKSampleType>) {
print("collected types: \(collectedTypes)")
for type in collectedTypes {
if let quantityType = type as? HKQuantityType {
if quantityType == HKQuantityType.quantityType(forIdentifier: .heartRate) {
if let heartRateQuantity = workoutBuilder.statistics(for: quantityType)?.mostRecentQuantity() {
let heartRateUnit = HKUnit(from: "count/min")
let heartRateValue = heartRateQuantity.doubleValue(for: heartRateUnit)
print("heart rate: \(heartRateValue)")
}
}
if quantityType == HKQuantityType.quantityType(forIdentifier: .heartRateVariabilitySDNN) {
if let hrvQuantity = workoutBuilder.statistics(for: quantityType)?.mostRecentQuantity() {
let hrvUnit = HKUnit.secondUnit(with: .milli)
let hrvValue = hrvQuantity.doubleValue(for: hrvUnit)
print("HRV: \(hrvValue)")
}
}
if quantityType == HKQuantityType.quantityType(forIdentifier: .bodyTemperature) {
if let bodyTempQuantity = workoutBuilder.statistics(for: quantityType)?.mostRecentQuantity() {
let tempUnit = HKUnit.degreeCelsius()
let tempValue = bodyTempQuantity.doubleValue(for: tempUnit)
print("body temp: \(tempValue)")
}
}
if quantityType == HKQuantityType.quantityType(forIdentifier: .respiratoryRate) {
if let respRateQuantity = workoutBuilder.statistics(for: quantityType)?.mostRecentQuantity() {
let respRateUnit = HKUnit(from: "count/min")
let respRateValue = respRateQuantity.doubleValue(for: respRateUnit)
print("breathing: \(respRateValue)")
}
}
}
}
}
}
Topic:
App & System Services
SubTopic:
Health & Fitness
Tags:
watchOS
Health and Fitness
HealthKit
Apple Watch
Hi,
I have seen a lot of answers in different threads Thread 1, Thread 2 that if an app doesn't support scenes, didFinishLaunchingWithOptions shouldn't be called during prewarming. Additionally, DTS Engineer on this Thread 3 mentioned that starting from late iOS 15, didFinishLaunchingWithOptions definitely won't be called during prewarming.
However, we are still seeing in our logs, that didFinishLaunchingWithOptions is called during prewarming, for some users, even on iOS 18. Our app doesn't support scenes, and our AppDelegate is completely Objective-C.
The problem is that in didFinishLaunchingWithOptions we set up our CoreData and Networking stack then we make a network request to fetch data and store it in database. When the app is launching in a prewarming state, CoreData stack can't load the persistent stores because the protected data isn't accessible during prewarming. We are setting the FileProtectionType to completeUnlessOpen for NSPersistentStoreDescription, which means the Core Data files are considered protected data. When user eventually launches app, network request resumes and crashes when trying to store data in database because Persistent Stores not loaded.
What would you recommend to resolve this issue? Rewriting the Core Data stack for lazy initialization is quite challenging since we're using an old library (RestKit) for networking and Core Data caching.
Thanks.
Topic:
App & System Services
SubTopic:
General
i used ios 18 new feature about custom control widget, but this looks like a bug, look at these pictures, control center list won't show these icons when i used my app for a while, and control center page can show these icons
Which scenario does SKErrorOverlayCancelled refer to specifically?
If the user pulls up the payment and cancels it, does it return SKErrorPaymentCancelled or SKErrorOverlayCancelled?
I have an iOS application for the iPhone that works with a companion app on the Apple Watch, using CoreMotion to provide data. How can I launch the Apple Watch companion app from the iPhone app before starting data recording? Can startWatchAppWithWorkoutConfiguration(...) be used for this without registering an actual workout with HealthKit? Or can I register this action as a new custom workout?
Topic:
App & System Services
SubTopic:
Health & Fitness
Hello,
We're encountering overlapping segments and discrepancies when analyzing running/workout data for a 5-mile run. The expected splits for the run are:
8:39
9:06
8:30
8:39
8:43
0:08
However, the raw data includes segments where start times begin before the previous segment ends, and there are duplicate start times. Below is a sample of the raw data:
"startDate": "2024-09-09T19:32:00.308-0400",
"eventType": "segment",
"eventTypeInt": 7,
"endDate": "2024-09-09T19:37:56.135-0400"
},
{
"startDate": "2024-09-09T19:32:00.308-0400",
"eventType": "segment",
"eventTypeInt": 7,
"endDate": "2024-09-09T19:41:08.476-0400"
},```
// Here's an example of where the second segment start time falls in side the first segments startDate and endDate
"startDate": "2024-09-09T19:54:22.658-0400",
"eventType": "segment",
"eventTypeInt": 7,
"endDate": "2024-09-09T19:59:41.215-0400"
},
{
"startDate": "2024-09-09T19:58:44.624-0400",
"eventType": "segment",
"eventTypeInt": 7,
"endDate": "2024-09-09T20:07:23.216-0400"
HealthKit tracker Id is the same with another Device, We are using an application to track our health progress and we are trying to connect our HealthKit to monitor our health data (steps and calories) but unfortunately we can't connect to the app (another application) at the same time because two devices is sharing just one health kit tracker ID. Can anyone help me to resolve this issue? Old phone was used by the other person before changing to new phone
Topic:
App & System Services
SubTopic:
Health & Fitness
Hello HealthKit Experts & Enthusiasts!
I am building an app called one sec which forces people to take a deep breath before they can use social media apps (it’s using Shortcuts Automations for that).
One important feature of one sec is the Good Morning Countdown:
For a specified time after waking up (e.g. 30mins) selected apps are blocked completely. This helps to start the day screen-free.
They way it works is, the user grants access to read HKCategoryTypeIdentifier.sleepAnalysis data.
I have implemented a HKObserverQuery and enableBackgroundDelivery in order to be informed whenever new HKCategoryTypeIdentifier.sleepAnalysis becomes available.
I noticed that when I have my device connected to Xcode, this works as expected. However, when I quit the app and launch it from my Home Screen, my observer query is not informed about new sleep data (except when my app is running in foreground). Any ideas?
Furthermore, I have noticed that sometimes sleep data is provided delayed to HealthKit, many minutes (sometimes even longer) after waking up, no sleep samples are to be found in the Health app. Of course, for my app it is crucial to get accurate + timely so apps can be blocked accordingly.
Is this an issue that the Apple Watch first needs to send the samples to the phone?
Thanks a lot for your help!
I am encountering issues on my device running iOS 18 that fetching heart rate samples associated to a given workout is very slow. Like 10+ seconds slow. This is unacceptable and unexpected.
In producing a video to attach to a feedback, I also observed that Apple Health app displays incorrect information if a workout effort score is associated to a workout.
In this image, you can see the Health app bug:
Total Resting Energy != Estimated Workout Effort Score
Here is the same workout after I delete the workout effort score using the Apple Health app:
Can anyone else see if attempting to view 'heart rate' data within the workout summary in Apple Health is unbearably slow if that workout also has an effort score associated?
My steps:
Record workout (Apple Activity app on watchOS)
Associate effort score
View the workout on Apple Health (iOS)
Attempt to view it's heart rate samples
Observe very slow loading times
Observe the incorrect cell label and value and disappearance of resting energy cell data
Remove/disassociate the effort score from the workout by tapping the workout effort row, and swipe to delete the value.
Navigate back, navigate back, and then go into the workout detail again
At this time the UI fixes itself, but the loading of heart rate data is still super slow
FB15269657 - HealthKit: Sample query to fetch heart rate samples associated to a workout is taking over 10 seconds - computing 'time in heart rate zone'
FB15278790 - Health: Workout summary 'Total Resting Energy' label has value of 'Estimated Workout Effort Score' for a value, pushed view shows empty