I have a Swift 3 Cocoa application that uses Apple's Unified Logging, like this: - import os
class MyClass
{
@available(OSX 10.12, *)
static let scribe = OSLog(subsystem: "com.mycompany.myapp", category: "myapp")
func SomeFunction(){
if #available(OSX 10.12, *){
os_log("Test Error Message", log: MyClass.scribe, type: .error)
}
if #available(OSX 10.12, *){
os_log("Test Info Message", log: MyClass.scribe, type: .info)
}
if #available(OSX 10.12, *){
os_log("Test Debug Message", log: MyClass.scribe, type: .debug)
}
}
}Within the Console application, both Include Info Messages and Include Debug Messages are turned on.When os_log is called, only the error type message is visible in the Console application.Using Terminal, with the command, all message types are visible in the Terminal output: -sudo log stream --level debugI've tried running the Console app as root, via sudo from the command line and the same issue occurs; no debug or info messages can be seen, even though they're set to being turned on under the Action menu.Setting system-wide logging to be debug, has no effect on the Console application output:sudo log config --mode level:debugPlease can someone tell me what I'm missing and how can I view debug and info messages in the Console application?
Core OS
RSS for tagExplore the core architecture of the operating system, including the kernel, memory management, and process scheduling.
Post
Replies
Boosts
Views
Activity
The UIApplication background task mechanism allows you to prevent your app from being suspended for short periods of time. While the API involved is quite small, there’s still a bunch of things to watch out for.
The name background task is somewhat misappropriate. Specifically, beginBackgroundTask(expirationHandler:) doesn’t actually start any sort of background task, but rather it tells the system that you have started some ongoing work that you want to continue even if your app is in the background. You still have to write the code to create and manage that work. So it’s best to think of the background task API as raising a “don’t suspend me” assertion.
You must end every background task that you begin. Failure to do so will result in your app being killed by the watchdog. For this reason I recommend that you attach a name to each background task you start (by calling beginBackgroundTask(withName:expirationHandler:) rather than beginBackgroundTask(expirationHandler:)). A good name is critical for tracking down problems when things go wrong.
IMPORTANT Failing to end a background task is the number one cause of background task problems on iOS. This usually involves some easy-to-overlook error in bookkeeping that results in the app begining a background task and not ending it. For example, you might have a property that stores your current background task identifier (of type UIBackgroundTaskIdentifier). If you accidentally creates a second background task and store it in that property without calling endBackgroundTask on the identifier that’s currently stored there, the app will ‘leak’ a background task, something that will get it killed by the watchdog. One way to avoid this is to wrap the background task in an object; see the QRunInBackgroundAssertion post on this thread for an example.
Background tasks can end in one of two ways:
When your app has finished doing whatever it set out to do.
When the system calls the task’s expiry handler.
Your code is responsible for calling endBackgroundTask(_:) in both cases.
All background tasks must have an expiry handler that the system can use to ‘call in’ the task. The background task API allows the system to do that at any time.
Your expiry handler is your opportunity to clean things up. It should not return until everything is actually cleaned up. It must run quickly, that is, in less than a second or so. If it takes too long, your app will be killed by the watchdog.
Your expiry handler is called on the main thread.
It is legal to begin and end background tasks on any thread, but doing this from a secondary thread can be tricky because you have to coordinate that work with the expiry handler, which is always called on the main thread.
The system puts strict limits on the total amount of time that you can prevent suspension using background tasks. On current systems you can expect about 30 seconds.
IMPORTANT I’m quoting these numbers just to give you a rough idea of what to expect. The target values have changed in the past and may well change in the future, and the amount of time you actually get depends on the state of the system. The thing to remember here is that the exact value doesn’t matter as long as your background tasks have a functional expiry handler.
You can get a rough estimate of the amount of time available to you by looking at UIApplication’s backgroundTimeRemaining property.
IMPORTANT The value returned by backgroundTimeRemaining is an estimate and can change at any time. You must design your app to function correctly regardless of the value returned. It’s reasonable to use this property for debugging but we strongly recommend that you avoid using as part of your app’s logic.
IMPORTANT Basing app behaviour on the value returned by backgroundTimeRemaining is the number two cause of background task problems on iOS.
The system does not guarantee any background task execution time. It’s possible (albeit unlikely, as covered in the next point) that you’ll be unable to create a background task. And even if you do manage to create one, its expiry handler can be called at any time.
beginBackgroundTask(expirationHandler:) can fail, returning UIBackgroundTaskInvalid, to indicate that you the system is unable to create a background task. While this was a real possibility when background tasks were first introduced, where some devices did not support multitasking, you’re unlikely to see this on modern systems.
The background time ‘clock’ only starts to tick when the background task becomes effective. For example, if you start a background task while the app is in the foreground and then stay in the foreground, the background task remains dormant until your app moves to the background. This can help simplify your background task tracking logic.
The amount of background execution time you get is a property of your app, not a property of the background tasks themselves. For example, starting two background task in a row won’t give you 60 seconds of background execution time.
Notwithstanding the previous point, it can still make sense to create multiple background tasks, just to help with your tracking logic. For example, it’s common to create a background task for each job being done by your app, ending the task when the job is done.
Do not create too many background tasks. How many is too many? It’s absolutely fine to create tens of background tasks but creating thousands is not a good idea.
IMPORTANT iOS 11 introduced a hard limit on the number of background task assertions a process can have (currently about 1000, but the specific value may change in the future). If you see a crash report with the exception code 0xbada5e47, you’ve hit that limit.
Note The practical limit that you’re most likely to see here is the time taken to call your expiry handlers. The watchdog has a strict limit (a few seconds) on the total amount of time taken to run background task expiry handlers. If you have thousands of handlers, you may well run into this limit.
If you’re working in a context where you don’t have access to UIApplication (an app extension or on watchOS) you can achieve a similar effect using the performExpiringActivity(withReason:using:) method on ProcessInfo.
If your app ‘leaks’ a background task, it may end up being killed by the watchdog. This results in a crash report with the exception code 0x8badf00d (“ate bad food”).
IMPORTANT A leaked background task is not the only reason for an 0x8badf00d crash. You should look at the backtrace of the main thread to see if the main thread is stuck in your code, for example, in a synchronous networking request. If, however, the main thread is happily blocked in the run loop, a leaked background task should be your primary suspect.
Prior to iOS 11 information about any outstanding background tasks would appear in the resulting crash report (look for the text BKProcessAssertion). This information is not included by iOS 11 and later, but you can find equivalent information in the system log.
The system log is very noisy so it’s important that you give each of your background tasks an easy-to-find name.
For more system log hints and tips, see Your Friend the System Log.
iOS 13 introduced the Background Tasks framework. This supports two type of requests:
The BGAppRefreshTaskRequest class subsumes UIKit’s older background app refresh functionality.
The BGProcessingTaskRequest class lets you request extended background execution time, typically overnight.
WWDC 2020 Session 10063 Background execution demystified is an excellent summary of iOS’s background execution model. Watch it, learn it, love it!
For more background execution hints and tips, see Background Tasks Resources.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Revision History
2023-06-16 Added a link to my QRunInBackgroundAssertion post.
2022-06-08 Corrected a serious error in the discussion of BGProcessingTaskRequest. Replaced the basic system log info with a reference to Your Friend the System Log. Added a link to Background Tasks Resources. Made other minor editorial changes.
2021-02-27 Fixed the formatting. Added a reference to the Background Tasks framework and the Background execution demystified WWDC presentation. Minor editorial changes.
2019-01-20 Added a note about changes in the iOS 13 beta. Added a short discussion about beginning and ending background tasks on a secondary thread.
2018-02-28 Updated the task name discussion to account for iOS 11 changes. Added a section on how to debug ‘leaked’ background tasks.
2017-10-31 Added a note about iOS 11’s background task limit.
2017-09-12 Numerous updates to clarify various points.
2017-08-17 First posted.
I'm trying to read the contents of a file on the filesystem in a macOS Swift app (Xcode 9 / Swift 4).I'm using the following snippet for it:let path = "/my/path/string.txt"
let s = try! String(contentsOfFile: path)
print(s)My problem is the following:1. This works in a Playground2. This works when I use the Command Line Tool macOS app template3. This terminates in a permission error when I use the Cocoa App macOS app templateThe permission error is the following:Fatal error: 'try!' expression unexpectedly raised an error:
Error Domain=NSCocoaErrorDomain Code=257 "The file "data.txt" couldn't be opened because you don't have permission to view it."
UserInfo={NSFilePath=/my/path/data.txt, NSUnderlyingError=0x60c0000449b0 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}I guess it's related to sandboxing but I found no information about it.1. How can I read from the filesystem in a sandboxed app? I mean there are so many GUI apps which need an Open File dialog, it cannot be a realistic restriction of sandboxed apps to not read files from outside the sandbox.2. Alternatively, how can I switch off sandboxing in Build Settings?3. Finally, I tried to compare the project.pbxproj files between the default Cocoa Apps and Command Line Tool template and I didn't see any meaningful difference, like something about security or sandbox. If not here, where are those settings stored?
I have successfully implemented Universal Links so that a visitor to specific URLs on our site is redirected to one of our apps. It all works well. Alarmingly well, in that it all worked perfectly first time. (I blame the documentation).
A question I can't find specifically addressed in the documentation is: what if we have two apps that can both handle a given link? This is in fact our situation.
In most cases users will have one or other of the apps installed. The correct behaviour would then be to direct the user to the installed app.
In some cases the user will have both apps installed. In that case the ideal behaviour would be to direct the user to what we have defined to be the "main" app.
It looks to me as if it is possible to two apps in an apple-app-site-association file, but not having found this in the documentation, I wonder: has anyone on here actually tried this? Did it work as expected?
Hi all, I'm looking for the specifications for the accelerometers used in current iPhone and iPad devices, including the sensitivity and the update rates possible.
Despite the documentation saying it's 100Hz, I've not yet found it to be better than 50Hz on any of iPhone SE, 8 or 11, nor iPad mini or Pros.
Any help would be much appreciated!
A
To join the Universal App Quick Start Program, you must be the Account Holder for the Apple Developer Account. Can the Account Holder then bestow access to Quick Start Program resources/private forums to other members of the organization? We have many people who can make use of this information, none of whom have access to the Account Holder account.
I guess this is appropriate here since Big Sur is still in development
Yesterday I created a new APFS partition with macOS Big Sur. I usually edit some files in /System/Library files to tweak my home setup to my liking, including some display settings. However the steps I usually take to be able to edit these files no longer work.
These steps were: Boot the Mac in recovery mode and go to the terminal,
Here I disable SIP using csrutil disable,
Reboot back in to Recovery Mode, open the terminal again
Remount the disk with write permissions using mount -uw /
Make the edits
However step 4 no longer seems to work on Big Sur as I am getting an error:
mount_apfs: volume could not be mounted: Permission denied
mount: / failed with 66
Is there another way to mount the file system with write permissions?
We have a test tool our engineers use to launch various versions of our application during development and verification. Each daily build of our application is stored on a server. As well, each push of a change generates a new build of our application that is stored on a server. These are added to a database and the developer application accesses the server via REST to find the desired version to run, retrieves a server path and launches the application. This tool is valuable in finding pushes that introduced regressions.
The developer application (Runner) is using the launchApplicationAtURL:options:configuration:error: (deprecated I know) to launch the app. Prior to Catalina, this was working great. However, as of Catalina, this process is taking a VERY long time due to the app needing to be "verified". the app seems to need to be copied to the users machine and verified. It only occurs the first launch, but as most of the time the users are running new push or daily builds, it has made the app useless. With the new remote work environment it is even worse as VPN copy can take forever.
I have switched to using NSTask with a shell script to open the executable in the bundle. If I add the developer tool (Runner) to the Developer Tools in Privacy this seems to launch the application without the need for verification. However this just seems wrong. It also provides little feedback to know when the application is up and running, which makes my user experience poor. As well many of the systems we use this tool on for verification do not have Developer Tools installed. They are VMs.
Is there a way for me to use the launchApplicationAtURL:options:configuration:error: (or the new openApplicationAtURL:configuration:completionHandler:) to launch these versions of the application without the need for the lengthy verification process? Adding our application to the Developer Tools did not seem to help.
Prior to iOS 14 our Dev server was routing universal links to our test devices just fine from both Xcode and TestFlight builds. But now that we've started testing on iOS 14 devices the links aren't being handled any more.
After doing some research we noticed the new configuration regarding Associated Domains for web servers that aren't reachable from the public internet.
https://developer.apple.com/documentation/safariservices/supporting_associated_domains
Starting with macOS 11 and iOS 14, apps no longer send requests for apple-app-site-association files directly to your web server. Instead, they send these requests to an Apple-managed content delivery network (CDN) dedicated to associated domains. While you’re developing your app, if your web server is unreachable from the public internet, you can use the alternate mode feature to bypass the CDN and connect directly to your private domain.You enable an alternate mode by adding a query string to your associated domain’s entitlement as follows:
<service>:<fully qualified domain>?mode=<alternate mode>
Given our Dev server is only reachable via a VPN we changed our project config to use the alternate mode:
<key>com.apple.developer.associated-domains</key>
<array>
<string>webcredentials:ourDevServerURL?mode=developer</string>
<string>applinks:ourDevServerURL?mode=developer</string>
</array>
But unfortunately that still doesn't work and in the console we can see the following swcd logs being generated after a fresh app install.
debug com.apple.swc 11:45:19.016561-0600 swcd entry Skipping domain si….va….com?mode=developer because developer mode is disabled
So what else do we need to get developer mode working for these app links?
We are building an iOS app that connects to a device using Bluetooth. To test unhappy flow scenarios for this app, we'd like to power cycle the device we are connecting to by using an IoT power switch that connects to the local network using WiFi (a Shelly Plug-S).
In my test code on iOS13, I was able to do a local HTTP call to the IP address of the power switch and trigger a power cycle using its REST interface. In iOS 14 this is no longer possible, probably due to new restrictions regarding local network usage without permissions (see: https://developer.apple.com/videos/play/wwdc2020/10110 ).
When running the test and trying a local network call to the power switch in iOS14, I get the following error:
Task <D206B326-1820-43CA-A54C-5B470B4F1A79>.<2> finished with error [-1009] Error Domain=NSURLErrorDomain Code=-1009 "The internet connection appears to be offline." UserInfo={_kCFStreamErrorCodeKey=50, NSUnderlyingError=0x2833f34b0 {Error Domain=kCFErrorDomainCFNetwork Code=-1009 "(null)" UserInfo={_kCFStreamErrorCodeKey=50, _kCFStreamErrorDomainKey=1}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <D206B326-1820-43CA-A54C-5B470B4F1A79>.<2>, _NSURLErrorRelatedURLSessionTaskErrorKey=("LocalDataTask <D206B326-1820-43CA-A54C-5B470B4F1A79>.<2>"), NSLocalizedDescription=The internet connection appears to be offline., NSErrorFailingURLStringKey=http://192.168.22.57/relay/0?turn=on, NSErrorFailingURLKey=http://192.168.22.57/relay/0?turn=on, _kCFStreamErrorDomainKey=1}
An external network call (to google.com) works just fine in the test.
I have tried fixing this by adding the following entries to the Info.plist of my UI test target:
<key>NSLocalNetworkUsageDescription</key>
<string>Local network access is needed for tests</string>
<key>NSBonjourServices</key>
<array>
<string>_http._tcp</string>
</array>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
However, this has no effect.
I have also tried adding these entries to the Info.plist of my app target to see if that makes a difference, but it doesn't. I'd also rather not add these entries to my app's Info.plist, because the app does not need local network access. Only the test does.
Does anyone know how to enable local network access during an iOS UI test in iOS14?
Hello, I have an app that talks with physical device over Wi-Fi.
The app can send commands and receives a stream of data from it. This commutation happens over Wi-Fi (which has no access to the internet)
As a result OS will throw Wi-Fi Assist alert, and offer switch to cellular data.
How to avoid this alert? In my scenario if user disconnects from Wi-Fi, he loses access to physical device.
In About Wi-Fi Assist - https://support.apple.com/en-us/HT205296 it is mentioned
Wi-Fi Assist doesn’t activate with some third-party apps that stream audio or video, or download attachments, like an email app, as they might use large amounts of data.
Well my app does download large amount of data from the device. Could my app be eligible for this exception?
Modern versions of macOS use a file system permission model that’s far more complex than the traditional BSD rwx model, and this post is my attempt at explaining that model. If you have a question about this, post it here on DevForums. Put your thread in the App & System Services > Core OS topic area and tag it with Files and Storage.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
On File System Permissions
Modern versions of macOS have four different file system permission mechanisms:
Traditional BSD permissions
Access control lists (ACLs)
App Sandbox
Mandatory access control (MAC)
The first two were introduced a long time ago and rarely trip folks up. The second two are newer, more complex, and specific to macOS, and thus are the source of some confusion. This post is my attempt to clear that up.
Error Codes
App Sandbox and the mandatory access control system are both implemented using macOS’s sandboxing infrastructure. When a file system operation fails, check the error to see whether it was blocked by this sandboxing infrastructure. If an operation was blocked by BSD permissions or ACLs, it fails with EACCES (Permission denied, 13). If it was blocked by something else, it’ll fail with EPERM (Operation not permitted, 1).
If you’re using Foundation’s FileManager, these error are both reported as Foundation errors, for example, the NSFileReadNoPermissionError error. To recover the underlying error, get the NSUnderlyingErrorKey property from the info dictionary.
App Sandbox
File system access within the App Sandbox is controlled by two factors. The first is the entitlements on the main executable. There are three relevant groups of entitlements:
The com.apple.security.app-sandbox entitlement enables the App Sandbox. This denies access to all file system locations except those on a built-in allowlist (things like /System) or within the app’s containers.
The various “standard location” entitlements extend the sandbox to include their corresponding locations.
The various “file access temporary exceptions” entitlements extend the sandbox to include the items listed in the entitlement.
Collectively this is known as your static sandbox.
The second factor is dynamic sandbox extensions. The system issues these extensions to your sandbox based on user behaviour. For example, if the user selects a file in the open panel, the system issues a sandbox extension to your process so that it can access that file. The type of extension is determined by the main executable’s entitlements:
com.apple.security.files.user-selected.read-only results in an extension that grants read-only access.
com.apple.security.files.user-selected.read-write results in an extension that grants read/write access.
Note There’s currently no way to get a dynamic sandbox extension that grants executable access. For all the gory details, see this post.
These dynamic sandbox extensions are tied to your process; they go away when your process terminates. To maintain persistent access to an item, use a security-scoped bookmark. See Accessing files from the macOS App Sandbox. To pass access between processes, use an implicit security scoped bookmark, that is, a bookmark that was created without an explicit security scope (no .withSecurityScope flag) and without disabling the implicit security scope (no .withoutImplicitSecurityScope flag)).
If you have access to a directory — regardless of whether that’s via an entitlement or a dynamic sandbox extension — then, in general, you have access to all items in the hierarchy rooted at that directory. This does not overrule the MAC protection discussed below. For example, if the user grants you access to ~/Library, that does not give you access to ~/Library/Mail because the latter is protected by MAC.
Finally, the discussion above is focused on a new sandbox, the thing you get when you launch a sandboxed app from the Finder. If a sandboxed process starts a child process, that child process inherits its sandbox from its parent. For information on what happens in that case, see the Note box in Enabling App Sandbox Inheritance.
IMPORTANT The child process inherits its parent process’s sandbox regardless of whether it has the com.apple.security.inherit entitlement. That entitlement exists primarily to act as a marker for App Review. App Review requires that all main executables have the com.apple.security.app-sandbox entitlement, and that entitlements starts a new sandbox by default. Thus, any helper tool inside your app needs the com.apple.security.inherit entitlement to trigger inheritance. However, if you’re not shipping on the Mac App Store you can leave off both of these entitlement and the helper process will inherit its parent’s sandbox just fine. The same applies if you run a built-in executable, like /bin/sh, as a child process.
When the App Sandbox blocks something, it typically generates a sandbox violation report. For information on how to view these reports, see Discovering and diagnosing App Sandbox violations.
To learn more about the App Sandbox, see the various links in App Sandbox Resources. For information about how to embed a helper tool in a sandboxed app, see Embedding a Command-Line Tool in a Sandboxed App.
Mandatory Access Control
Mandatory access control (MAC) has been a feature of macOS for many releases, but it’s become a lot more prominent since macOS 10.14. There are many flavours of MAC but the ones you’re most likely to encounter are:
Full Disk Access (macOS 10.14 and later)
Files and Folders (macOS 10.15 and later)
App container protection (macOS 14 and later)
App group container protection (macOS 15 and later)
Data Vaults (see below) and other internal techniques used by various macOS subsystems
Mandatory access control, as the name suggests, is mandatory; it’s not an opt-in like the App Sandbox. Rather, all processes on the system, including those running as root, as subject to MAC.
Data Vaults are not a third-party developer opportunity. See this post if you’re curious.
In the Full Disk Access and Files and Folders cases, users grant a program a MAC privilege using System Settings > Privacy & Security. Some MAC privileges are per user (Files and Folders) and some are system wide (Full Disk Access). If you’re not sure, run this simple test:
On a Mac with two users, log in as user A and enable the MAC privilege for a program.
Now log in as user B. Does the program have the privilege?
If a process tries to access an item restricted by MAC, the system may prompt the user to grant it access there and then. For example, if an app tries to access the desktop, you’ll see an alert like this:
“AAA” would like to access files in your Desktop folder.
[Don’t Allow] [OK]
To customise this message, set Files and Folders properties in your Info.plist.
This system only displays this alert once. It remembers the user’s initial choice and returns the same result thereafter. This relies on your code having a stable code signing identity. If your code is unsigned, or signed ad hoc (“Signed to Run Locally” in Xcode parlance), the system can’t tell that version N+1 of your code is the same as version N, and thus you’ll encounter excessive prompts.
Note For information about how that works, see TN3127 Inside Code Signing: Requirements.
The Files and Folders prompts only show up if the process is running in a GUI login session. If not, the operation is allowed or denied based on existing information. If there’s no existing information, the operation is denied by default.
For more information about app and app group container protection, see the links in Trusted Execution Resources. For more information about app groups in general, see App Groups: macOS vs iOS: Fight!
On managed systems the site admin can use the com.apple.TCC.configuration-profile-policy payload to assign MAC privileges.
For testing purposes you can reset parts of TCC using the tccutil command-line tool. For general information about that tool, see its man page. For a list of TCC service names, see the posts on this thread.
Note TCC stands for transparency, consent, and control. It’s the subsystem within macOS that manages most of the privileges visible in System Settings > Privacy & Security. TCC has no API surface, but you see its name in various places, including the above-mentioned configuration profile payload and command-line tool, and the name of its accompanying daemon, tccd.
While tccutil is an easy way to do basic TCC testing, the most reliable way to test TCC is in a VM, restoring to a fresh snapshot between each test. If you want to try this out, crib ideas from Testing a Notarised Product.
The MAC privilege mechanism is heavily dependent on the concept of responsible code. For example, if an app contains a helper tool and the helper tool triggers a MAC prompt, we want:
The app’s name and usage description to appear in the alert.
The user’s decision to be recorded for the whole app, not that specific helper tool.
That decision to show up in System Settings under the app’s name.
For this to work the system must be able to tell that the app is the responsible code for the helper tool. The system has various heuristics to determine this and it works reasonably well in most cases. However, it’s possible to break this link. I haven’t fully research this but my experience is that this most often breaks when the child process does something ‘odd’ to break the link, such as trying to daemonise itself.
If you’re building a launchd daemon or agent and you find that it’s not correctly attributed to your app, add the AssociatedBundleIdentifiers property to your launchd property list. See the launchd.plist man page for the details.
Scripting
MAC presents some serious challenges for scripting because scripts are run by interpreters and the system can’t distinguish file system operations done by the interpreter from those done by the script. For example, if you have a script that needs to manipulate files on your desktop, you wouldn’t want to give the interpreter that privilege because then any script could do that.
The easiest solution to this problem is to package your script as a standalone program that MAC can use for its tracking. This may be easy or hard depending on the specific scripting environment. For example, AppleScript makes it easy to export a script as a signed app, but that’s not true for shell scripts.
TCC and Main Executables
TCC expects its bundled clients — apps, app extensions, and so on — to use a native main executable. That is, it expects the CFBundleExecutable property to be the name of a Mach-O executable. If your product uses a script as its main executable, you’re likely to encounter TCC problems. To resolve these, switch to using a Mach-O executable. For an example of how you might do that, see this post.
Revision History
2024-11-08 Added info about app group container protection. Clarified that Data Vaults are just one example of the techniques used internally by macOS. Made other editorial changes.
2023-06-13 Replaced two obsolete links with links to shiny new official documentation: Accessing files from the macOS App Sandbox and Discovering and diagnosing App Sandbox violations. Added a short discussion of app container protection and a link to WWDC 2023 Session 10053 What’s new in privacy.
2023-04-07 Added a link to my post about executable permissions. Fixed a broken link.
2023-02-10 In TCC and Main Executables, added a link to my native trampoline code. Introduced the concept of an implicit security scoped bookmark. Introduced AssociatedBundleIdentifiers. Made other minor editorial changes.
2022-04-26 Added an explanation of the TCC initialism. Added a link to Viewing Sandbox Violation Reports. Added the TCC and Main Executables section. Made significant editorial changes.
2022-01-10 Added a discussion of the file system hierarchy.
2021-04-26 First posted.
I see that UIScribbleInteractionDelegate has scribbleInteraction(_:shouldBeginAt:) that you can always return false from in order to disable scribble. Is there any way to disable it in a website via javascript or dom attributes?
sudo ifconfig en0 ether [MAC address]
Now results in
ifconfig: ioctl (SIOCAIFADDR): Can't assign requested address
I regularly see questions, both here on DevForums and in my Day Job™ at DTS, that are caused by a fundamental misunderstanding of how background execution works on iOS. These come in many different variants, for example:
How do I keep my app running continuously in the background?
If I schedule a timer, how do I get it to fire when the screen is locked?
How do I run code in the background every 15 minutes?
How do I set up a network server that runs in the background?
How can my app provide an IPC service to another one of my apps while it’s in the background?
How can I resume my app in the background if it’s been ‘force quit’ by the user?
The short answer to all of these is You can’t. iOS puts strict limits on background execution. Its default behaviour is to suspend your app shortly after the user has moved it to the background; this suspension prevents the process from running any code.
There’s no general-purpose mechanism for:
Running code continuously in the background
Running code at some specific time in the background
Running code periodically at a guaranteed interval
Resuming in the background in response to a network or IPC request
However, iOS does provide a wide range of special-purpose mechanisms for accomplishing specific user goals. For example:
If you’re building a music player, use the audio background mode to continue playing after the user has moved your app to the background.
If you’re building a timer app, use a local notification to notify the user when your timer has expired.
If you’re building a video player app, use AVFoundation’s download support.
Keep in mind that the above is just a short list of examples. There are many other special-purpose background execution mechanisms, so you should search the documentation for something appropriate to your needs.
IMPORTANT Each of these mechanisms fulfils a specific purpose. Do not attempt to use them for some other purpose. Before using a background API, read clause 2.5.4 of the App Review Guidelines.
Additionally, iOS provides some general-purpose mechanisms for background execution:
To resume your app in the background in response to an event on your server, use a background notification (aka a ‘silent’ push). For more information, see Pushing background updates to your App.
To request a small amount of background execution time to refresh your UI, use BGAppRefreshTaskRequest.
To request extended background execution time, typically delivered overnight when the user is asleep, use BGProcessingTaskRequest.
To prevent your app from being suspended for a short period of time so that you can complete some user task, use a UIApplication background task. For more information on this, see UIApplication Background Task Notes.
To download or upload a large HTTP resource, use an NSURLSession background session.
All of these mechanisms prevent you from abusing them to run arbitrary code in the background. As an example, consider the NSURLSession resume rate limiter.
For more information about these limitations, and background execution in general, I strongly recommend that you watch WWDC 2020 Session 10063 Background execution demystified. It’s an excellent resource.
Specifically, this talk addresses a common misconception about the app refresh mechanism (BGAppRefreshTaskRequest and the older background fetch API). Folks assume that app refresh will provide regular background execution time. That’s not the case. The system applies a range of heuristics to decide which apps get app refresh time and when. This is a complex issue, one that I’m not going to try to summarise here, but the take-home message is that, if you expect that the app refresh mechanism will grant you background execution time, say, every 15 minutes, you’ll be disappointed. In fact, there are common scenarios where it won’t grant you any background execution time at all! Watch the talk for the details.
When the user ‘force quits’ an app by swiping up in the multitasking UI, iOS interprets that to mean that the user doesn’t want the app running at all. So:
If the app is running, iOS terminates it.
iOS also sets a flag that prevents the app from being launched in the background. That flag gets cleared when the user next launches the app manually.
This gesture is a clear statement of user intent; there’s no documented way for your app to override the user’s choice.
Note In some circumstances iOS will not honour this flag. The exact cases where this happens are not documented and have changed over time.
Finally, if you have questions about background execution that aren’t covered by the resources listed here, please open a new thread on DevForums with the details. Tag it appropriately for the technology you’re using; if nothing specific springs to mind, use Background Tasks. Also, make sure to include details about the specific problem you’re trying to solve because, when it comes to background execution, the devil really is in the details.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Change history:
2024-03-21 Added a discussion of ‘force quit’.
2023-05-11 Added a paragraph that explains a common misconception about the app refresh mechanism. Made other minor editorial changes.
2021-08-12 Added more entries to the common questions list, this time related to networking and IPC. Made minor editorial changes.
2021-07-26 Extended the statement about what’s not possible to include “running code periodically at a guaranteed interval”.
2021-07-22 First posted.
I've set up a couple of domains (seemingly) successfully with iCloud+ Custom Domains. All the DNS entries are correct.
Now, when I attempt to add an email address I get the error "There was a problem with adding this email address. Please try again later."
This has been happening for over 24 hours. I'm not quite sure how to proceed - I know this is in Beta, but I keep reading how it is working for other people so its hard to think this is a general problem.
I'm adding entirely new domains so there is no chance that the email addresses are previously known by Apple / used for a previous AppleID.
Any ideas please?
Could someone tell me the default version of Python, installed with Mac OS Monterey? The one symlinked from /usr/bin/python to /System/Library/Frameworks.
I have an App that builds for iOS, iPadOS, macOS and Apple TV, which was last released to all the App Stores in April. Preferences/settings are handled by the App itself except for the Apple TV variant, where I use a Settings bundle. This worked fine until tvOS 15.0, where it appears that tvOS is not updating the value of the App’s settings from NSUserDefaults when the Settings App opens. I have been working on this problem off and on for the last week and am at wits end.
I’ve searched WWDC videos looking for a clue, there must be some simple change I cannot see. I’ve made clean projects for iOS and tvOS, and using the identical OBJ-C code and Settings plist entries, the iOS version works perfectly, the tvOS version fails in the simulator and on the device. I am not trying to synchronize Settings across devices, just persist across restarts on a single device.
My code stores data correctly in NSUserDefaults, it simply seems that tvOS Settings App is not reading values from there for display, nor writing changes that the user makes from Settings back to user defaults. None of the types in the test projects work: TexField, Switch, Title.
The test code is so simple I hesitate to include it, but the code and the NSUserDefaults key identifiers do match. This code will preset my App’s version number for Settings to display in iOS 15 but not tvOS 15. It used to work in tvOS 14:
<key>DefaultValue</key>
<string>DefaultVersionValue</string>
<key>Type</key>
<string>PSTitleValueSpecifier</string>
<key>Title</key>
<string>Version</string>
<key>Key</key>
<string>VersionKey</string>
</dict>
``` NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
[ud registerDefaults:@{
@"TextFieldKey" : @"TextFieldValue",
@"VersionKey" : @"VersionValue"
}];
[ud setObject:@"3.14" forKey:@"VersionKey"];
Any idea? Many thanks.
So apparently Monterey has switched to creating .ips files instead of .crash files for application crashes. Console.app can convert these .ips files to "old-style" crash format. But is there a command-line tool to do the same thing?
I made a minor change the UI of my tvOS App, and am now getting errors related to the App Icon. I have confirmed that all the background images DO match the requirements but App Store Connect won't let me upload:
App Store Connect Operation Error
Invalid Image Asset. The image stack 'App Icon' in 'Payload/My TV.app/Assets.car' has a background layer image that does not match the canvas dimensions '400x240'.
App Store Connect Operation Error
Invalid Image Asset. The image stack 'App Icon' in 'Payload/My TV.app/Assets.car' has a background layer image that does not match the canvas dimensions '800x480'.
App Store Connect Operation Error
Invalid Image Asset. The image stack 'App Icon' in 'Payload/My TV.app/Assets.car' has a background layer image that does not match the canvas dimensions '1280x768'.
App Store Connect Operation Error
Invalid Image Asset. The image stack 'App Icon' in 'Payload/My TV.app/Assets.car' has a background layer image that does not match the canvas dimensions '2560x1536'.
App Store Connect Operation Error
Invalid Image Asset. The App Store Icon must only contain an image with size (1280pt × 768pt @1x). Refer to https://developer.apple.com/tvos/human-interface-guidelines/icons-and-images/app-icon for more information
Have the standards changed? Or is there another issue I should be looking at? Thanks!