Hi,
I'd like to develop an app which runs speech recognition even after going into background. I know I can accomplish this using audio background mode and the process the audio but I am not sure if this workaround would get accepted into App Store because of the processing limitations while in the background.
How can I accomplish this while still being compliant with Apples privacy policy and other restrictions?
Thanks,
Marek
General
RSS for tagDelve 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
We have a requirement where we have to navigate user to specific section (Passwords) in device settings on tap of a button. I've seen other popular apps doing it & also seen some solutions where people provided an option of using "App-prefs". But as per documentation, this is a private API.
What is the solution here if I want to open specific section in device settings without taking a chance of my app getting rejected while submission process?
Topic:
App & System Services
SubTopic:
General
Hello, our app gets rejected as it crashes on launch. According to the logs, it happens because the app attempts to access private-sensitive data. We don't collect any of personal data, so it is probably done by Google Firebase embedded in the app (Core, Firestore, Auth). Maybe you have met similar cases and know any of Firebase settings that disable attempts of accessing privacy-sensitive data? We already set FirebaseDataCollectionDefaultEnabled to NO in info.plist, but it still not enough. Maybe error in facebook sdk? Before that it was written that there was an error when starting the ipad air 5
Log1
Log2
Log3
I haven't gotten any hits searching for this, so I decided to open a new thread.
The Tech Note that was mentioned in an earlier 2024 thread doesn't mention this error.
I've been trying different ways to get a token, and finally found this article that seems to be in the correct format.
https://dev.to/hasone/generate-jwt-token-for-apple-store-connect-api-using-python-3j5h
The Apple App Store Server Swift Library was supposed to have a createJWT() method, but it's gone now.
curl -v -H 'Authorization: Bearer [token]' "https://weatherkit.apple.com/api/v1/availability/37.323/122.032?country=US"
Host weatherkit.apple.com:443 was resolved.
IPv6: (none)
IPv4: 23.66.3.87, 23.66.3.70, 23.66.3.74, 23.66.3.72, 23.66.3.81, 23.66.3.75, 23.66.3.91, 23.66.3.71, 23.66.3.73
Trying 23.66.3.87:443...
Connected to weatherkit.apple.com (23.66.3.87) port 443
ALPN: curl offers h2,http/1.1
(304) (OUT), TLS handshake, Client hello (1):
CAfile: /etc/ssl/cert.pem
CApath: none
(304) (IN), TLS handshake, Server hello (2):
(304) (IN), TLS handshake, Unknown (8):
(304) (IN), TLS handshake, Certificate (11):
(304) (IN), TLS handshake, CERT verify (15):
(304) (IN), TLS handshake, Finished (20):
(304) (OUT), TLS handshake, Finished (20):
SSL connection using TLSv1.3 / AEAD-AES256-GCM-SHA384 / [blank] / UNDEF
ALPN: server accepted http/1.1
Server certificate:
subject: C=US; ST=California; O=Apple Inc.; CN=weather-data.apple.com
start date: Oct 9 21:14:44 2024 GMT
expire date: Jan 7 20:21:03 2025 GMT
subjectAltName: host "weatherkit.apple.com" matched cert's "weatherkit.apple.com"
issuer: C=US; O=Apple Inc.; CN=Apple Public Server ECC CA 1 - G1
SSL certificate verify ok.
using HTTP/1.x
GET /api/v1/availability/37.323/122.032?country=US HTTP/1.1
Host: weatherkit.apple.com
User-Agent: curl/8.7.1
Accept: /
Authorization: Bearer [token]
Request completely sent off
< HTTP/1.1 401 Unauthorized
< Server: Apple
< Content-Type: application/json
< Content-Length: 26
< X-Frame-Options: SAMEORIGIN
< Strict-Transport-Security: max-age=31536000; includeSubdomains
< X-XSS-Protection: 1; mode=block
< Access-Control-Allow-Origin: *
< X-Content-Type-Options: nosniff
< Content-Security-Policy: default-src 'self';
< X-REQUEST-ID: 320cab08-acba-0127-fe19-4893dacf059c
< X-Apple-Origin: 3c6511d9-6be2-32cb-8412-efd1b1efa576
< Content-Disposition: inline;filename=f.txt
< Date: Tue, 15 Oct 2024 10:40:01 GMT
< X-Cache: TCP_MISS from a23-220-165-87.deploy.akamaitechnologies.com (AkamaiGHost/11.6.5-30d892fcde524eb1bee7eeb45111707d) (-)
< Connection: keep-alive
<
Connection #0 to host weatherkit.apple.com left intact
{"reason": "MISSING_AUTH"}
PLATFORM AND VERSION
Xcode Version 16.2 beta 3 (16C5023f)
macOS 15.1.1 (24B91)
Run-time configuration: iOS 18.0
DESCRIPTION OF PROBLEM
We are currently testing the functionality of AirDrop by bringing iPhones close to each other.
I am trying to transfer the activityItemsConfiguration set in the modal screen via AirDrop.
However, if presentationStyle is fullscreen, it succeeds, but otherwise the connection is successful but no item is displayed on the screen.
STEPS TO REPRODUCE
Open my project.
Run on device
Tap Present with toggle is off.
ModalViewController presented as sheet.
Bring another iPhone closer
Play connection animation, then just display connected.
Recently, I have found that the AppShortcut create with AppIntent might be push on the lock screen. But it didn't happen when I was developing. I'm curious how to simulate this case
I have a PDF file with images, using pdfview.document DataRepresentation() converts PDF to Data format, and the background color of the images in the converted PDF turns black. This only occurs on iOS 18 iPad devices, and there is no such problem on iOS 17 iPad and iOS 18 iPhone
Topic:
App & System Services
SubTopic:
General
I'm trying to send an API call to generate the payload for an App Clips Rich Link in Apple Messages. My request has header and body like in the description in the image, and in the authorization header I have a valid secret and fresh iat stamp. but the request returns 403 forbidden status. Did it happend to anyone? Can some one point me to the problem?
https://register.apple.com/resources/messages/msp-rest-api/construct-payload
Topic:
App & System Services
SubTopic:
General
Bonjour
depuis la mise à jour d’iOS survenue hier (13/12/2024), je ne peux plus envoyer d’iMessage.
Topic:
App & System Services
SubTopic:
General
How to determine whether the shortcut command is triggered by Siri or the user clicks?
Hi all.
Since upgrading to a new iPhone 16 pro, running 18.2 public beta, I'm having issue with my wallpaper/Lock Screen.
If AOD is turned OFF, my lock screen is almost too dim to read, and the chosen Lock Screen wallpaper has a blurred effect on it.
if AOD is ON, the screen is still too dim to read, and the wallpaper is just a faint shade of the colour of the image chosen.
Topic:
App & System Services
SubTopic:
General
Some Apple URL schemes are documented for third-party use. It’s fine to use those URL schemes for their intended purpose.
Other Apple URL schemes are not officially documented. Their use is unsupported. If you rely on such implementation details, things might work, or they might not, and that state might change over time.
IMPORTANT If you ship via the App Store, pay attention to clause 2.5.1 of the App Review Guidelines.
The Apple URL scheme documentation is not always easy to find. I’m aware of the following:
Apple URL Scheme Reference
QA1924 Opening Keyboard Settings from a Keyboard Extension [This Q&A was retired years ago.]
Preparing your app to be the default messaging app
The doc comments for es_new_client in <EndpointSecurity/ESClient.h>
Developer > Bug Reporting describes the applefeedback scheme
Additionally, as questions about this most commonly crop up in the context of opening Settings (System Settings on macOS), I wanted to highlight the following:
UIApplication.openSettingsURLString property (in Objective-C this is UIApplicationOpenSettingsURLString)
UIApplication.openNotificationSettingsURLString property (in Objective-C this is UIApplicationOpenNotificationSettingsURLString)
AccessibilitySettings.openSettings(for:) method
FIFinderSyncController.showExtensionManagementInterface() class method
SMAppService.openSystemSettingsLoginItems() class method
VSOpenTVProviderSettingsURLString global
CXCallDirectoryManager.openSettings(completionHandler:) method
If your app needs to perform some action that’s not covered by the above, file an enhancement request for a supported way to do that. Make sure to describes your use case in detail.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Revision History
2025-04-21 Added a link to CXCallDirectoryManager.openSettings(completionHandler:).
2024-10-25 Added a link to UIApplication.openNotificationSettingsURLString and VSOpenTVProviderSettingsURLString. Added a link to Preparing your app to be the default messaging app.
2024-10-01 Added info about the applefeedback URL scheme.
2024-09-29 Added a link to SMAppService.openSystemSettingsLoginItems().
2024-09-27 Added a titbit for Finder Sync extension developers. Added an invitation to file feedback.
2024-08-05 First posted.
I've found an app that has a call blocking feature an is able to add more than 10_000_000 entries. As I understand it doesn't use more than one extension for it because I see only one in the Call Blocking & Identifying settings menu. How to implement that? My limit now is around 1_800_000 entries.
I'm trying (in Swift) to use CryptoKit to generate the required JWT for the Apple Music Web API, as documented (sort of) here.
But I'm getting 401s no matter what I try. I found some examples of generating JWTs online, but something isn't working here. I've set up my identifiers and gotten an API secret through my account in the dev portal. It's associated with an identifier requesting Music API access (I requested all three available Music-related capabilities).
For the secret, I'm using the long key string from the .p8 file I generated and downloaded from the dev portal.
Here's what I've tried:
struct APIToken
{
struct Header: Encodable
{
let alg = "HS256"
let kid: String
}
struct Payload: Encodable
{
let iss: String
let iat: String
let exp: String
}
static func tokenize(keyID: String, issuerID: String, secret: String) -> String
{
let privateKey = SymmetricKey(data: Data(secret.utf8))
let headerJSONData = try! JSONEncoder().encode(Header(kid: keyID))
let headerBase64String = headerJSONData.base64EncodedString()
let currUnixTime = Int(Date().timeIntervalSince1970)
let expUnixTime = currUnixTime + 5 * 2628288 // five months of seconds
let payloadJSONData = try! JSONEncoder().encode(Payload(iss: issuerID, iat: "\(currUnixTime)", exp: "\(expUnixTime)"))
let payloadBase64String = payloadJSONData.base64EncodedString()
let toSign = Data((headerBase64String + "." + payloadBase64String).utf8)
let signature = HMAC<SHA256>.authenticationCode(for: toSign, using: privateKey)
let signatureBase64String = Data(signature).base64EncodedString()
let token = [headerBase64String, payloadBase64String, signatureBase64String].joined(separator: ".")
print(token)
return token
}
}
I also tried making sure the base64 strings are URL-safe with this extension:
extension Data
{
func URLSafeBase64EncodedString() -> String
{
return base64EncodedString()
.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
.replacingOccurrences(of: "=", with: "")
}
}
but that made no difference.
All the documentation says is
A decoded developer token has the following format.
{
"alg": "ES256",
"kid": "ABC123DEFG"
}
{
"iss": "DEF123GHIJ",
"iat": 1437179036,
"exp": 1493298100
}
After you create the token, sign it with your MusicKit private key using the ES256 algorithm.
Am I not doing that? Any insight appreciated.
I have released a watchOS-specific application that retrieves data from the iPhone calendar app and displays it on the Apple Watch.
It uses the calendars function in EKEventStore to retrieve the list of calendars, but it seems that it sometimes fails to retrieve iCloud calendars.
Trouble is, this problem only occurs in a very few users‘ environments, the majority of other users’ environments are able to retrieve them without any problems, and I cannot reproduce it at all in my environment.
Local calendars and Google calendars seem to be retrieved without any problems.
Minimal example code:
import SwiftUI
import EventKit
struct ContentView: View {
let eventStore = EKEventStore()
@State var success: Bool = false
@State var calendarNames: [String] = [String]()
func request() async {
success = (try? await eventStore.requestFullAccessToEvents()) ?? false
}
func list() {
calendarNames = eventStore.calendars(for: .event).map { $0.title }
}
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Access: \(success.description)")
ScrollView {
ForEach(calendarNames, id: \.self) { name in
Text(name)
}
}
}
.onAppear {
Task {
await request()
list()
}
}
.padding()
}
}
I asked the user experiencing the problem to try restarting the iPhone and Apple Watch, reinstalling the app and re-pairing them, but there was no change.
I would appreciate any information you can provide.
Best regards.
I need some assistance with the Screen Time API’s DeviceActivityReport extension. I know the extension is sandboxed but I need the data inside my app. Jomo is currently doing this so it’s not impossible. I see they’re saying it’s an estimate which is about 5 - 10 off of the actual screen time, but how are they doing this?
Any attempt to store the screen time data inside some sort of database or UserDefaults always fails of course due to the sandbox.
Any advice would be greatly appreciated!
Hi folks,
I have trouble with reading NFC tag in background while my application is running.
I still receives a message in my iPhone 13, NFC tag of web Open "donator.cz" in application Safari.
But I would like to open the app Donator which is here: https://apps.apple.com/dk/app/don%C3%A1tor/id6473955033
My NFC chip scanned by "NFC Tools" is ISO 14443-3A (NXP-NTAG213)
In the tag is mentioned https://donator.cz/<8digits-number>**text
In my Info.plist of application is:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>https://donator.cz</string>
</array>
<key>com.apple.developer.nfc.readersession.felica.systemcodes</key>
<array>
<string>12FC</string>
</array>
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
<string>D2760000850101</string>
</array>
Apple CDN looks like: https://app-site-association.cdn-apple.com/a/v1/donator.cz
I have read in Apple documentation https://developer.apple.com/documentation/corenfc/adding-support-for-background-tag-reading
that application should be in progress A Core NFC reader session is in progress.
How to do it in AppDelegate or SceneDelegate.
One note is that everything works properly in case of reading NFC based on button click is pressed.
My NFCHandler looks like:
//
// NFCReader.swift
// Donator
//
// Created by Petr Hracek on 22.11.2024.
//
import Foundation
import UIKit
import CoreNFC
class NFCHandler: NSObject, NFCNDEFReaderSessionDelegate {
var readerSession: NFCNDEFReaderSession?
func startBackgroundScanning() {
guard NFCNDEFReaderSession.readingAvailable else {
return
}
readerSession = NFCNDEFReaderSession(delegate: self, queue: DispatchQueue.main, invalidateAfterFirstRead: true)
readerSession?.alertMessage = "Prilozte NFC tag"
readerSession?.begin()
}
func readTag(session: NFCNDEFReaderSession , tags: [NFCNDEFTag] ) {
if tags.count > 1 {
// Restart polling in 500ms
let retryInterval = DispatchTimeInterval.milliseconds(500)
session.alertMessage = "More than 1 tag is detected, please remove all tags and try again."
DispatchQueue.global().asyncAfter(deadline: .now() + retryInterval, execute: {
session.restartPolling()
})
return
}
// Connect to the found tag and perform NDEF message reading
let tag = tags.first!
session.connect(to: tag, completionHandler: { (error: Error?) in
if nil != error {
session.alertMessage = "Unable to connect to tag."
session.invalidate()
return
}
tag.queryNDEFStatus(completionHandler: { (ndefStatus: NFCNDEFStatus, capacity: Int, error: Error?) in
if .notSupported == ndefStatus {
session.alertMessage = "Tag is not NDEF compliant"
session.invalidate()
return
} else if nil != error {
session.alertMessage = "Unable to query NDEF status of tag"
session.invalidate()
return
}
tag.readNDEF(completionHandler: { (message: NFCNDEFMessage?, error: Error?) in
var statusMessage: String
if nil != error || nil == message {
statusMessage = "Fail to read NDEF from tag"
} else {
statusMessage = "Found 1 NDEF message"
DispatchQueue.main.async {
// Process detected NFCNDEFMessage objects.
debugPrint(message!)
//self.tableView.reloadData()
}
}
session.alertMessage = statusMessage
session.invalidate()
})
})
})
}
/// - Tag: sessionBecomeActive
/// This method will called when NFC session become active
/// Tells the delegate that the session detected NFC tags with NDEF messages.
func readerSessionDidBecomeActive(_ session: NFCNDEFReaderSession) {
debugPrint("NFC session become active======")
}
func readerSessionDidInvalidate(_ session: NFCNDEFReaderSession) {
debugPrint("NFC session invalidate======")
}
func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
print(error)
}
func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {
for message in messages {
for record in message.records {
print("Type name format: \(record.typeNameFormat)")
print("Payload: \(record.payload)")
print("Type: \(record.type)")
print("Identifier: \(record.identifier)")
}
}
}
/// - Tag: processingNDEFTag
/// if This method is not implement then only func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) will call
/// Tells the delegate that the session detected NFC tags with NDEF messages and enables read-write capability for the session.
func readerSession(_ session: NFCNDEFReaderSession, didDetect tags: [NFCNDEFTag]) {
self.readTag(session: session, tags: tags)
}
}
Ever since updating to iOS18, CarPlay has been buggy for me. One of the constant issues is that after it connects, when I select an app (eg google maps or Spotify), the entire app will freeze. This happens regardless of the app I choose. Nothing on the app will be responsive unless I use the physical car controls to back out of the app. Once I’m on the main view of carplay (where it shows all the apps or where it shows the maps/audio mixes screen) then carplay becomes responsive again. But since I can’t use any of the apps as soon as I select one, I have to reboot my phone to resolve the issue. However, the issue will just happen again ok a subsequent attempt to connect. Some times it will work ok, probably happens again every 2-3 times I connect. This never happened prior to iOS18.
Any suggestions?
Hello,
I have a problem loading data from UserDefaults. The group is set. When I test the software on an iOS phone/emulator, everything is OK. When I test the software on a Mac, it is:
The main program can write and read data.
The widget cannot read the data :(
Topic:
App & System Services
SubTopic:
General
Hi all, I am working with MusicKit and have managed to get a user's recommendation playlists (favorites, get up, etc). Isolating just one, I am trying to access the tracks in there using .tracks but it returns nothing. Wondering if I am doing something wrong or if these don't have tracks necessarily associated with them.
Code is below
(not everything just kinda where I am accessing the playlist)
try await requestMusicAuthorization()
let request = MusicPersonalRecommendationsRequest()
let response = try await request.response()
guard let madeForYou = response.recommendations.first(where: { $0.title == "Made for You" }) else {
throw NSError(domain: "RecommendationError", code: 0, userInfo: [NSLocalizedDescriptionKey: "No 'Made for You' recommendation found."])
}
guard let firstPlaylist = madeForYou.playlists.first else {
throw NSError(domain: "PlaylistError", code: 1, userInfo: [NSLocalizedDescriptionKey: "No playlists found in 'Made for You' recommendation."])
}
print("Fetching tracks for playlist: \(firstPlaylist.name ?? "Unknown")")
let playlistRequest = MusicCatalogResourceRequest<Playlist>(matching: \.id, equalTo: firstPlaylist.id)
let playlistResponse = try await playlistRequest.response()
guard let playlist = playlistResponse.items.first else {
throw NSError(domain: "PlaylistError", code: 2, userInfo: [NSLocalizedDescriptionKey: "Couldn't fetch the playlist details."])
}
guard let tracks = playlist.tracks else {
throw NSError(domain: "PlaylistError", code: 3, userInfo: [NSLocalizedDescriptionKey: "No tracks found in the playlist."])
}