{"id":6067,"library":"pyobjc-framework-apptrackingtransparency","title":"App Tracking Transparency Framework for PyObjC","description":"pyobjc-framework-AppTrackingTransparency provides Python wrappers for Apple's App Tracking Transparency framework on macOS. This framework enables applications to request user authorization for tracking across apps and websites, a critical privacy feature introduced in iOS 14 and macOS 11. It is part of the larger PyObjC project, which offers Python bindings for many macOS (Cocoa) frameworks. The current version is 12.1, with releases typically aligning with macOS SDK updates and Python compatibility.","status":"active","version":"12.1","language":"en","source_language":"en","source_url":"https://github.com/ronaldoussoren/pyobjc","tags":["macos","cocoa","apptrackingtransparency","privacy","pyobjc"],"install":[{"cmd":"pip install pyobjc-framework-apptrackingtransparency","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"The core PyObjC bridge is required for all framework wrappers.","package":"pyobjc-core"}],"imports":[{"symbol":"ATTrackingManager","correct":"from AppTrackingTransparency import ATTrackingManager"},{"symbol":"ATTrackingManagerAuthorizationStatus","correct":"from AppTrackingTransparency import ATTrackingManagerAuthorizationStatus"}],"quickstart":{"code":"import objc\nfrom Foundation import NSObject, NSLog, NSRunLoop, NSDefaultRunLoopMode, objc_object\nfrom AppTrackingTransparency import ATTrackingManager, ATTrackingManagerAuthorizationStatus\n\nclass TrackingDelegate(NSObject):\n    def init(self):\n        self = objc.super(TrackingDelegate, self).init()\n        if self is None: return None\n        return self\n\n    def requestTrackingPermission(self):\n        current_status = ATTrackingManager.trackingAuthorizationStatus()\n        NSLog(f\"Initial tracking status: {current_status}\")\n\n        if current_status == ATTrackingManagerAuthorizationStatus.notDetermined:\n            NSLog(\"Requesting tracking authorization...\")\n            # Objective-C method with completion handler translates to PyObjC with underscore suffix\n            ATTrackingManager.requestTrackingAuthorization_(self.trackingAuthorizationCompletionHandler_)\n        else:\n            NSLog(\"Authorization already determined or restricted.\")\n            self.checkTrackingStatus()\n\n    def trackingAuthorizationCompletionHandler_(self, status: ATTrackingManagerAuthorizationStatus) -> None:\n        # This handler might not be called on the main thread; dispatch UI updates if any.\n        NSLog(f\"Tracking authorization completion handler called with status: {status}\")\n        self.checkTrackingStatus()\n\n    def checkTrackingStatus(self):\n        status = ATTrackingManager.trackingAuthorizationStatus()\n        if status == ATTrackingManagerAuthorizationStatus.authorized:\n            NSLog(\"Tracking authorized!\")\n        elif status == ATTrackingManagerAuthorizationStatus.denied:\n            NSLog(\"Tracking denied.\")\n        elif status == ATTrackingManagerAuthorizationStatus.notDetermined:\n            NSLog(\"Tracking not determined.\")\n        elif status == ATTrackingManagerAuthorizationStatus.restricted:\n            NSLog(\"Tracking restricted by parental controls or MDM.\")\n        else:\n            NSLog(\"Unknown tracking status.\")\n\ndef main():\n    delegate = TrackingDelegate.alloc().init()\n    delegate.requestTrackingPermission()\n\n    # For the completion handler to be called, an NSRunLoop must be active.\n    # In a full AppKit application, this is handled automatically.\n    # For a console script, run a short loop.\n    NSLog(\"Running runloop for 5 seconds to allow async callback...\")\n    NSRunLoop.currentRunLoop().runUntilDate_(objc.NSTimeIntervalToBeDateTime(objc.current_time() + 5.0))\n    NSLog(\"Runloop finished.\")\n\nif __name__ == '__main__':\n    main()\n","lang":"python","description":"This example demonstrates how to request app tracking authorization and check its status. For the authorization prompt to appear, you *must* add the `NSUserTrackingUsageDescription` key with a purpose string to your application's `Info.plist` file (an Xcode project setting, not Python code). The completion handler for `requestTrackingAuthorization_` is asynchronous and requires a running `NSRunLoop` to execute."},"warnings":[{"fix":"Upgrade your Python environment to 3.10 or later.","message":"PyObjC 12.0 dropped support for Python 3.9, and PyObjC 11.0 dropped support for Python 3.8. Ensure your project uses Python 3.10 or newer.","severity":"breaking","affected_versions":">=11.0"},{"fix":"Add `NSUserTrackingUsageDescription` (String) with a descriptive message to your application's `Info.plist` file.","message":"To display the App Tracking Transparency authorization prompt, you *must* add the `NSUserTrackingUsageDescription` key to your application's `Info.plist` file (typically done in Xcode). Without this, the system will not present the dialog.","severity":"gotcha","affected_versions":"All"},{"fix":"Check `ATTrackingManager.trackingAuthorizationStatus()` before calling `requestTrackingAuthorization_()` and handle each status appropriately. Do not expect repeated prompts.","message":"The `requestTrackingAuthorization` method is a one-time request. The system remembers the user's choice and will not prompt again unless the user uninstalls and then reinstalls the app, or if the status is `notDetermined`. Calls only prompt when the application state is active.","severity":"gotcha","affected_versions":"All"},{"fix":"Review memory management practices for custom Objective-C classes implemented in Python, especially those with `init` methods, to ensure correct reference handling under the new ARC model.","message":"PyObjC 11.1 introduced significant changes to how the core bridge handles Automatic Reference Counting (ARC) for initializer (`init` family) methods, aligning with `clang`'s documentation. This can affect memory management for custom Objective-C classes implemented in Python.","severity":"breaking","affected_versions":">=11.1"}],"env_vars":null,"last_verified":"2026-04-14T00:00:00.000Z","next_check":"2026-07-13T00:00:00.000Z"}