General:
Forums subtopic: App & System Services > Networking
TN3151 Choosing the right networking API
Networking Overview document — Despite the fact that this is in the archive, this is still really useful.
TLS for App Developers forums post
Choosing a Network Debugging Tool documentation
WWDC 2019 Session 712 Advances in Networking, Part 1 — This explains the concept of constrained networking, which is Apple’s preferred solution to questions like How do I check whether I’m on Wi-Fi?
TN3135 Low-level networking on watchOS
TN3179 Understanding local network privacy
Adapt to changing network conditions tech talk
Understanding Also-Ran Connections forums post
Extra-ordinary Networking forums post
Foundation networking:
Forums tags: Foundation, CFNetwork
URL Loading System documentation — NSURLSession, or URLSession in Swift, is the recommended API for HTTP[S] on Apple platforms.
Network framework:
Forums tag: Network
Network framework documentation — Network framework is the recommended API for TCP, UDP, and QUIC on Apple platforms.
Building a custom peer-to-peer protocol sample code (aka TicTacToe)
Implementing netcat with Network Framework sample code (aka nwcat)
Configuring a Wi-Fi accessory to join a network sample code
Moving from Multipeer Connectivity to Network Framework forums post
Network Extension (including Wi-Fi on iOS):
See Network Extension Resources
Wi-Fi Fundamentals
TN3111 iOS Wi-Fi API overview
Wi-Fi Aware framework documentation
Wi-Fi on macOS:
Forums tag: Core WLAN
Core WLAN framework documentation
Wi-Fi Fundamentals
Secure networking:
Forums tags: Security
Apple Platform Security support document
Preventing Insecure Network Connections documentation — This is all about App Transport Security (ATS).
Available trusted root certificates for Apple operating systems support article
Requirements for trusted certificates in iOS 13 and macOS 10.15 support article
About upcoming limits on trusted certificates support article
Apple’s Certificate Transparency policy support article
What’s new for enterprise in iOS 18 support article — This discusses new key usage requirements.
Technote 2232 HTTPS Server Trust Evaluation
Technote 2326 Creating Certificates for TLS Testing
QA1948 HTTPS and Test Servers
Miscellaneous:
More network-related forums tags: 5G, QUIC, Bonjour
On FTP forums post
Using the Multicast Networking Additional Capability forums post
Investigating Network Latency Problems forums post
WirelessInsights framework documentation
iOS Network Signal Strength
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Foundation
RSS for tagAccess essential data types, collections, and operating-system services to define the base layer of functionality for your app using Foundation.
Posts under Foundation tag
200 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
For ages, we've been using appStoreReceiptUrl to detect if the app was installed from TestFlight or not, but now that's deprecated. Since we have a strict policy of no warnings on the project, we need to find a way to check if the app was installed from TestFlight or from the App Store. Does anyone know what's the new way to do so?
I thought about using MarketplaceKit.AppDistributor.testFlight but to use MarketplaceKit you need to jump through hoops that our app really doesn't need to - we don't distribute outside of the App Store.
Any ideas are much appreciated! 🙏
Topic:
App Store Distribution & Marketing
SubTopic:
TestFlight
Tags:
Foundation
App Store
TestFlight
我正在使用 Core Data 开发一个 SwiftUI 项目。我的数据模型中有一个名为 AppleUser 的实体,具有以下属性:id (UUID)、name (String)、email (String)、password (String) 和 createdAt (Date)。所有属性都是非可选的。
我使用 Xcode 的自动生成创建了相应的 Core Data 类文件(AppleUser+CoreDataClass.swift 和 AppleUser+CoreDataProperties.swift)。我还有一个 PersistenceController,它使用模型名称 JobLinkModel 初始化 NSPersistentContainer。
当我尝试使用以下方法保存新的 AppleUser 对象时:
让用户 = AppleUser(上下文:viewContext)
user.id = UUID()
user.name = “用户 1”
user.email = “...”
user.password = “密码 1”
user.createdAt = Date()【电子邮件格式正确,但已替换为“...”出于隐私原因】
尝试?viewContext.save()
我在控制台中收到以下错误:核心数据保存失败:Foundation._GenericObjCError.nilError, [:]
用户快照: [“id”: ..., “name”: “User1”, “email”: “...”, “password”: “...”, “createdAt”: ...]
所有字段都有有效值,核心数据模型似乎正确。我还尝试过:
• 检查 NSPersistentContainer(name:) 中的模型名称是否与 .xcdatamodeld 文件 (JobLinkModel) 匹配
• 确保正确设置 AppleUser 实体类、模块和 Codegen(类定义、当前产品模块)
• 删除重复或旧的 AppleUser 类文件
• 清理 Xcode 构建文件夹并从模拟器中删除应用程序
• 对上下文使用 @Environment(.managedObjectContext)
尽管如此,在保存新的 AppleUser 对象时,我仍然会收到 _GenericObjCError.nilError。
我想了解:
为什么即使所有字段都不是零且正确分配,核心数据也无法保存?
这可能是由于一些残留的旧类文件引起的,还是我缺少设置中的其他内容?
我应该采取哪些步骤来确保 Core Data 正确识别 AppleUser 实体并允许保存?
任何帮助或指导将不胜感激。
Topic:
App Store Distribution & Marketing
SubTopic:
General
Tags:
Foundation
Swift Packages
Design
Accounts
A user of my app brought to my attention that unless they select their ~/Library/Mail folder explicitly in an open panel, they get an error when scanning it inside my app. I can confirm that I also get a permission error when trying to scan it as a subfolder of ~/Library, but not if I select it directly.
I'm assuming this is intentional, but it would be nice to have an explanation or some documentation that I can point my users to when they encounter what appears to them as a bug in my app. What makes this matter even more confusing is that selecting a folder in any open panel of an app gives the app access to it for the lifetime of the app, but after restarting the app, access is lost again (unless it has a bookmark to it). This was probably the reason why the user thought that it worked in another app but not in mine.
This is the code I use to scan:
let openPanel = NSOpenPanel()
openPanel.canChooseDirectories = true
if openPanel.runModal() == .cancel {
return
}
let enumerator = FileManager.default.enumerator(at: openPanel.urls[0], includingPropertiesForKeys: nil) { url, error in
print(url.path, error)
return true
}
while let url = enumerator?.nextObject() as? URL {
}
And this the error related to the Mail folder:
~/Library/Mail Error Domain=NSCocoaErrorDomain Code=257 "The file “Mail” couldn’t be opened because you don’t have permission to view it." UserInfo={NSURL=file:///~/Library/Mail, NSFilePath=/~/Library/Mail, NSUnderlyingError=0x600002991470 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}
With the RC version of macOS 26, an issue persists when you try to create a bookmark with security scope for the root folder "/". This leads to an error "The file couldn’t be opened.". However, you can create bookmark for /Applications, /System, /Users...
This is quite annoying for one of my app because a user can create a cartography of his disk usage, and the access to the root folder "/" is the only way to do so!
Is there a workaround?
PS: reported the issue with ID FB20186406
let openPanel = NSOpenPanel()
openPanel.canChooseDirectories = true
openPanel.canChooseFiles = false
openPanel.beginSheetModal(for: self.view.window!) { (result) in
guard result == .OK, let folderURL = openPanel.url else {
return
}
openPanel.close()
do {
let data = try folderURL.bookmarkData(options: .withSecurityScope, includingResourceValuesForKeys: nil, relativeTo: nil)
print("Bookmark data was created for \(folderURL.path)")
} catch (let error) {
print("Error creating bookmark for \(folderURL.path), with error: \(error.localizedDescription)")
}
}
Greetings,
With MacOS 15 Sequoia, Apple updated key-value-observations in such a way, that an unremoved observation by a now deallocated object will no longer cause an exception, when the observed object triggers said observation.
While this is fundamentally a positive change, the issue comes with the fact, that this change affects systems based on the version of their operating system and not the version of the operating system of the build system.
Many of our customers use old operating system versions and old hardware - meaning they can't easily update. Since we need to use up to date Xcode versions to develop for newer systems, our developers tend to have rather new OS versions.
This means, that we are increasingly facing bugs which only happen in customer systems but not in most developer (or QA) systems.
Currently, we still can use earlier OS versions with Xcode to fix these bugs, but once the used Xcode versions no longer support MacOS 14 or below this will become a major hurdle.
Are there known solutions to this issue?
We are currently attempting to swizzle observer adding and removal in order to fix the problem for old systems as well, but this has proven to be quite difficult and unstable. Since any weakly held property in the middle of an observation keypath can cause crashes, one would have to split up observations into multiple subobservations, which is less simple than it sounds, due to custom implementations of addObserver (such as there seems to be in array controller proxies) and collection operators.
Thanks for any suggestions!
Problem summary
I have a macOS helper app that is launched from a sandboxed main app. The helper:
has com.apple.security.app-sandbox = true and com.apple.security.inherit = true in its entitlements,
is signed and embedded inside the main app bundle (placed next to the main executable in Contents/MacOS),
reports entitlement_check = 1 (code signature contains sandbox entitlement, implemented via SecStaticCode… check),
sandbox_check(getpid(), NULL, 0) returns 1 (runtime sandbox enforcement present),
APP_SANDBOX_CONTAINER_ID environment variable is not present (0).
Despite that, Cocoa APIs return non-container home paths:
NSHomeDirectory() returns /Users/<me>/ (the real home).
[[NSFileManager defaultManager] URLsForDirectory:inDomains:] and
URLForDirectory:inDomain:appropriateForURL:create:error: return paths rooted at /Users/<me>/ (not under ~/Library/Containers/<app_id>/Data/...) — i.e. they look like non-sandboxed locations.
However, one important exception: URLForDirectory:... for NSItemReplacementDirectory (temporary/replacement items) does return a path under the helper's container (example: ~/Library/Containers/<app_id>/Data/tmp/TemporaryItems/NSIRD_<helper_name>_hfc1bZ).
This proves the sandbox is active for some FileManager APIs, yet standard directory lookups (Application Support, Documents, Caches, and NSHomeDirectory()) are not being redirected to the container.
What I expect
The helper (which inherits the sandbox and is clearly sandboxed) should get container-scoped paths from Cocoa’s FileManager APIs (Application Support, Documents, Caches), i.e. paths under the helper’s container: /Users/<me>/Library/Containers/<app_id>/Data/....
What I tried / diagnostics already gathered
Entitlements & code signature
codesign -d --entitlements :- /path/to/Helper.app/Contents/MacOS/Helper
# shows com.apple.security.app-sandbox = true and com.apple.security.inherit = true
Runtime checks (Objective-C++ inside helper):
extern "C" int sandbox_check(pid_t pid, const char *op, int flags);
NSLog(@"entitlement_check = %d", entitlement_check()); // SecStaticCode check
NSLog(@"env_variable_check = %d", (getenv("APP_SANDBOX_CONTAINER_ID") != NULL));
NSLog(@"runtime_sandbox_check = %d", sandbox_check(getpid(), nullptr, 0));
NSLog(@"NSHomeDirectory = %s", NSHomeDirectory());
NSArray *urls = [[NSFileManager defaultManager]
URLsForDirectory:NSApplicationSupportDirectory
inDomains:NSUserDomainMask];
NSLog(@"URLsForDirectory: %@", urls);
Observed output:
entitlement_check = 1
env_variable_check = 0
runtime_sandbox_check = 1
NSHomeDirectory = /Users/<me>
URLsForDirectory: ( "file:///Users/<me>/Library/Application%20Support/..." )
Temporary/replacement directory (evidence sandbox active for some APIs):
NSURL *tmpReplacement = [[NSFileManager defaultManager]
URLForDirectory:NSItemReplacementDirectory
inDomain:NSUserDomainMask
appropriateForURL:nil
create:YES
error:&err];
NSLog(@"NSItemReplacementDirectory: %@", tmpReplacement.path);
Observed output (example):
/Users/<me>/Library/Containers/<app_id>/Data/tmp/TemporaryItems/NSIRD_<helper_name>_hfc1bZ
Other facts
Calls to NSHomeDirectory() and URLsForDirectory: are made after main() to avoid "too early" initialization problems.
Helper is placed in Contents/MacOS (not Contents/Library/LoginItems).
Helper is a non-GUI helper binary launched by the main app (not an XPC service).
macOS version: Sequoia 15.6
Questions
Why do NSHomeDirectory() and URLsForDirectory: return the real /Users/<me>/... paths in a helper process that is clearly sandboxed (entitlement + runtime enforcement), while NSItemReplacementDirectory returns a container-scoped temporary path?
Is this behavior related to how the helper is packaged or launched (e.g., placement in Contents/MacOS vs Contents/Library/LoginItems, or whether it is launched with posix_spawn/fork+exec vs other APIs)?
Are there additional entitlements or packaging rules required for a helper that inherits sandbox to have Cocoa directory APIs redirected to the container (for Application Support, Documents, Caches)?
*Thanks in advance — I can add any requested logs
Hi everyone, I'm using an app group to share data between iOS and it's watch companion app.
I ensured that is has the same identifier in Signing & Capabilities and in the .entitlements files.
Here is the UserDefaults part:
class UserDefaultsManager {
private let suitName = "group.com.sanjeevbalakrishnan.Test"
public func saveItems(_ items: [ItemDTO]) {
print("Save \(items.count) items to shared defaults")
let defaults = UserDefaults(suiteName: suitName)
let data = try? JSONEncoder().encode(items)
defaults?.set(data, forKey: "items")
}
public func loadItems() -> [ItemDTO] {
let defaults = UserDefaults(suiteName: suitName)
print(defaults)
guard let data = defaults?.data(forKey: "items") else {
print("watchOS received data is empty")
return []
}
let items = [ItemDTO].from(data: data)
print("Load \(items.count) items from user defaults")
return items
}
}
For testing I called loadItems after saveItems on iOS app and it returned items. However, on watchOS app it always returns empty array.
What do I need to consider?
Thanks.
Best regards
Sanjeev
A user of my app noticed that when using it to move a file to the trash on an USB drive, the trash doesn't show the file until unmounting the drive and mounting it again. I was able to reproduce it with one of my own USB drives, but with another USB drive it doesn't reproduce. All USB drives are formatted APFS.
When moving a file to the trash from the Finder, both USB drives immediately list it in the trash. Is this a macOS bug, or am I doing something wrong?
I created FB19941168.
let openPanel = NSOpenPanel()
openPanel.runModal()
let url = openPanel.urls[0]
do {
var result: NSURL?
try FileManager.default.trashItem(at: url, resultingItemURL: &result)
print(result as Any)
} catch {
fatalError(error.localizedDescription)
}
I have created a sample app which read/write from a network file. When the file was attempted to open (using open Linux API), connection to network file was lost. The thread which was stuck on the open method, returns after a long time.
It was observed that for macOS, the maximum return time of the thread was around 10 mins, whereas in Windows and Linux, the maximum timeout was 60 sec and 90 sec.
macOS has a very large timeout before returning the thread with a network failure error. Is this by designed and expected? With a large timeout as 10mins, it's difficult to respond swiftly back to the user.
Hi,
I encountered the following error while trying to launch a video game developed with Unity and running on an iPhone 12 and iPhone 16 Pro.
Native StackTrace:
Thread 2 (crashed)
0 libsystem_kernel.dylib 0x00000001d40102ec <symbols missing for uuid: 21ee5290d1193c31b948431865a67738>
1 libsystem_c.dylib 0x000000019330fba0 <symbols missing for uuid: 7135c2c8ba5836368b46a9e6226ead45>
2 UnityFramework 0x000000010e7bc744 <symbols missing for uuid: 4c1540b0ca733555aa69fc3e514204a3>
3 UnityFramework 0x000000010dc1c22c <symbols missing for uuid: 4c1540b0ca733555aa69fc3e514204a3>
4 UnityFramework 0x000000010cc26da4 <symbols missing for uuid: 4c1540b0ca733555aa69fc3e514204a3>
5 CoreFoundation 0x000000018b4af984 <symbols missing for uuid: 76a3b1983c09323e83590d4978e156f5>
6 libobjc.A.dylib 0x0000000183277140
7 libc++abi.dylib 0x00000001e7d20068
8 libc++abi.dylib 0x00000001e7d2000c
9 libdispatch.dylib 0x0000000193256de8 <symbols missing for uuid: 5f66cdb608a936158c6a4e3b47005495>
10 libdispatch.dylib 0x000000019325e400 <symbols missing for uuid: 5f66cdb608a936158c6a4e3b47005495>
11 libdispatch.dylib 0x000000019325ef30 <symbols missing for uuid: 5f66cdb608a936158c6a4e3b47005495>
12 libdispatch.dylib 0x0000000193269cb4 <symbols missing for uuid: 5f66cdb608a936158c6a4e3b47005495>
13 libdispatch.dylib 0x0000000193269528 <symbols missing for uuid: 5f66cdb608a936158c6a4e3b47005495>
14 libsystem_pthread.dylib 0x00000001e7e00934
15 libsystem_pthread.dylib 0x00000001e7dfd0cc
I have a UIKit app where I've adopted SwiftData and I'm struggling with a crash coming in from some of my users. I'm not able to reproduce it myself and as it only happens to a small fraction of my user base, it seems like a race condition of some sort.
This is the assertion message:
SwiftData/DefaultStore.swift:453: Fatal error: API Contract Violation: Editors must register their identifiers before invoking operations on this store SwiftData.DefaultStore: 00CF060A-291A-4E79-BEC3-E6A6B20F345E did not. (ID is unique per crash)
This is the ModelActor that crashes:
@available(iOS 17, *)
@ModelActor
actor ConsumptionDatabaseStorage: ConsumptionSessionStorage {
struct Error: LocalizedError {
var errorDescription: String?
}
private let sortDescriptor = [SortDescriptor(\SDConsumptionSession.startTimeUtc, order: .reverse)]
static func createStorage(userId: String) throws -> ConsumptionDatabaseStorage {
guard let appGroupContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: UserDefaults.defaultAppGroupIdentifier) else {
throw Error(errorDescription: "Invalid app group container ID")
}
func createModelContainer(databaseUrl: URL) throws -> ModelContainer {
return try ModelContainer(for: SDConsumptionSession.self, SDPriceSegment.self, configurations: ModelConfiguration(url: databaseUrl))
}
let databaseUrl = appGroupContainer.appendingPathComponent("\(userId).sqlite")
do {
return self.init(modelContainer: try createModelContainer(databaseUrl: databaseUrl))
} catch {
// Creating the model storage failed. Remove the database file and try again.
try? FileManager.default.removeItem(at: databaseUrl)
return self.init(modelContainer: try createModelContainer(databaseUrl: databaseUrl))
}
}
func isStorageEmpty() async -> Bool {
(try? self.modelContext.fetchCount(FetchDescriptor<SDConsumptionSession>())) ?? 0 == 0 // <-- Crash here!
}
func sessionsIn(interval: DateInterval) async throws -> [ConsumptionSession] {
let fetchDescriptor = FetchDescriptor(predicate: #Predicate<SDConsumptionSession> { sdSession in
if let startDate = sdSession.startTimeUtc {
return interval.start <= startDate && interval.end > startDate
} else {
return false
}
}, sortBy: self.sortDescriptor)
let consumptionSessions = try self.modelContext.fetch(fetchDescriptor) // <-- Crash here!
return consumptionSessions.map { ConsumptionSession(swiftDataSession: $0) }
}
func updateSessions(sessions: [ConsumptionSession]) async throws {
if #unavailable(iOS 18) {
// Price segments are duplicated if re-inserted so unfortunately we have to delete and reinsert sessions.
// On iOS 18, this is enforced by the #Unique macro on SDPriceSegment.
let sessionIds = Set(sessions.map(\.id))
try self.modelContext.delete(model: SDConsumptionSession.self, where: #Predicate<SDConsumptionSession> {
sessionIds.contains($0.id)
})
}
for session in sessions {
self.modelContext.insert(SDConsumptionSession(consumptionSession: session))
}
if self.modelContext.hasChanges {
try self.modelContext.save()
}
}
func deleteAllSessions() async {
if #available(iOS 18, *) {
try? self.modelContainer.erase()
} else {
self.modelContainer.deleteAllData()
}
}
}
The actor conforms to this protocol:
protocol ConsumptionSessionStorage {
func isStorageEmpty() async -> Bool
func hasCreditCardSessions() async -> Bool
func sessionsIn(interval: DateInterval) async throws -> [ConsumptionSession]
func updateSessions(sessions: [ConsumptionSession]) async throws
func deleteAllSessions() async
}
The crash is coming in from line 30 and 41, in other words, when trying to fetch data from the database. There doesn't seem to be any common trait for the crashes. They occur across iOS versions and device types.
Any idea what might cause this?
We observed a new crash after upgrading to iOS 18.
This crash does not occur on iOS 17 or earlier.
Crash Stacks From Xcode Organizer
CoreFoundation: __CFRunLoopServiceMachPort + 160
2. CoreFoundation: __CFRunLoopServiceMachPort.cold.1 + 64
Crash Stacks From APM
In release mode, the values are missing. I don't know what's wrong with it. If I install the debug version first and then overwrite it with the release build, I can retrieve the values stored in debug mode. But if I uninstall completely and install the release version directly, it's empty
App initiates a App group based UserDefaults within the willFinishLaunchingWithOptions method and the same reference are used throughout the app life cycle
+ (NSUserDefaults *)appGroupUserDefaults
{
if (_appGroupUserDefaults == nil)
{
NSString *appGroupIdentifier = [NSString stringWithFormat:@"group.%@",[[NSBundle mainBundle] bundleIdentifier]];
NSUserDefaults *groupDefaults = [[NSUserDefaults standardUserDefaults] initWithSuiteName:appGroupIdentifier];
if(groupDefaults != nil)
{
NSLog(@"[DB_ENCRYPTION] appGroupUserDefaults initialised");
_appGroupUserDefaults = groupDefaults;
}
else
{
NSLog(@"<ALA_ERROR>: [CCF-OS] [DB_ENCRYPTION] %s Unable to create NSUSerDefaults with groupIdentifier", __func__);
_appGroupUserDefaults = [NSUserDefaults standardUserDefaults];
}
}
return _appGroupUserDefaults;
}
Doesn't have any issues on accessing the values but seen the below console error:
Couldn't read values in CFPrefsPlistSource<0x103eedb00> (Domain: group.com.kodiak.InstaPoC, User: kCFPreferencesAnyUser, ByHost: Yes, Container: (null), Contents Need Refresh: Yes): Using kCFPreferencesAnyUser with a container is only allowed for System Containers, detaching from cfprefsd
Does it require any action here ?
I have an app which uses ubiquitous containers and files in them to share data between devices. It's a bit unusual in that it indexes files in directories the user grants access to, which may or may not exist on a second device - those files are identified by SHA-1 hash. So a second device scanning before iCloud data has fully sync'd can create duplicate references which lead to an unpleasant user experience.
To solve this, I store a small binary index in the root of the ubiquitous file container of the shared data, containing all of the known hashes, and as the user proceeds through the onboarding process, a background thread is attempting to "prime" the ubiquitous container by calling FileManager.default.startDownloadingUbiquitousItemAt() for each expected folder and file in a sane order.
This likely creates a situation not anticipated by the iOS/iCloud integration's design, as it means my app has a sort of precognition of files it should not yet know about.
In the common case, it works, but there is a corner case where iCloud sync has just begun, and very, very little metadata is available (the common case, however, in an emulator), in which two issues come up:
I/O may hang indefinitely, trying to read a file as it is arriving. This one I can work around by running the I/O in a thread created with the POSIX pthread_create and using pthread_cancel to kill it after a timeout.
Attempts to call FileManager.default.startDownloadingUbiquitousItemAt() fails with an error Error Domain=NSCocoaErrorDomain Code=257 "The file couldn’t be opened because you don’t have permission to view it.". The permissions aspect of it is nonsense, but I can believe there's no applicable "sort of exists, sort of doesn't" error code to use and someone punted. The problem is that this same error will be thrown on any attempt to access that file for the life of the application - a restart is required to make it usable.
Clearly, the error or the hallucinated permission failure is cached somewhere in the bowels of iOS's FileManager. I was hoping startAccessingSecurityScopedResource() would allow me to bypass such a cache, as it does with URL.resourceValues() returning stale file sizes and last modified times. But it does not.
Is there some way to clear this state without popping up a UI with an Exit button (not exactly the desired iOS user experience)?
Topic:
App & System Services
SubTopic:
iCloud & Data
Tags:
Foundation
Files and Storage
iOS
iCloud Drive
We are building a hybrid iOS app using Angular (web) rendered inside a WKWebView, hosted by a native Swift app. Communication between the Angular UI and native Swift code is done using WKScriptMessageHandler.
The app mostly works without issues, but in rare edge cases, we’re seeing crashes on the main thread, and the crash is reported in Firebase Crashlytics. The root cause appears related to CFRelease and WKScriptMessageHandler.
Here’s the relevant crash stack:
Crashed: com.apple.main-thread
0 CoreFoundation 0xbfac CFRelease + 44
1 CoreFoundation 0xa734 __CFURLDeallocate + 128
2 CoreFoundation 0x730c _CFRelease + 292
3 libobjc.A.dylib 0x4e28 AutoreleasePoolPage::releaseUntil(objc_object**) + 204
4 libobjc.A.dylib 0x4cbc objc_autoreleasePoolPop + 260
5 WebKit 0x99f194 WebKit::WebUserContentControllerProxy::didPostMessage(WTF::ObjectIdentifierGeneric<WebKit::WebPageProxyIdentifierType, WTF::ObjectIdentifierMainThreadAccessTraits<unsigned long long>, unsigned long long>, WebKit::FrameInfoData&&, WTF::ObjectIdentifierGeneric<WebKit::ScriptMessageHandlerIdentifierType, WTF::ObjectIdentifierMainThreadAccessTraits<unsigned long long>, unsigned long long>, std::__1::span<unsigned char const, 18446744073709551615ul>, WTF::CompletionHandler<void (std::__1::span<unsigned char const, 18446744073709551615ul>, WTF::String const&)>&&) + 680
6 WebKit 0x1b358 WebKit::WebUserContentControllerProxy::didReceiveMessage(IPC::Connection&, IPC::Decoder&) + 392
7 WebKit 0xe86b0 IPC::MessageReceiverMap::dispatchMessage(IPC::Connection&, IPC::Decoder&) + 272
8 WebKit 0x23c0c WebKit::WebProcessProxy::didReceiveMessage(IPC::Connection&, IPC::Decoder&) + 44
9 WebKit 0xe3f054 IPC::Connection::dispatchMessage(WTF::UniqueRef<IPC::Decoder>) + 252
10 WebKit 0x332d4 IPC::Connection::dispatchIncomingMessages() + 744
11 JavaScriptCore 0x58a7c WTF::RunLoop::performWork() + 204
12 JavaScriptCore 0x599a4 WTF::RunLoop::performWork(void*) + 36
13 CoreFoundation 0x56328 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28
14 CoreFoundation 0x562bc __CFRunLoopDoSource0 + 176
15 CoreFoundation 0x53dc0 __CFRunLoopDoSources0 + 244
16 CoreFoundation 0x52fbc __CFRunLoopRun + 840
17 CoreFoundation 0x52830 CFRunLoopRunSpecific + 588
18 GraphicsServices 0x11c4 GSEventRunModal + 164
19 UIKitCore 0x3d2eb0 -[UIApplication _run] + 816
20 UIKitCore 0x4815b4 UIApplicationMain + 340
21 APP1 0xa2f80 main + 21 (AppDelegate.swift:21)
22 ??? 0x1c234eec8 (シンボルが不足しています)
Steps:
WebView: WKWebView
Message passing: WKScriptMessageHandler → passing data from Angular → Swift
WKWebView is long-lived and reused
Native is using WKUserContentController.add(_:name:) to register handlers
Crashes are intermittent (hard to reproduce), but often follow:
Screen sleep/wake
Push notification open
Angular calling native immediately after resume
Questions:
Has anyone seen this specific crash pattern involving CFRelease and WKScriptMessageHandler?
Are there known WebKit or CoreFoundation bugs related to WKScriptMessageHandler and retained URLs or message content?
Thank you for your help!
content = try String(contentsOfFile: filepath) is the following warning.
'init(contentsOfFile:)' was deprecated in iOS 18: Use init(contentsOfFile:encoding:) instead
After internet searching I could find an answer.
I would appreciate a rewrite of my code line to get rid of 31 warnings.
Thanks a LOT
Charlie
I am seeing a weird behavior of the date formatter (Full code is below).
When run, this will give the following output:
57: 1 month, 3 weeks, 5 days
58: 1 month, 3 weeks, 6 days
59: 2 months
60: 2 months, 1 day
61: 2 months
62: 2 months, 1 day
63: 2 months, 2 days
So both 59 days and 61 days are 2 months, and both 60 and 62 days are 2 months and 1 day.
This of course is especially weird because this means, 2 months also comes after 2 months and a day.
Can someone explain to me what is going on here?
import Foundation
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full
let calendar = Calendar(identifier: .gregorian)
let today = calendar.date(from: DateComponents(year: 2025, month: 7, day: 26))!
for day in 57...63 {
let startDate = calendar.date(byAdding: .day, value: -day, to: today)!
let components = calendar.dateComponents([.day, .weekOfMonth, .month,. year], from: startDate, to: today)
let result = formatter.string(from: components)!
print ("\(String(format: "%3d", day)): \(result)")
}
When the iPhone is set to 12-hour time format, obtaining a timestamp similar to "2025-07-18 16:29:00" fails
I have discovered a gap in my understanding of user selected URLs in iOS, and I would be grateful if someone can put me right please.
My understanding is that a URL selected by a user can be accessed by calling url.startAccessingSecurityScopedResource() call. Subsequently a call to stopAccessingSecurityScopedResource() is made to avoid sandbox memory leaks.
Furthermore, the URL can be saved as a bookmark and reconstituted when the app is run again to avoid re-asking permission from the user.
So far so good.
However, I have discovered that a URL retrieved from a bookmark can be accessed without the call to url.startAccessingSecurityScopedResource(). This seems contrary to what the documentation says here
So my question is (assuming this is not a bug) why not save and retrieve the URL immediately in order to avoid having to make any additional calls to url.startAccessingSecurityScopedResource?
Bill Aylward
You can copy and paste the code below into a new iOS project to illustrate this. Having chosen a folder, the 'Summarise folder without permission' button fails as expected, but once the 'Retrieve URL from bookmark' has been pressed, it works fine.
import SwiftUI
import UniformTypeIdentifiers
struct ContentView: View {
@AppStorage("bookmarkData") private var bookmarkData: Data?
@State private var showFolderPicker = false
@State private var folderUrl: URL?
@State private var folderReport: String?
var body: some View {
VStack(spacing: 20) {
Text("Selected folder: \(folderUrl?.lastPathComponent ?? "None")")
Text("Contents: \(folderReport ?? "Unknown")")
Button("Select folder") {
showFolderPicker.toggle()
}
Button("Deselect folder") {
folderUrl = nil
folderReport = nil
bookmarkData = nil
}
.disabled(folderUrl == nil)
Button("Retrieve URL from bookmark") {
retrieveFolderURL()
}
.disabled(bookmarkData == nil)
Button("Summarise folder with permission") {
summariseFolderWithPermission(true)
}
.disabled(folderUrl == nil)
Button("Summarise folder without permission") {
summariseFolderWithPermission(false)
}
.disabled(folderUrl == nil)
}
.padding()
.fileImporter(
isPresented: $showFolderPicker,
allowedContentTypes: [UTType.init("public.folder")!],
allowsMultipleSelection: false
) { result in
switch result {
case .success(let urls):
if let selectedUrl = urls.first {
print("Processing folder: \(selectedUrl)")
processFolderURL(selectedUrl)
}
case .failure(let error):
print("\(error.localizedDescription)")
}
}
.onAppear() {
guard folderUrl == nil else { return }
retrieveFolderURL()
}
}
func processFolderURL(_ selectedUrl: URL?) {
guard selectedUrl != nil else { return }
// Create and save a security scoped bookmark in AppStorage
do {
guard selectedUrl!.startAccessingSecurityScopedResource() else { print("Unable to access \(selectedUrl!)"); return }
// Save bookmark
bookmarkData = try selectedUrl!.bookmarkData(options: .minimalBookmark, includingResourceValuesForKeys: nil, relativeTo: nil)
selectedUrl!.stopAccessingSecurityScopedResource()
} catch {
print("Unable to save security scoped bookmark")
}
folderUrl = selectedUrl!
}
func retrieveFolderURL() {
guard let bookmarkData = bookmarkData else {
print("No bookmark data available")
return
}
do {
var isStale = false
let url = try URL(
resolvingBookmarkData: bookmarkData,
options: .withoutUI,
relativeTo: nil,
bookmarkDataIsStale: &isStale
)
folderUrl = url
} catch {
print("Error accessing URL: \(error.localizedDescription)")
}
}
func summariseFolderWithPermission(_ permission: Bool) {
folderReport = nil
print(String(describing: folderUrl))
guard folderUrl != nil else { return }
if permission { print("Result of access requrest is \(folderUrl!.startAccessingSecurityScopedResource())") }
do {
let contents = try FileManager.default.contentsOfDirectory(atPath: folderUrl!.path)
folderReport = "\(contents.count) files, the first is: \(contents.first!)"
} catch {
print(error.localizedDescription)
}
if permission { folderUrl!.stopAccessingSecurityScopedResource() }
}
}