When simulating a Storekit error like an invalid device verification or others of that type, should we finish a failed transaction? When I test with a Storekit configuration file, all failed transactions persist after every restart. The Apple-provided sample code for Storekit 2 has transactions finished only when they are successful.
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
I am working on an iOS app where I need to detect when a user starts and stops driving using the Apple Core Motion framework. I've implemented the following MotionActivityManager class to handle activity updates and display the detected states in a SwiftUI view.
While I can accurately detect "Stationary" and "Walking" states, detecting the "Driving" (Automotive) state has been unreliable. The accuracy often fails, and the framework frequently misclassifies driving as other states like "Unknown" or "Walking."
Here's the implementation:
@Published var motionStates: [MotionState] = []
@Published var startDate: String = ""
@Published var confidence: String = ""
init() {
setupDefaultStates()
startActivityUpdates()
}
private func setupDefaultStates() {
motionStates = [
MotionState(label: "Stationary", value: false),
MotionState(label: "Walking", value: false),
MotionState(label: "Running", value: false),
MotionState(label: "Automotive", value: false),
MotionState(label: "Cycling", value: false),
MotionState(label: "Unknown", value: false)
]
}
func startActivityUpdates() {
guard CMMotionActivityManager.isActivityAvailable() else {
print("Motion activity is not available.")
return
}
motionActivityManager.startActivityUpdates(to: .main) { [weak self] motion in
guard let self = self, let motion = motion else { return }
DispatchQueue.main.async {
self.updateProperties(with: motion)
}
}
}
private func updateProperties(with motion: CMMotionActivity) {
motionStates = [
MotionState(label: "Stationary", value: motion.stationary),
MotionState(label: "Walking", value: motion.walking),
MotionState(label: "Running", value: motion.running),
MotionState(label: "Automotive", value: motion.automotive),
MotionState(label: "Cycling", value: motion.cycling),
MotionState(label: "Unknown", value: motion.unknown)
]
startDate = dateFormatter.string(from: motion.startDate)
switch motion.confidence {
case .low:
confidence = "Low"
case .medium:
confidence = "Medium"
case .high:
confidence = "High"
@unknown default:
confidence = "Unknown"
}
}
}
struct MotionState: Identifiable {
let id = UUID()
let label: String
let value: Bool
}
struct ContentView: View {
@StateObject private var motionManager = MotionActivityManager()
var body: some View {
ScrollView {
VStack(spacing: 16) {
ForEach(motionManager.motionStates) { state in
LabelView(label: state.label, value: state.value ? "True" : "False")
}
LabelView(label: "Confidence", value: motionManager.confidence)
}
.padding()
}
.onAppear {
UIApplication.shared.isIdleTimerDisabled = true
motionManager.startActivityUpdates()
}
.navigationTitle("Motion Activity")
}
}
Issues:
The motion.automotive state is often not detected accurately.
The confidence level remains low for the automotive state, even when the device is clearly in a car.
How can I improve the detection accuracy of the "Driving" state using the Core Motion framework?
At present, I am using the avfoundation external device API to connect my iPad to a DSLR camera for data collection. On my end, I am using AVCapture Video Data Output to obtain raw data for processing and rendering. However, the pixelbuf returned from the system layer is incomplete, with only a portion cropped in the middle. But using the Mac API is normal. I would like to ask how to obtain the complete pixelbuf of the image on iPad
I have a video, after recording there is no sound, after a few seconds there is only audio sound that I recorded.
Topic:
App & System Services
SubTopic:
Processes & Concurrency
Hello,
I am working on a Flutter application where I need to use Bluetooth Low Energy (BLE) in Peripheral mode to advertise data even when the app is in the background (or when the screen is turned off) on iOS devices.
I am using the package flutter_ble_peripheral to handle BLE advertising and peripherals. My goal is to make sure that the BLE advertising continues running when the app is minimized or in the background.
Here is what I have already done:
Added the required Bluetooth permissions in Info.plist.
Enabled Background Modes in Xcode (with Bluetooth LE Accessories enabled).
Used the FlutterBlePeripheral.start() method to start advertising.
However, when I minimize the app or turn off the screen, the BLE advertising seems to stop. I have ensured that the app is not terminated but still the advertising is not persistent.
I would like to confirm whether flutter_ble_peripheral works reliably in the background on iOS, or if there are any additional configurations or limitations I need to consider to ensure that advertising continues in the background.
Any insights or experiences would be greatly appreciated.
Thanks!
In the documentation for a Message Filter Extension it states:
If you have servers that can help your app extension determine how to handle a message, you must add the Associated Domains capability to your Xcode project and specify those domains.
(https://developer.apple.com/documentation/sms_and_call_reporting/sms_and_mms_message_filtering/creating_a_message_filter_app_extension)
The words servers and domains are in the plural.
If it's possible to specify multiple servers/domains for a Message Filter Extension then how is that done? There's no documentation nor reference for that.
If multiple domains can be added to the info.plist then what is the iOS behavior in that case?
Can the extension supply/change which domain is used at run time?
I have written an App with a fileIpmorter modifier.
I used TestFlight to pass it to friend for a test.
The App works fine until my friend uses the fileImporter function:
He can select the file to import (simple csv file), the fileImporter closes without having read out the csv file!
I was able to analyze that the do-catch-block within the fileImporter modifier throws an error at the mac of my friend.
The App behaves totally different to my Mac: On my Mac it works perfectly:
the csv file is read out and the data can be used within the APP.
Why does it behave like this?
Why does this happen to the mac of my friend but not on mine?
More strange:
The Apple team is not able to even use the csv-file I passed them in the App Store Connect process: They are not able to select the file in the downloads folder.
All three used MAC´s with three different behaviors? - How comes?
I'm using flutter's inappwebview. All functions work on my simulator and phone, but when I submit for review, I get an answer saying infinite loading. How did it happen? I don't know what the problem is.
Topic:
App & System Services
SubTopic:
Processes & Concurrency
My device is a Matter switch with 12 buttons, but its physical buttons do not correspond to the button icons displayed in the Apple Home App. The mapping between them is chaotic, for example, physical button 1 is mapped to button icon 3, and physical button 2 is mapped to button icon 7, without any pattern. And every time the factory settings are restored and the network is reconfigured, the mapping will be different from the last time, and restoring the factory settings will change it again. I have checked my program and I am certain that the events triggered by physical buttons correspond correctly to the Matter Generic Switch Endpoint in the ZCL file. I don't understand why there was such a mistake. I am using GSDK 4.4.1, Silicon Labs Matter 2.2.1-1.2. I asked the manufacturer of the chip (the staff of Silicon Labs), and they said that the corresponding order displayed on the app is determined by the APP side, and has nothing to do with Matter devices, is this a problem caused by Apple's system, and if so, is there any solution?
I have an app available for download in the Apple App Store. The app sends local notifications, which are scheduled at the user's request once the app launches. I've recently learned that when new versions of my app are deployed and automatically update on the user's device, previously scheduled local notifications are deleted. Given my app design, the user can re-launch the app in order to re-schedule the local notifications. This is a bit of a problem, though, because part of my app's value is in reminding the user - so after requesting a local notification, the user expects to receive a local notification and then launch the app, not the other way around.
Given this, I've been exploring solutions so my app continues to function as expected (including delivering local notifications, even if the app hasn't yet been launched) after an app update. I've explored .backgroundTasks(), but they too are apparently deleted with an app update and require the app to be re-launched first to work as expected. Another solution might be to use push notifications instead of local notifications, but that seems like a very involved solution if I'm just looking to make sure that local notifications persist after an app update. I can't be the only person to have this dilemma - am I overlooking a simple solution?
After updating to watchOS 11.1, updates using WidgetCenter.shared.reloadAllTimelines() in WKRefreshBackgroundTask stopped working. When the background task is triggered, it gets data from the phone and updates the WidgetKit complications. But now the refresh call WidgetCenter.shared.reloadAllTimelines() does not update the complications.
I have:
an Automator workflow saved as an application "workflow.app"
an Apple Script saved as an application "script.app"
a PDF file residing on Desktop "test.pdf"
How do I launch workflow.app and pass test.pdf as the input for workflow from inside script.app?
https://developer.apple.com/documentation/appstoreserverapi/get-v2-history-_transactionid
I would like to inquire about the detailed triggers for updating receipts in this API specification.
Recently, I was using this API with sort=DESCENDING&revoked=false to retrieve the expiration date of the most recent receipt and determine the subscription status. However, for some reason, an old receipt with an earlier expiration date appeared as the first receipt, and I would like to know the reason for this.
Can you provide information on what specific events or actions trigger the updating of receipts in this API?
Also, regarding https://developer.apple.com/documentation/appstoreserverapi/status, will statuses 3 and 4 not be returned in the response unless the billing grace period is enabled in the App Store?
I'm working on my first subscription for an app I've built, and can't seem to figure out where I'm going wrong with this one whether it's something in Xcode or App Store Connect. Any idea where to start? Somethings to check. TIA.
Topic:
App & System Services
SubTopic:
StoreKit
Hi there,
I am using WeatherKit to display weather forecast information in an app.
I would like to include some information about when the weather forecast was issued for my users to see.
This information is included in the response Metadata as documented in the WeatherKit REST API docs:
https://developer.apple.com/documentation/weatherkitrestapi/metadata
Specifically there is a “reportedTime” property which I would like to use here.
However I am consuming WeatherKit via the Swift API, I don’t see this property available via the Swift APIs.
How can I access the reportedTime property via the WeatherKit Swift APIs? Or is it not exposed via the Swift APIs?
I am working with an open source watch called PineTime to implement ANCS support so users can receive iOS notifications in the watch.
I am having g trouble discovering the ANCS on an iOS device. The watch is properly paired and bonded. I realize that the ANCS may not always be present, so I also subscribed to the GATT Service changed characteristic, but never received a notification/indication for a service becoming active.
Is there something I am missing? Thanks!
For important background information, read Extra-ordinary Networking before reading this.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Don’t Try to Get the Device’s IP Address
I regularly see questions like:
How do I find the IP address of the device?
How do I find the IP address of the Wi-Fi interface?
How do I identify the Wi-Fi interface?
I also see a lot of really bad answers to these questions. That’s understandable, because the questions themselves don’t make sense. Networking on Apple platforms is complicated and many of the things that are ‘obviously’ true are, in fact, not true at all. For example:
There’s no single IP address that represents the device, or an interface. A device can have 0 or more interfaces, each of which can have 0 or more IP addresses, each of which can be IPv4 and IPv6.
A device can have multiple interfaces of a given type. It’s common for iPhones to have multiple WWAN interfaces, for example.
It’s not possible to give a simple answer to any of these questions, because the correct answer depends on the context. Why do you need this particular information? What are you planning to do with it?
This post describes the scenarios I most commonly encounter, with my advice on how to handle each scenario.
IMPORTANT BSD interface names, like en0, are not considered API. There’s no guarantee, for example, that an iPhone’s Wi-Fi interface is en0. If you write code that relies on a hard-coded interface name, it will fail in some situations.
Service Discovery
Some folks want to identify the Wi-Fi interface so that they can run a custom service discovery protocol over it. Before you do that, I strongly recommend that you look at Bonjour. This has a bunch of advantages:
It’s an industry standard [1].
It’s going to be more efficient on the ‘wire’.
You don’t have to implement it yourself, you can just call an API [2].
For information about the APIs available, see TN3151 Choosing the right networking API.
If you must implement your own service discovery protocol, don’t think in terms of finding the Wi-Fi interface. Rather, write your code to work with all Wi-Fi interfaces, or perhaps even all Ethernet-like interfaces. That’s what Apple’s Bonjour implementation does, and it means that things will work in odd situations [3].
To find all Wi-Fi interfaces, get the interface list and filter it for ones with the Wi-Fi functional type. To find all broadcast-capable interfaces, get the interface list and filter it for interfaces with the IFF_BROADCAST flag set. If the service you’re trying to discover only supports IPv4, filter out any IPv6-only interfaces.
For advice on how to do this, see Interface List and Network Interface Type in Network Interface APIs.
When working with multiple interfaces, it’s generally a good idea to create a socket per interface and then bind that socket to the interface. That ensures that, when you send a packet, it’ll definitely go out the interface you expect.
For more information on how to implement broadcasts correctly, see Broadcasts and Multicasts, Hints and Tips.
[1] Bonjour is an Apple term for:
RFC 3927 Dynamic Configuration of IPv4 Link-Local Addresses
RFC 6762 Multicast DNS
RFC 6763 DNS-Based Service Discovery
[2] That’s true even on non-Apple platforms. It’s even true on most embedded platforms. If you’re talking to a Wi-Fi accessory, see Working with a Wi-Fi Accessory.
[3] Even if the service you’re trying to discover can only be found on Wi-Fi, it’s possible for a user to have their iPhone on an Ethernet that’s bridged to a Wi-Fi. Why on earth would they do that? Well, security, of course. Some organisations forbid their staff from using Wi-Fi.
Logging and Diagnostics
Some folks want to log the IP address of the Wi-Fi interface, or the WWAN, or both for diagnostic purposes. This is quite feasible, with the only caveat being there may be multiple interfaces of each type.
To find all interfaces of a particular type, get the interface list and filter it for interfaces with that functional type. See Interface List and Network Interface Type in Network Interface APIs.
Interface for an Outgoing Connection
There are situations where you need to get the interface used by a particular connection. A classic example of that is FTP. When you set up a transfer in FTP, you start with a control connection to the FTP server. You then open a listener and send its IP address and port to the FTP server over your control connection. What IP address should you use?
There’s an easy answer here: Use the local IP address for the control connection. That’s the one that the server is most likely to be able to connect to.
To get the local address of a connection:
In Network framework, first get the currentPath property and then get its localEndpoint property.
In BSD Sockets, use getsockname. See its man page for details.
Now, this isn’t a particularly realistic example. Most folks don’t use FTP these days [1] but, even if they do, they use FTP passive mode, which avoids the need for this technique. However, this sort of thing still does come up in practice. I recently encountered two different variants of the same problem:
One developer was implementing VoIP software and needed to pass the devices IP address to their VoIP stack. The best IP address to use was the local IP address of their control connection to the VoIP server.
A different developer was upgrading the firmware of an accessory. They do this by starting a server within their app and sending a command to the accessory to download the firmware from that server. Again, the best IP address to use is the local address of the control connection.
[1] See the discussion in TN3151 Choosing the right networking API.
Listening for Connections
If you’re listening for incoming network connections, you don’t need to bind to a specific address. Rather, listen on all local addresses. In Network framework, this is the default for NWListener. In BSD Sockets, set the address to INADDR_ANY (IPv4) or in6addr_any (IPv6).
If you only want to listen on a specific interface, don’t try to bind to that interface’s IP address. If you do that, things will go wrong if the interface’s IP address changes. Rather, bind to the interface itself:
In Network framework, set either the requiredInterfaceType property or the requiredInterface property on the NWParameters you use to create your NWListener.
In BSD Sockets, set the IP_BOUND_IF (IPv4) or IPV6_BOUND_IF (IPv6) socket option.
How do you work out what interface to use? The standard technique is to get the interface list and filter it for interfaces with the desired functional type. See Interface List and Network Interface Type in Network Interface APIs. Remember that their may be multiple interfaces of a given type. If you’re using BSD Sockets, where you can only bind to a single interface, you’ll need to create multiple listeners, one for each interface.
Listener UI
Some apps have an embedded network server and they want to populate a UI with information on how to connect to that server. This is a surprisingly tricky task to do correctly. For the details, see Showing Connection Information for a Local Server.
Outgoing Connections
In some situations you might want to force an outgoing connection to run over a specific interface. There are four common cases here:
Set the local address of a connection [1].
Force a connection to run over a specific interface.
Force a connection to run over a type of interface.
Force a connection to run over an interface with specific characteristics. For example, you want to download some large resource without exhausting the user’s cellular data allowance.
The last case should be the most common — see the Constraints section of Network Interface Techniques — but all four are useful in specific circumstances.
The following sections explain how to tackle these tasks in the most common networking APIs.
[1] This implicitly forces the connection to use the interface with that address. For an explanation as to why, see the discussion of scoped routing in Network Interface Techniques.
Network Framework
Network framework has good support for all of these cases. Set one or more of the following properties on the NWParameters object you use to create your NWConnection:
requiredLocalEndpoint property
requiredInterface property
prohibitedInterfaces property
requiredInterfaceType property
prohibitedInterfaceTypes property
prohibitConstrainedPaths property
prohibitExpensivePaths property
Foundation URL Loading System
URLSession has fewer options than Network framework but they work in a similar way: Set one or more of the following properties on the URLSessionConfiguration object you use to create your session:
allowsCellularAccess property
allowsConstrainedNetworkAccess property
allowsExpensiveNetworkAccess property
Note While these session configuration properties are also available on URLRequest, it’s better to configure this on the session.
There’s no option that forces a connection to run over a specific interface. In most cases you don’t need this — it’s better to use the allowsConstrainedNetworkAccess and allowsExpensiveNetworkAccess properties — but there are some situations where that’s necessary. For advice on this front, see Running an HTTP Request over WWAN.
BSD Sockets
BSD Sockets has very few options in this space. One thing that’s easy and obvious is setting the local address of a connection: Do that by passing the address to bind.
Alternatively, to force a connection to run over a specific interface, set the IP_BOUND_IF (IPv4) or IPV6_BOUND_IF (IPv6) socket options.
Revision History
2025-01-21 Added a link to Broadcasts and Multicasts, Hints and Tips. Made other minor editorial changes.
2023-07-18 First posted.
I want to check if the device has a internet connection or not by pinging DNS "8.8.8.8".
connection.send(content: content, completion: .contentProcessed {[weak self] error in
send function is not returning any error even if the host is unreachable.
I am checking if I can receive the data or not but connection.receiveMessage function never returns.
This is the complete code which I am following:
private let networkMonitor = NWPathMonitor()
private var connection: NWConnection
@MainActor var isConnectedToInternet = false
init(host: NWEndpoint.Host = "8.8.8.8",
port: NWEndpoint.Port = 53) {
let endpoint = NWEndpoint.hostPort(host: host, port: port)
connection = NWConnection(to: endpoint, using: .udp)
startMonitoring()
}
private func startMonitoring() {
networkMonitor.pathUpdateHandler = { [weak self] path in
guard let self else { return }
ping(callback: { isSuccess in
print("***** ping status:", isSuccess)
Task { @MainActor in
self.isConnectedToInternet = isSuccess
}
})
}
let queue = DispatchQueue(label: QueueLabel.networkMonitor)
networkMonitor.start(queue: queue)
}
func ping(
host: NWEndpoint.Host = "8.8.8.8",
port: NWEndpoint.Port = 53,
callback: @escaping ((Bool) -> Void)
) {
var didSendState = false
connection.stateUpdateHandler = {[weak self] state in
guard let self = self else { return }
guard !didSendState else {
if state != .cancelled {
cancel(connection)
}
return
}
switch state {
case .ready:
// State is ready now send data
let content = "Ping".data(using: .utf8)
let startTime = Date()
connection.send(content: content, completion: .contentProcessed {[weak self] error in
guard let self = self else { return }
if error != nil {
callback(false)
didSendState = true
cancel(connection)
} else {
print("Ping sent, waiting for response...")
connection.receiveMessage { [weak self] content, _, _, receiveError in
guard let self = self else { return }
if let receiveError {
print("Error receiving ping: \(receiveError.localizedDescription)")
callback(false)
} else if let content = content, String(data: content, encoding: .utf8) == "Ping" {
let roundTripTime = Date().timeIntervalSince(startTime)
print("Ping received! Round-trip time: \(roundTripTime) seconds")
callback(true)
} else {
print("Invalid response received")
callback(true)
}
didSendState = true
cancel(connection)
}
}
})
case .failed( _), .waiting( _), .cancelled:
didSendState = true
callback(false)
case .setup, .preparing:
// No callback because the ping has not yet succeeded or failed
break
@unknown default:
didSendState = true
callback(false)
// We don't know what this unknown default means, so cancel pings to be safe
cancel(connection)
}
}
connection.start(queue: .main)
}
func cancel(_ connection: NWConnection) {
connection.cancel()
}
}
Can anyone please help what I am doing wrong.
Hi,
I’m able to view the activity log using the macOS application integrated with Endpoint Security Entitlement in Xcode by setting Debug Process As: root.
However, after archiving the application into a .app using a Developer ID Application certificate and sending it to my friend, they encountered the error ES_NEW_CLIENT_RESULT_ERR_NOT_PRIVILEGED during client initialization when running the application.
Could you please guide me on how to resolve this issue? Specifically, what is the correct technical approach to make the application run as root?
Thanks
I want to use the Apple Healthkit data to recommend personalised insurance. Is this allowed? As I have read in the documentation that the Apple Healthkit data can only be used for fitness and health purposes. Anyone knows what is meant / scope of "fitness and health purposes"? Will personalised insurance as per health data be allowed under this category?