Posts under App & System Services topic

Post

Replies

Boosts

Views

Activity

New features for APNs token authentication now available
Team-scoped keys introduce the ability to restrict your token authentication keys to either development or production environments. Topic-specific keys in addition to environment isolation allow you to associate each key with a specific Bundle ID streamlining key management. For detailed instructions on accessing these features, read our updated documentation on establishing a token-based connection to APNs.
0
0
1.5k
Feb ’25
Issue with Property Wrapper Publisher Being Deallocated Prematurely When Not Stored as a Property
Hello everyone, I've built a @CurrentValue property wrapper that mimics the behavior of @Published, allowing a property to publish values on "did set". I've also created my own assign(to:) implementation that works with @CurrentValue properties, allowing values to be assigned from a publisher to a @CurrentValue property. However, I'm running into an issue. When I use this property wrapper with two classes and the source class (providing the publisher) is not stored as a property, the subscription is deallocated, and values are no longer forwarded. Here's the property wrapper code: @propertyWrapper public struct CurrentValue<Value> { /// A publisher for properties marked with the `@CurrentValue` attribute. public struct Publisher: Combine.Publisher { public typealias Output = Value public typealias Failure = Never /// A subscription that forwards the values from the CurrentValueSubject to the downstream subscriber private class CurrentValueSubscription<S>: Subscription where S: Subscriber, S.Input == Output, S.Failure == Failure { private var subscriber: S? private var currentValueSubject: CurrentValueSubject<S.Input, S.Failure>? private var cancellable: AnyCancellable? init(subscriber: S, publisher: CurrentValue<Value>.Publisher) { self.subscriber = subscriber self.currentValueSubject = publisher.subject } func request(_ demand: Subscribers.Demand) { var demand = demand cancellable = currentValueSubject?.sink { [weak self] value in // We'll continue to emit new values as long as there's demand if let subscriber = self?.subscriber, demand > 0 { demand -= 1 demand += subscriber.receive(value) } else { // If we have no demand, we'll cancel our subscription: self?.subscriber?.receive(completion: .finished) self?.cancel() } } } func cancel() { cancellable = nil subscriber = nil currentValueSubject = nil } } /// A subscription store that holds a reference to all the assign subscribers so we can cancel them when self is deallocated fileprivate final class AssignSubscriptionStore { fileprivate var cancellables: Set<AnyCancellable> = [] } fileprivate let subject: CurrentValueSubject<Value, Never> fileprivate let assignSubscriptionStore: AssignSubscriptionStore = .init() fileprivate var value: Value { get { subject.value } nonmutating set { subject.value = newValue } } init(_ initialValue: Output) { self.subject = .init(initialValue) } public func receive<S>(subscriber: S) where S: Subscriber, Failure == S.Failure, Output == S.Input { let subscription = CurrentValueSubscription(subscriber: subscriber, publisher: self) subscriber.receive(subscription: subscription) } } public var wrappedValue: Value { get { publisher.value } nonmutating set { publisher.value = newValue } } public var projectedValue: Publisher { get { publisher } mutating set { publisher = newValue } } private var publisher: Publisher public init(wrappedValue: Value) { publisher = .init(wrappedValue) } } /// A subscriber that receives values from an upstream publisher and assigns them to a downstream CurrentValue property. private final class AssignSubscriber<Input>: Subscriber, Cancellable { typealias Failure = Never private var receivingSubject: CurrentValueSubject<Input, Never>? private weak var assignSubscriberStore: CurrentValue<Input>.Publisher.AssignSubscriptionStore? init(currentValue: CurrentValue<Input>.Publisher) { self.receivingSubject = currentValue.subject self.assignSubscriberStore = currentValue.assignSubscriptionStore } func receive(subscription: Subscription) { // Hold a reference to the subscription in the downstream publisher // so when it deallocates, the susbcription is automatically cancelled assignSubscriberStore?.cancellables.insert(AnyCancellable(subscription)) subscription.request(.unlimited) } func receive(_ input: Input) -> Subscribers.Demand { receivingSubject?.value = input return .none } func receive(completion: Subscribers.Completion<Never>) { // Nothing to do here } public func cancel() { receivingSubject = nil assignSubscriberStore = nil } } public extension Publisher where Self.Failure == Never { /// Assigns the output of the upstream publisher to a downstream CurrentValue property /// - Parameter currentValue: The CurrentValue property to assign the values to func assign(to currentValue: inout CurrentValue<Self.Output>.Publisher) { let subscriber = AssignSubscriber(currentValue: currentValue) self.subscribe(subscriber) } } Here’s an example demonstrating the issue, where two classes are used: Source, which owns the @CurrentValue property, and Forwarder1, which subscribes to updates from Source: final class Source { @CurrentValue public private(set) var value: Int = 1 func update(value: Int) { self.value = value } } final class Forwarder1 { @CurrentValue public private(set) var value: Int init(source: Source) { self.value = source.value source.$value.dropFirst().assign(to: &$value) // The source is not stored as a property, so the subscription deallocates } func update(value: Int) { self.value = value } } With this setup, if source isn’t retained as a property in Forwarder1, the subscription is deallocated prematurely, and value in Forwarder1 stops receiving updates from Source. However, this doesn’t happen with @Published properties in Combine. Even if source isn’t retained, @Published subscriptions seem to stay active, propagating values as expected. My Questions: What does Combine do internally with @Published properties that prevents the subscription from being deallocated prematurely, even if the publisher source isn’t retained as a property? Is there a recommended approach to address this in my custom property wrapper to achieve similar behavior, ensuring the subscription isn’t lost? Any insights into Combine’s internals or suggestions on how to resolve this would be greatly appreciated. Thank you!
0
4
441
Nov ’24
Taking long time to load Device Activity Report
When I try to load the device activity report, it takes too long to load data. Is this because of development time? Will the problem be solved when the app is live on the App Store? If it does not depend on the development profile, then please give me a solution for the fast data loading in the device activity report extension. Thank you
0
1
414
Nov ’24
PTT Bluetooth transmission does not work as expected
Hello, I've been working to implement PTT in the way recommended by the documentation. The main issue is that the bluetooth methods are opaque, so I cannot solve for what I need. The result will be that I will have to resort to hacky approaches that the PTT framework seems to be intended to solve (playing silent clips, playing custom notification sounds, having long running background audio sessions). I am testing with Anker soundcore mini as well as airpod pro. Here's the issue: there are 2 very different behaviours depending on whether I'm using a call/fullDuplex session and a halfDuplex session. halfDuplex Anchor mini Current behaviour long press activates siri pressing again after siri is active, starts transmission long press activates siri again pressing again after siri is active, stops transmission pause/play routes to the ongoing media session and plays music Expected behaviour play/pause should map to transmit/stopTransmit IF I have to use long press, it should at least not trigger siri AirPod pro Current behaviour long press changes noise cancellation pause/play routes to the ongoing media session and plays music Expected behaviour play/pause should map to transmit/stopTransmit fullDuplex/call Anchor mini: Current behaviour long press activates siri pressing again after siri is active, starts transmission long press activates siri again pressing again after siri is active, stops transmission pause/play routes to the ongoing media session and plays music Expected behaviour play/pause should map to transmit/stopTransmit IF I have to use long press, it should at least not trigger siri AirPod pro Current behaviour long press changes noise cancellation pause/play maps to mute/unmute (even if media is playing) Expected behaviour This makes sense for call behaviour, I wish it worked this well for PTT The intention here is to be able to fully interact with a channel hands-free. The current API seems to make that impossible. Is that by design? Reading all the docs seems to suggest its intended for transmit/stopTransmit to be doable just with the play/pause buttons, but even apple hardware seems to not support that.
0
0
541
Nov ’24
frequentPushEnablementUpdates for live activity is never called.
frequentPushEnablementUpdates asynchronous sequence is never called even if 'More Frequent Updates' is toggled ON or OFF. for await frequentPushEnabled in ActivityAuthorizationInfo().frequentPushEnablementUpdates { // never called } Though we are able to get the 'More Frequent Updates' value once by the following: var isEnabled = ActivityAuthorizationInfo().frequentPushesEnabled //true if ON, false if OFF This only gives the result once as it is not async observation sequence. But the 'frequentPushEnablementUpdates' async sequence is never called. As per the doc - 'frequentPushEnablementUpdates' is an asynchronous sequence you use to observe whether a person permitted you to update Live Activities with frequent ActivityKit push notifications.
0
0
360
Nov ’24
What is the criterion for Font Book's "English" Language group
I've created a font family, but Font Book refuses to include it in the English language set, despite my best efforts. The font has every glyph in the OpenType "Std" set, plus several others. I've checked various boxes for Latin 1 and Macintosh Character Codepages; plus Unicode ranges for Basic Latin, additional Latin, etc, etc. I've compared it to several other fonts that are in the English set, and I can't see anything that they have that my fonts don't. (In fact, many of them seem to have much less!) I've created other fonts that are in the English set, but I've no idea what the difference is. Given that macOS relies on these Language sets, in order to hide the thousands of unnecessary fonts that are permanently installed in the OS, there ought to be some guidance on how to do this.
0
0
410
Nov ’24
How to implement continuous speech recognition in the background?
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
0
0
465
Dec ’24
App with iMessage extension AND sticker pack
Im not a dev but trying to create something trying to create an app that includes an iMessage extension AND a sticker pack. My first attempt I tried to create a iMessage app but apparently I cant include a sticker pack. Ive tried to create a shell app with a sticker pack and iMessage extension but it's just not working. Can someone please let me know how I can do this. How can I get an iMessage extension app and a sticker pack installed at the same time from the same app. Ive tried everything, tried creating a seperate iOS app with sticker pack and iMessage extension and nothing. A lot of times a get an error like "CompileAssetCatalogVariant failed with a nonzero exit code"" If I remove the sticker pack builds successfully. thank you in advance
0
0
498
Nov ’24
Pull data on iOS App Homescreen Widget
Hello fellow developers! I am interested in obtaining the following information regarding one of our Home Screen widgets: Pull the following data about the "my_app_widget" homepage widget in total and by month for the last 12 months (Sep '23 - Sep '24): Widget install events Unique widget installs Device type (iPad, iOS). Thus far, I am using AWS Lambda and have the proper credentials within a Secrets Manager and I keep getting a 409 error from this code: const AWS = require('aws-sdk'); const axios = require('axios'); const jose = require('jose'); const crypto = require('crypto'); const s3 = new AWS.S3(); const secretsManager = new AWS.SecretsManager(); const cloudwatchlogs = new AWS.CloudWatchLogs(); const logGroupName = '/aws/lambda/my_lambda_function'; const logStreamName = '2024/11/05/[$LATEST]XXXXXXXXXXXXXX'; const getSecret = async (secretName) => { const secret = await secretsManager.getSecretValue({ SecretId: secretName }).promise(); return JSON.parse(secret.SecretString); }; const logError = async (message) => { const params = { logGroupName, logStreamName, logEvents: [ { message: JSON.stringify(message), timestamp: Date.now() } ] }; try { await cloudwatchlogs.putLogEvents(params).promise(); } catch (error) { console.error('Failed to log to CloudWatch:', error); } }; const getJwtToken = async (keyId, issuerId, privateKeyPem) => { try { const privateKey = crypto.createPrivateKey({ key: privateKeyPem, format: 'pem', type: 'pkcs8' }); const payload = { iss: issuerId, exp: Math.floor(Date.now() / 1000) + 20 * 60, aud: 'appstoreconnect-v1' }; const token = await new jose.SignJWT(payload) .setProtectedHeader({ alg: 'ES256', kid: keyId }) .sign(privateKey); return token; } catch (error) { await logError({ error: 'Error generating JWT', details: error }); throw new Error('JWT generation failed'); } }; const fetchAndUploadReport = async (url, token, s3Key, isAnalytics = false, body = null) => { try { const headers = { 'Authorization': `Bearer ${token}`, 'Accept': isAnalytics ? 'application/json' : 'application/a-gzip', 'Content-Type': 'application/json' }; const response = await axios({ method: isAnalytics ? 'post' : 'get', url: url, headers: headers, data: body, responseType: isAnalytics ? 'json' : 'stream' }); if (response.status === 200) { let bodyContent = isAnalytics ? JSON.stringify(response.data) : response.data; await s3.upload({ Bucket: 'my_bucket_name', Key: s3Key, Body: bodyContent }).promise(); return { statusCode: 200, body: `${s3Key} fetched and uploaded successfully` }; } else { await logError({ error: 'API response error', status: response.status, statusText: response.statusText, url }); return { statusCode: response.status, body: response.statusText }; } } catch (error) { await logError({ error: 'Error fetching report', url, details: error }); return { statusCode: 500, body: JSON.stringify(`Error fetching ${s3Key}`) }; } }; exports.handler = async (event) => { const secretName = 'AppStoreConnectPrivateKey'; try { const secretData = await getSecret(secretName); const { keyId, issuerId, private_key: privateKeyPem } = secretData; const token = await getJwtToken(keyId, issuerId, privateKeyPem); const startDate = '2023-09-01'; const endDate = '2024-09-30'; const apiEndpoints = [ { url: `https://api.appstoreconnect.apple.com/v1/analyticsReportRequests`, // Changed to request report s3Key: 'my_folder/my_subfolder/unique_widget_installs.json', isAnalytics: true, body: { "data": { "type": "analyticsReportRequests", "attributes": { "accessType": "ONGOING", "name": "Home Screen Widget Installs", "category": "APP_USAGE" }, "relationships": { "app": { "data": { "type": "apps", "id": "YYYYYYYYYYYY" } } } } } } ]; Returns the following error : { "error": "Error fetching report", "url": "https://api.appstoreconnect.apple.com/v1/analyticsReportRequests", "details": { "message": "Request failed with status code 409", "name": "AxiosError", "stack": "AxiosError: Request failed with status code 409\n at settle (/var/task/node_modules/axios/dist/node/axios.cjs:2019:12)\n at IncomingMessage.handleStreamEnd (/var/task/node_modules/axios/dist/node/axios.cjs:3135:11)\n at IncomingMessage.emit (node:events:531:35)\n at IncomingMessage.emit (node:domain:488:12)\n at endReadableNT (node:internal/streams/readable:1696:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:82:21)\n at Axios.request (/var/task/node_modules/axios/dist/node/axios.cjs:4287:41)\n at process.processTicksAndRejections (node:internal/process/task_queues:95:5)\n at async fetchAndUploadReport (/var/task/index.js:68:26)\n at async Promise.all (index 0)\n at async exports.handler (/var/task/index.js:174:25)", "config": { "transitional": { "silentJSONParsing": true, "forcedJSONParsing": true, "clarifyTimeoutError": false }, "adapter": [ "xhr", "http", "fetch" ], "transformRequest": [ null ], "transformResponse": [ null ], "timeout": 0, "xsrfCookieName": "XSRF-TOKEN", "xsrfHeaderName": "X-XSRF-TOKEN", "maxContentLength": -1, "maxBodyLength": -1, "env": {}, So I am not sure if the JSON body I am passing this URL endpoint are correct or if this is the correct API to be using to attempt to obtain this information. Please let me know when you have the chance and I look forward to hearing from you.
0
0
315
Nov ’24
Can the Bundle ID Impact the Loading Time of a Pod/Framework?
Recent Incident with SDKAnalytics Version 11.11.4 We recently released version 11.11.4 of SDKAnalytics for use in the SuperApp. This update introduced several significant changes since the last generated version, 11.11.0. The previous version's primary change was the migration of the integration pipeline and its identifier from OQ6 to FW6. Additionally, we performed refactoring and adjustments to the project's configurations. In SDKAnalytics, we use XcodeGen to simplify project setup and minimize conflicts. We also rely on CocoaPods to create and manage our Pods/Frameworks. The SuperApp, where SDKAnalytics is implemented, operates as a centralized ecosystem. Its products and user journeys are segregated into Pods/Frameworks, distributed across multiple repositories, following a multi-repo structure. Currently, the app includes over 300 Pods. Starting from version 11.11.1 of our SDK, we implemented some important project changes. However, when we released version 11.11.4, which included a new feature for the SuperApp, we encountered a critical issue. Incident Overview All SDKs implemented in the SuperApp have their loading times monitored. After updating SDKAnalytics from version 11.11.0 to 11.11.4, the loading time spiked from 200 ms to 3000 ms. Faced with this significant impact, we launched a task force to investigate and resolve the issue. Investigation and Diagnosis After several days of investigation, we carefully reviewed the numerous pull requests merged between versions 11.11.0 and 11.11.4. As a strategy, we reverted the project.yml configurations from version 11.11.4 to match those of version 11.11.0. This rollback resolved the loading time issue, indicating that the problem stemmed from the project's configuration. Upon deeper analysis, we identified the culprit: a single line of configuration. The Bundle ID for the SuperApp follows the pattern com.companyname.enterprise. However, in version 11.11.4, SDKAnalytics adopted a new Bundle ID format: com.companyname.SDKAnalytics. This change directly impacted the SDKAnalytics loading time when implemented in the SuperApp. Solution To resolve the issue, we reverted this configuration. We modified the Bundle ID for SDKAnalytics to br.com.SDKAnalytics, removing the com.companyname prefix. After this change, the loading time returned to normal. Reflection The lingering question remains: What is the logical explanation for this discrepancy in loading time caused by the Bundle ID configuration? This behavior is unexpected, and we plan to investigate further to understand the underlying technical reasons.
0
1
447
Nov ’24
How to relocate CloudStorage root folder for user independent path
Dear Apple engineers, Is it possible to make a fileprovider cloud volume mount path independent of the user's home folder in order to have constant path across desktop clients when files are referenced / placed by applications like Adobe Creative Cloud ? Ideally mount or link the fileprovider cloud volume under /Volumes Thanks,
0
0
448
Nov ’24
Calling finish on an unfinishedTransaction doesn't work
So, we've implemented IAP with StoreKit2 e2e for both the client and backend and it's working mostly perfectly, however we have an issue which we can't seem to understand Apple's behavior. So, imagine a purchase that occurred on the 10th of December in the sandbox environment through an install from TestFlight, and this same purchase keeps getting queued in the Transaction.unfinished list for some reason (today, the 17th of December, a whole week after the initial purchase!). Here's the flow: We iterate the list on app launch Send the unfinishedTransaction's transactionId to our servers The server says "hey, we could verify it with Apple but it's not longer active (expired). We can't really work with it so just finish it on your side and don't send it to me again" The client finishes!! the transaction On the very next app launch it keeps reappearing in the Transaction.unfinished queue Are we doing something wrong, why doesn't it get cleaned? Is this an expected behavior? Note, this is generally the server's logic for new purchases: If we weren't able to contact Apple - we tell the client to not finish the transaction so that we'll be able to re-iterate it on the next app launch or retry If the transaction is not expired and valid - we update our records and tell the client to finish the transaction If we couldn't update our records - we tell the client to not finish the transaction so that we'll be able to re-iterate it on the next app launch or retry If the transaction is not valid for some reason - we tell the user to finish the transaction The server might see it as a valid transaction if we'll send the originalTransactionId instead of the 'transactionId(using it to callgetTransactionInfoinAppStoreServerLibrary`), but is this something we want to do? This will obviously not fix the problem because the server tells the client to finish the transaction anyways, but it simply doesn't work. Please, any advice or changes to make to either Client/Server would be greatly appreciated Best Regards, Ofek
0
0
280
Dec ’24
Using ApplePay to generate QR code
For instore payment, we are building payment app that would accept Applepay as method of payment and our payment gateway integration support Applepay. We are building this app for a Merchant based in Netherlands and wanted to check if there is any restriction in generating QR code that include apple pay payload and ask instore Cashier to scan the mobile QR using the barcode scanner to initial the transaction. Let me know if there is a restriction or limitation in generating the QR code to include Applepay payment details.
0
0
410
Nov ’24
Wallet is not highlighting boarding pass changes
Hi, I'm making changes in boarding pass through my webService and I changing Seat information but Wallet is not highlighting this information. Am I doing wrong? What do I need to do? Do need I inform anything? The request I do to silent push notification: apns-priority: 5 apns-topic: pass.**** apns-push-type: background { "aps": { "content-available": "1" } } Images links (before/after changes) https://ibb.co/0sPkbSZ https://ibb.co/rZR1jcC https://ibb.co/BCZKF1h https://ibb.co/zxQNGWW
0
0
292
Nov ’24
Can't ping ip address releated apple login
We want to support apple login in our application, and our domain has protection from public access, so we have followed document "Configuring your environment for Sign in with Apple" from Xcode ---> window --- > Developer Document to use ip connect to apple. when we ping the ip list in the document, like: 17.32.139.128/27 17.32.139.160/27 17.140.126.0/27 17.140.126.32/27 17.179.144.128/27 17.179.144.160/27 17.179.144.192/27 17.179.144.224/27 17.253.0.0/16 but they have no response. what's wrong with it? hope help!
0
0
167
Nov ’24