For information I stumbled upon a regression with SwiftUI Slider on iOS 26. Its onEditingChanged closure might be called twice when interaction ends, with a final Boolean incorrect value of true provided to the closure.
As a result apps cannot reliably rely on this closure to detect when an interaction with the slider starts or ends.
I filed a feedback under FB20283439 (iOS 26.0 regression: Slider onEditingChanged closure is unreliable).
Overview
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Created
I use [[SKPaymentQueue defaultQueue] restoreCompletedTransactions]. Works on my App which is in the store (compiled pre-iOS 26).
If I compile the same App now, same codebase with Xcode Version 26.0, restore does not work. Nothing happens. Tested on real device (iOS 26).
Documentation says its deprecated, but my deployment target is iOS 12.
Anyone has similar issues? Any recommendations?
Topic:
App & System Services
SubTopic:
StoreKit
Hello,
Are there any plans to compile a python 3.13 version of tensorflow-metal?
Just got my new Mac mini and the automatically installed version of python installed by brew is python 3.13 and while if I was in a hurry, I could manage to get python 3.12 installed and use the corresponding tensorflow-metal version but I'm not in a hurry.
Many thanks,
Alan
Hi,
I found a Bug in new Preview App on MacOS 26 release, while adding a new calendar entry.
If I click on a date inside a PDF file in Preview App, the calendar view pops and prompts to add a new calendar event. The background, which I guess should show the calendar, is showing a yellow screen. See images below.
This happens on both my M1 Air and M4 Pro Macbook.
Kind regards,
Lorenz
Topic:
Community
SubTopic:
Apple Developers
We would like to request an enhancement to Xcode Cloud workflows to support skipping builds when a GitHub Pull Request is in Draft state.
Our team frequently collaborates on pull requests that go through multiple iterations during the code review cycle. Each small commit or push triggers an Xcode Cloud workflow run, even if the PR is still in draft and not ready for final review or CI validation. This leads to:
Wasted compute resources and time on draft work that is not yet intended for integration.
Increased noise in Xcode Cloud logs and dashboards.
Longer feedback cycles for meaningful PRs, since draft workflows compete for available concurrency.
A simple option in the workflow configuration (e.g., “Skip runs for draft pull requests”) would address this problem by:
Reducing unnecessary workflow executions.
Freeing up capacity for production-ready and review-ready builds.
Improving overall developer productivity by aligning CI runs with the actual readiness of a PR.
This feature would be especially valuable for teams with frequent collaboration and long-lived PRs.
Thank you for considering this request—we believe it would significantly improve the efficiency of Xcode Cloud for real-world development workflows.
Hello, I am looking to develop a relationship with a developer that has experience running through the IOS build approval process. To elaborate, my team and I have designed and built a software application which is working through the Apple Developer review process to have the app approved and released to the App Store. Unfortunately, there has been some challenges, simple challenges in my eyes with our interface preventing Apple from approving our application. Happy to elaborate further.
A primary problem and solution I have seen is the software build was testing solely on the iPhone but as recently directed it seem the application must be accessible on iPad as well. With this the case, I have experience some software platforms where on the ipad the interface is not displayed on the whole screen. I am looking for direction on how to implement this setup for the 1st IOS build. Another concern from Apples Developer Review team is the App Tracking Transparency kit may need to be implemented.
I have some buttons. I set the bezelStyle to NSBezelStyleGlass.
I'm sometimes experiencing the following issue:
Put the system in dark mode.
Some glass buttons still draw with the light appearance.
One or more of the following actions usually makes the appearance redraw proper:
-Clicking the button
-Deactivating and then reactivating the window.
-Close and then reopen the window.
I tried setNeedsDisplay YES etc. but that didn't work
The delay is quite noticeable. Everything else is in dark mode except one or two glass buttons.
This seems to workaround the issue:
BOOL didToggleGlass = NO;
if (self.bezelStyle == NSBezelStyleGlass)
{
// Turn glass off just for a sec.
self.bezelStyle = NSBezelStyleToolbar;
didToggleGlass = YES;
}
if (didToggleGlass)
{
// Put glass back on.
self.bezelStyle = NSBezelStyleGlass;
}
Apparently toggling glass cause the effective appearance to change so you can't use the above workaround in a -viewDidChangeEffectiveAppearance b/c you'll create an infinite loop unless you guard against it.
(This only started happening as of Xcode 26.)
I know macOS and watchOS don't support this property, but all other platforms do (did?) up until I upgraded Xcode. Now when I compile I get this:
Value of type 'AVPlayerItem' has no member 'externalMetadata'
(Sorry if this is not the right place to post...)
I upgraded my iPad / macOS to 26 yesterday. Soon, I noticed that the two buttons in the toolbar would sometimes not appear:
Note that they should be visible at all times.
I played a little more to see if there was any pattern, but I could not find any. Has anyone experienced something similar...? Is this an iPadOS26 bug? (I haven't checked with an iPhone yet.)
Thanks.
Hello, this may not be the correct place to ask this question so I apologize in advance if this is the case.
We are currently having some issues when attempting to restore device back ups via iCloud that where previously enrolled to our MDM solution, as upon the restore no app data seems to be persisted over (we have tested restoring the backup on the same device and we have been able to have data persist between wipes)
On the initial device we have ensured that the restrictions
allowCloudKeychainSync
allowManagedAppsCloudSync
are set to true, and can see that the initial devices back up has the app data backed up, yet despite this data is not persisted when restoring from back up on a new device.
On the device where the back up was initially done when restoring the applications are applied but indicated that they must be re-installed via our management console, once the app has been uninstalled and reinstalled the old data does show up, when applied to the new device our mdm solution pushes down the app.managed config but the device treats it as a new install.
Could this possibly be due to us using Device Licensing when assigning apps? Or is it due to the intial device only performing a token update request when restoring and the new device going through the entire checkin proccess?
Both devices are provisioned via DEP, and applications where assigned initially via VPP
Any insight on this would be useful
(For reference this is an MDM solution of our own making so we are attempting to sus out if there is a configuration issue we could be overlooking).
Steps to Reproduce:
Connect a MacBook Pro (lid closed) to a large external monitor.
Run the SDL3 testwm test application.
git clone https://github.com/libsdl-org/SDL.git
cmake -S . -B build -DBUILD_SHARED_LIBS=OFF -DSDL_TESTS=ON
cmake --build build
The testwm binary will be located in the build/test directory.
Move the application window around the left edge of the external display.
Observed Result:
WindowServer crashes.
System Configuration:
MacBook Pro M3 Max, macOS Sequoia 15.6.1
LG GX9, 5120x2160 resolution, running at 165 Hz refresh rate
Lid closed, single external display
Panic Log:
panic(cpu 7 caller 0xfffffe0027f61d5c): "mismatched swapID's 6386399 vs 6386400\n" @UnifiedPipeline.cpp:14570
Debugger message: panic
Memory ID: 0xff
OS release type: User
OS version: 24G90
Kernel version: Darwin Kernel Version 24.6.0: Mon Jul 14 11:30:55 PDT 2025; root:xnu-11417.140.69~1/RELEASE_ARM64_T6031
Fileset Kernelcache UUID: 8AA69CD2038CD2BAE2ED364428F4DBEA
Kernel UUID: 75A21406-D046-3232-AA3F-085335D5C848
Boot session UUID: B949E839-683B-4DAF-BE42-4562758F976E
iBoot version: iBoot-11881.140.96
iBoot Stage 2 version: iBoot-11881.140.96
secure boot?: YES
roots installed: 0
Paniclog version: 14
KernelCache slide: 0x000000001e0ec000
KernelCache base: 0xfffffe00250f0000
Kernel slide: 0x000000001e0f4000
Kernel text base: 0xfffffe00250f8000
Kernel text exec slide: 0x000000001f870000
Kernel text exec base: 0xfffffe0026874000
mach_absolute_time: 0x64e7db3e6a9
Epoch Time: sec usec
Boot : 0x68b207f0 0x00082ee7
Sleep : 0x68c1a51c 0x00048c6c
Wake : 0x68c1a760 0x00039aa4
Calendar: 0x68c1b78d 0x0001776a
Zone info:
Zone map: 0xfffffe1018000000 - 0xfffffe3618000000
. VM : 0xfffffe1018000000 - 0xfffffe15e4000000
. RO : 0xfffffe15e4000000 - 0xfffffe187e000000
. GEN0 : 0xfffffe187e000000 - 0xfffffe1e4a000000
. GEN1 : 0xfffffe1e4a000000 - 0xfffffe2416000000
. GEN2 : 0xfffffe2416000000 - 0xfffffe29e2000000
. GEN3 : 0xfffffe29e2000000 - 0xfffffe2fae000000
. DATA : 0xfffffe2fae000000 - 0xfffffe3618000000
Metadata: 0xfffffe393c010000 - 0xfffffe3945810000
Bitmaps : 0xfffffe3945810000 - 0xfffffe394c104000
Extra : 0 - 0
CORE 0 recently retired instr at 0xfffffe0026a407a0
CORE 1 recently retired instr at 0xfffffe0026a40798
CORE 2 recently retired instr at 0xfffffe0026a407a0
CORE 3 recently retired instr at 0xfffffe0026a407a0
CORE 4 recently retired instr at 0xfffffe0026a407a0
CORE 5 recently retired instr at 0xfffffe0026a407a0
CORE 6 recently retired instr at 0xfffffe0026a407a0
CORE 7 recently retired instr at 0xfffffe0026a3eefc
CORE 8 recently retired instr at 0xfffffe0026a407a0
CORE 9 recently retired instr at 0xfffffe0026a407a0
CORE 10 recently retired instr at 0xfffffe0026a407a0
CORE 11 recently retired instr at 0xfffffe0026a407a0
CORE 12 recently retired instr at 0xfffffe0026a407a0
CORE 13 recently retired instr at 0xfffffe0026a407a0
TPIDRx_ELy = {1: 0xfffffe29e4ef5ee0 0: 0x0000000000001007 0ro: 0x000000016c59b0e0 }
CORE 0 PVH locks held: None
CORE 1 PVH locks held: None
CORE 2 PVH locks held: None
CORE 3 PVH locks held: None
CORE 4 PVH locks held: None
CORE 5 PVH locks held: None
CORE 6 PVH locks held: None
CORE 7 PVH locks held: None
CORE 8 PVH locks held: None
CORE 9 PVH locks held: None
CORE 10 PVH locks held: None
CORE 11 PVH locks held: None
CORE 12 PVH locks held: None
CORE 13 PVH locks held: None
CORE 0: PC=0xfffffe0026abfa40, LR=0xfffffe0026ae4fc8, FP=0xfffffe65b8703980
CORE 1: PC=0x0000000193ae2730, LR=0x000000019389d108, FP=0x000000016f43e590
CORE 2: PC=0xfffffe0026911e84, LR=0xfffffe0026911e84, FP=0xfffffe65b850bed0
CORE 3: PC=0xfffffe0026911e84, LR=0xfffffe0026911e84, FP=0xfffffe65b8ee7ed0
CORE 4: PC=0xfffffe0026911e84, LR=0xfffffe0026911e84, FP=0xfffffe65b7eebed0
CORE 5: PC=0xfffffe0026a3ac1c, LR=0xfffffe0026a3ac18, FP=0xfffffe65b8c63e40
CORE 6: PC=0xfffffe0026911e84, LR=0xfffffe0026911e84, FP=0xfffffe65b7033ed0
CORE 7 is the one that panicked. Check the full backtrace for details.
CORE 8: PC=0xfffffe0026a3ac1c, LR=0xfffffe0026a3ac18, FP=0xfffffe65b737be40
CORE 9: PC=0xfffffe0026911e84, LR=0xfffffe0026911e84, FP=0xfffffe65b8f1fed0
CORE 10: PC=0xfffffe0026911e84, LR=0xfffffe0026911e84, FP=0xfffffe65b7fe7ed0
CORE 11: PC=0xfffffe0026a3ac1c, LR=0xfffffe0026a3ac18, FP=0xfffffe65b870fe40
CORE 12: PC=0xfffffe0026911e84, LR=0xfffffe0026911e84, FP=0xfffffe65b80a7ed0
CORE 13: PC=0xfffffe0026a3ac1c, LR=0xfffffe0026a3ac18, FP=0xfffffe65b685fe40
Compressor Info: 6% of compressed pages limit (OK) and 16% of segments limit (OK) with 0 swapfiles and OK swap space
Panicked task 0xfffffe23153cb940: 10375 pages, 28 threads: pid 406: WindowServer
Panicked thread: 0xfffffe29e4ef5ee0, backtrace: 0xfffffe65b6f07210, tid: 5146
lr: 0xfffffe00268d53d4 fp: 0xfffffe65b6f072a0
lr: 0xfffffe0026a36da0 fp: 0xfffffe65b6f07310
lr: 0xfffffe0026a35114 fp: 0xfffffe65b6f073d0
lr: 0xfffffe002687f8b0 fp: 0xfffffe65b6f073e0
lr: 0xfffffe00268d5710 fp: 0xfffffe65b6f077b0
lr: 0xfffffe0027169290 fp: 0xfffffe65b6f077d0
lr: 0xfffffe0027f61d5c fp: 0xfffffe65b6f07850
lr: 0xfffffe0029186878 fp: 0xfffffe65b6f07880
lr: 0xfffffe00270bd2a0 fp: 0xfffffe65b6f078b0
lr: 0xfffffe00270bd5b0 fp: 0xfffffe65b6f07a40
lr: 0xfffffe0026a00194 fp: 0xfffffe65b6f07b60
lr: 0xfffffe00268dcd48 fp: 0xfffffe65b6f07c00
lr: 0xfffffe00268b2ed4 fp: 0xfffffe65b6f07c60
lr: 0xfffffe00268c6868 fp: 0xfffffe65b6f07cb0
lr: 0xfffffe00268c6c80 fp: 0xfffffe65b6f07da0
lr: 0xfffffe0026a29bbc fp: 0xfffffe65b6f07e50
lr: 0xfffffe0026a355a4 fp: 0xfffffe65b6f07f10
lr: 0xfffffe002687f8b0 fp: 0xfffffe65b6f07f20
lr: 0x000000018dc89c34 fp: 0x0000000000000000
Kernel Extensions in backtrace:
com.apple.iokit.IOMobileGraphicsFamily(343.0)[6C8CFA29-99CD-39D4-81BC-2B0F147BE64F]@0xfffffe002917d860->0xfffffe00291a024f
We’ve been approved for the Advanced Commerce API and are setting up the generic product identifiers per the guide:
https://developer.apple.com/documentation/advancedcommerceapi/setting-up-your-project-for-advanced-commerce#Set-up-generic-product-identifiers
We have multiple auto-renewable subscriptions (for simplicity: Product 1, Product 2, etc.). We created a new subscription group for Advanced Commerce and are about to add the subscription(s) inside that group.
Should we create one auto-renewable subscription (generic, e.g. subscription.ac) to represent all of our subscriptions, or one generic per product family (e.g., product1.ac, product2.ac, …)? If the answer depends on whether subscribers can hold multiple products simultaneously, please advise which structure supports that (e.g., separate groups).
Reporting identifiers / segmentation: In Sales and Trends and Payments & Financial Reports, which identifier(s) will appear after migration: the legacy StoreKit product_id, the new generic product id, and/or the SKU? If we use a single generic subscription for all products, what’s Apple’s recommended way to segment revenue by product (Product 1 vs. Product 2)? If SKUs don’t surface in these reports, should we prefer multiple generics/groups to preserve report-level segmentation?
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
In-App Purchase
Advanced Commerce API
I'm running into a refund issue when testing in-app purchases in sandbox mode. I'm able to successfully purchase items but roughly 1 out of 3 times, when the refund window pops up, it says it cannot connect even though our webhook servers can verify the transaction id sent from apple. My internet connection is good and I've varied the wait period from purchase to refund from 15mins to 2 hours. Any help would be greatly appreciated.
Topic:
App & System Services
SubTopic:
StoreKit
Hello! Some colleagues and work on Jujutsu, a version control system compatible with git, and I think we've uncovered a potential lock contention bug in either APFS or the Darwin kernel. There are four contributing factors to us thinking this is related to APFS or the Kernel:
jj's testsuite uses nextest, a test runner for Rust that spawns each individual test as a separate process.
The testsuite slowed down by a factor of ~5x on macOS after jj started using fsync. The slowdown increases as additional cores are allocated.
A similar slowdown did not occur on ext4.
Similar performance issues were reported in the past by a former Mercurial maintainer: https://gregoryszorc.com/blog/2018/10/29/global-kernel-locks-in-apfs/.
My friend and colleague André has measured the test suite on an M3 Ultra with both a ramdisk and a traditional SSD and produced this graph:
(The most thorough writeup is the discussion on this pull request.)
I know I should file a feedback/bug report, but before I do, I'm struggling with profiling and finding kernel/APFS frames in my profiles so that I can properly attribute the cause of this apparent lock contention. Naively, I ran xctrace record --template 'Time Profiler' --output output.trace --launch /Users/dbarsky/.cargo/bin/cargo-nextest nextest run, and while that detected all processes spawned by nextest, it didn't record all processes as part of the same inspectable profile and didn't really show any frames from the kernel/APFS—I had to select individual processes. So I don't waste people's time and so that I can point a frame/smoking gun in the right system, how can I can use instruments to profile where the kernel and/or APFS are spending its time? Do I need to disable SIP?
Can we Wrap a website in a React Native Web view and Make it live on iOS?
Here is an example code (Just a web application wrapped inside React Native )
import React, { useEffect, useRef, useState } from "react";
import { BackHandler, StyleSheet } from "react-native";
import { SafeAreaProvider, SafeAreaView } from "react-native-safe-area-context";
import { WebView } from "react-native-webview";
export default function App() {
const webviewRef = useRef<WebView>(null);
const [canGoBack, setCanGoBack] = useState(false);
// Handle Android back button
useEffect(() => {
const backHandler = BackHandler.addEventListener("hardwareBackPress", () => {
if (canGoBack && webviewRef.current) {
webviewRef.current.goBack();
return true; // prevent app exit
}
return false; // allow app exit
});
return () => backHandler.remove();
}, [canGoBack]);
return (
<SafeAreaProvider>
<SafeAreaView style={styles.container} edges={["top", "bottom", "left", "right"]}>
<WebView
ref={webviewRef}
source={{ uri: "https://www.kallardo.com/" }}
style={styles.webview}
startInLoadingState={true}
javaScriptEnabled={true}
domStorageEnabled={true}
onNavigationStateChange={(navState) => setCanGoBack(navState.canGoBack)}
/>
</SafeAreaView>
</SafeAreaProvider>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
webview: {
flex: 1,
},
});
I want to know will we get approval easier or makes it complicated or not allowed
Topic:
App Store Distribution & Marketing
SubTopic:
General
Tags:
App Store
App Store Connect
WebKit
This is a topic that’s come up a few times on the forums, so I thought I’d write up a summary of the issues I’m aware of. If you have questions or comments, start a new thread in the App & System Services > Networking subtopic and tag it with Network Extension. That way I’ll be sure to see it go by.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Network Extension Provider Packaging
There are two ways to package a network extension provider:
App extension ( appex )
System extension ( sysex )
Different provider types support different packaging on different platforms. See TN3134 Network Extension provider deployment for the details.
Some providers, most notably packet tunnel providers on macOS, support both appex and sysex packaging. Sysex packaging has a number of advantages:
It supports direct distribution, using Developer ID signing.
It better matches the networking stack on macOS. An appex is tied to the logged in user, whereas a sysex, and the networking stack itself, is global to the system as a whole.
Given that, it generally makes sense to package your Network Extension (NE) provider as a sysex on macOS. If you’re creating a new product that’s fine, but if you have an existing iOS product that you want to bring to macOS, you have to account for the differences brought on by the move to sysex packaging. Similarly, if you have an existing sysex product on macOS that you want to bring to iOS, you have to account for the appex packaging. This post summarises those changes.
Keep the following in mind while reading this post:
The information here applies to all NE providers that can be packaged as either an appex or a sysex. When this post uses a specific provider type in an example, it’s just an example.
Unless otherwise noted, any information about iOS also applies to iPadOS, tvOS, and visionOS.
Process Lifecycle
With appex packaging, the system typically starts a new process for each instance of your NE provider. For example, with a packet tunnel provider:
When the users starts the VPN, the system creates a process and then instantiates and starts the NE provider in that process.
When the user stops the VPN, the system stops the NE provider and then terminates the process running it.
If the user starts the VPN again, the system creates an entirely new process and instantiates and starts the NE provider in that.
In contrast, with sysex packaging there’s typically a single process that runs all off the sysex’s NE providers. Returning to the packet tunnel provider example:
When the users starts the VPN, the system instantiates and starts the NE provider in the sysex process.
When the user stops the VPN, the system stops and deallocates the NE provider instances, but leaves the sysex process running.
If the user starts the VPN again, the system instantiates and starts a new instances of the NE provider in the sysex process.
This lifecycle reflects how the system runs the NE provider, which in turn has important consequences on what the NE provider can do:
An appex acts like a launchd agent [1], in that it runs in a user context and has access to that user’s state.
A sysex is effectively a launchd daemon. It runs in a context that’s global to the system as a whole. It does not have access to any single user’s state. Indeed, there might be no user logged in, or multiple users logged in.
The rest of this post explores specific consequences of the NE provider lifecycle.
[1] It’s not actually run as a launchd agent. Rather, there’s a system launchd agent that acts as the host for the app extension.
App Groups
With an app extension, the app extension and its container app run as the same user. Thus it’s trivial to share state between them using an app group container.
Note When talking about extensions on Apple platforms, the container app is the app in which the extension is embedded and the host app is the app using the extension. For network extensions the host app is the system itself.
That’s not the case with a system extension. The system extension runs as root whereas the container app runs an the user who launched it. While both programs can claim access to the same app group, the app group container location they receive will be different. For the system extension that location will be inside the home directory for the root user. For the container app the location will be inside the home directory of the user who launched it.
This does not mean that app groups are useless in a Network Extension app. App groups are also a factor in communicating between the container app and its extensions, the subject of the next section.
IMPORTANT App groups have a long and complex history on macOS. For the full story, see App Groups: macOS vs iOS: Working Towards Harmony.
Communicating with Extensions
With an app extension there are two communication options:
App-provider messages
App groups
App-provider messages are supported by NE directly. In the container app, send a message to the provider by calling sendProviderMessage(_:responseHandler:) method. In the appex, receive that message by overriding the handleAppMessage(_:completionHandler:) method.
An appex can also implement inter-process communication (IPC) using various system IPC primitives. Both the container app and the appex claim access to the app group via the com.apple.security.application-groups entitlement. They can then set up IPC using various APIs, as explain in the documentation for that entitlement.
With a system extension the story is very different. App-provider messages are supported, but they are rarely used. Rather, most products use XPC for their communication. In the sysex, publish a named XPC endpoint by setting the NEMachServiceName property in its Info.plist. Listen for XPC connections on that endpoint using the XPC API of your choice.
Note For more information about the available XPC APIs, see XPC Resources.
In the container app, connect to that named XPC endpoint using the XPC Mach service name API. For example, with NSXPCConnection, initialise the connection with init(machServiceName:options:), passing in the string from NEMachServiceName. To maximise security, set the .privileged flag.
Note XPC Resources has a link to a post that explains why this flag is important.
If the container app is sandboxed — necessary if you ship on the Mac App Store — then the endpoint name must be prefixed by an app group ID that’s accessible to that app, lest the App Sandbox deny the connection. See app groups documentation for the specifics.
When implementing an XPC listener in your sysex, keep in mind that:
Your sysex’s named XPC endpoint is registered in the global namespace. Any process on the system can open a connection to it [1]. Your XPC listener must be prepared for this. If you want to restrict connections to just your container app, see XPC Resources for a link to a post that explains how to do that.
Your sysex only gets one named XPC endpoint, and thus one XPC listener. If your sysex includes multiple NE providers, take that into account when you design your XPC protocol.
[1] Assuming that connection isn’t blocked by some other mechanism, like the App Sandbox.
Inter-provider Communication
A sysex can include multiple types of NE providers. For example, a single sysex might include a content filter and a DNS proxy provider. In that case the system instantiates all of the NE providers in the same sysex process. These instances can communicate without using IPC, for example, by storing shared state in global variables (with suitable locking, of course).
It’s also possible for a single container app to contain multiple sysexen, each including a single NE provider. In that case the system instantiates the NE providers in separate processes, one for each sysex. If these providers need to communicate, they have to use IPC.
In the appex case, the system instantiates each provider in its own process. If two providers need to communicate, they have to use IPC.
Managing Secrets
An appex runs in a user context and thus can store secrets, like VPN credentials, in the keychain. On macOS this includes both the data protection keychain and the file-based keychain. It can also use a keychain access group to share secrets with its container app. See Sharing access to keychain items among a collection of apps.
Note If you’re not familiar with the different types of keychain available on macOS, see TN3137 On Mac keychain APIs and implementations.
A sysex runs in the global context and thus doesn’t have access to user state. It also doesn’t have access to the data protection keychain. It must use the file-based keychain, and specifically the System keychain. That means there’s no good way to share secrets with the container app.
Instead, do all your keychain operations in the sysex. If the container app needs to work with a secret, have it pass that request to the sysex via IPC. For example, if the user wants to use a digital identity as a VPN credential, have the container app get the PKCS#12 data and password and then pass that to the sysex so that it can import the digital identity into the keychain.
Memory Limits
iOS imposes strict memory limits an NE provider appexen [1]. macOS imposes no memory limits on NE provider appexen or sysexen.
[1] While these limits are not documented officially, you can get a rough handle on the current limits by reading the posts in this thread.
Frameworks
If you want to share code between a Mac app and its embedded appex, use a structure like this:
MyApp.app/
Contents/
MacOS/
MyApp
PlugIns/
MyExtension.appex/
Contents/
MacOS/
MyExtension
…
Frameworks/
MyFramework.framework/
…
There’s one copy of the framework, in the app’s Frameworks directory, and both the app and the appex reference it.
This approach works for an appex because the system always loads the appex from your app’s bundle. It does not work for a sysex. When you activate a sysex, the system copies it to a protected location. If that sysex references a framework in its container app, it will fail to start because that framework isn’t copied along with the sysex.
The solution is to structure your app like this:
MyApp.app/
Contents/
MacOS/
MyApp
Library/
SystemExtensions/
MyExtension.systemextension/
Contents/
MacOS/
MyExtension
Frameworks/
MyFramework.framework/
…
…
That is, have both the app and the sysex load the framework from the sysex’s Frameworks directory. When the system copies the sysex to its protected location, it’ll also copy the framework, allowing the sysex to load it.
To make this work you have to change the default rpath configuration set up by Xcode. Read Dynamic Library Standard Setup for Apps to learn how that works and then tweak things so that:
The framework is embedded in the sysex, not the container app.
The container app has an additional LC_RPATH load command for the sysex’s Frameworks directory (@executable_path/../Library/SystemExtensions/MyExtension.systemextension/Contents/Frameworks).
The sysex’s LC_RPATH load command doesn’t reference the container app’s Frameworks directory (@executable_path/../../../../Frameworks) but instead points to the sysex’s Framweorks directory (@executable_path/../Frameworks).
We have had 2 Builds so far stuck archiving. Both indicate in their logs that Build Archive took a normal amount of time (9m and 19m) but the step Archive - iOS never finished. One of them ran for more than 6 days until we noticed and canceled it. The other one ran for 18 hours, and also had to be canceled manually.
They were in two different projects, with no significant changes. The first build ran on Xcode 16.4 (16F6) and macOS Sequoia 15.6 (24G84), which we had had no issues like this with until just now, and the second ran on Xcode 26 (17A324) and macOS Tahoe 26 (25A354). We tested our app on the newest Xcode version and had no issues.
Submitted report using feedback assistant:
FB20279737.
Topic:
Developer Tools & Services
SubTopic:
Xcode Cloud
In my project, the window.rootViewController is a UITabBarController containing four UIViewControllers. The first, third, and fourth VCs are empty, while the second VC's view hierarchy is structured as follows:
UIViewController.view
├── UIScrollView (contentSize: self.view.width * 2, 0; backgroundColor: .red)
├── UIScrollView (contentSize: 0, self.view.height * 2; backgroundColor: .black)
└── UIScrollView (contentSize: 0, self.view.height * 2; backgroundColor: .white)
When I switch to the second tab and horizontally scroll the scrollView, the tabBar color doesn't adapt to the current view's dominant color. However, if I launch the app and sequentially tap every tab before switching to the second tab, the tabBar color then changes dynamically during horizontal scrolling. But if I background the app and return, the tabBar reverts to black.
Why does this happen? How can I either: Manually control the tabBar color, or Make it automatically match the page's dominant color?
This issue occurs when the "Reduce Transparency" accessibility setting is enabled.
Topic:
UI Frameworks
SubTopic:
UIKit
Hi,
I am developing the browser based on Chromium, which initially relies on the nw_browser stack for discovering locally available network resources.
We have observed an issue where, after each software update—specifically, whenever additional files are written into the application bundle—a popup appears requesting the user to allow local network access, even if this permission was already granted.
The behavior is reproducible: simply overwriting files in the app bundle (we are using rsync as Chromium), even while the application is already running, causes the prompt to reappear.
We have also noticed that Chromium itself exhibits the same behavior.
Also I found the mess in system settings, it has several Google Chrome for example: https://www.loom.com/share/da401f39ab134628807d77f1ca3185f5?from_recorder=1&focus_title=1
We would like to provide a smoother experience for our users and avoid confusing them with repeated permission prompts.
Could you please advise on possible approaches or best practices to improve our update mechanism in this regard?
The following code works properly, ensuring the list is scrolled at the correct ID when first rendered:
import SwiftUI
struct DataItem: Identifiable {
let id: Int
let height: CGFloat
init(id: Int) {
self.id = id
self.height = CGFloat.random(in: 100...300)
}
}
struct ContentView: View {
@State private var items = (0..<1000).map { DataItem(id: $0) }
@State private var scrollPosition: ScrollPosition
init() {
let mid = 500
_scrollPosition = State(initialValue: .init(id: mid, anchor: .center))
}
var body: some View {
ScrollView {
LazyVStack(spacing: 8) {
ForEach(items) { item in
Text("Item \(item.id)")
.frame(height: item.height)
.frame(maxWidth: .infinity)
.background(.gray)
}
}
.scrollTargetLayout()
}
.scrollPosition($scrollPosition, anchor: .center)
}
}
However, if I change this to use VStack this ceases to work - the list begins rendered at the top of the list. The only way I can render it starting at the correct position is using side effects like onAppear or task, where I would update the scroll position.
I have observed the following behavior on my iPhone 15 Pro/iOS 26. Is this a bug?
Topic:
UI Frameworks
SubTopic:
SwiftUI