{"id":6094,"library":"pyobjc-framework-devicecheck","title":"PyObjC DeviceCheck Framework","description":"PyObjC-framework-DeviceCheck provides Python wrappers for Apple's DeviceCheck framework on macOS, allowing Python applications to interact with DeviceCheck APIs to manage device state and assert app integrity. It is part of the broader PyObjC project, a bridge that enables Python scripts to fully utilize Objective-C class libraries like Cocoa. The library is actively maintained, with version 12.1 being the current release, and follows a frequent release cadence tied to macOS SDK and Python version updates.","status":"active","version":"12.1","language":"en","source_language":"en","source_url":"https://github.com/ronaldoussoren/pyobjc","tags":["macos","cocoa","apple","devicecheck","pyobjc"],"install":[{"cmd":"pip install pyobjc-framework-devicecheck","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"This package provides the core bridge between Python and Objective-C, essential for all PyObjC framework wrappers.","package":"pyobjc-core","optional":false}],"imports":[{"note":"Classes and functions from Objective-C frameworks are mapped directly to Python modules with the same name.","symbol":"DCDevice","correct":"from DeviceCheck import DCDevice"},{"note":"Required for running event loops in command-line scripts for asynchronous Objective-C calls.","symbol":"AppHelper","correct":"from PyObjCTools import AppHelper"}],"quickstart":{"code":"import objc\nfrom DeviceCheck import DCDevice\nfrom PyObjCTools import AppHelper\nimport Foundation # For NSData, NSError types\n\ndef device_check_completion_handler(token_data, error):\n    \"\"\"Objective-C completion handler for generateTokenWithCompletionHandler_.\"\"\"\n    if error:\n        print(f\"Error generating token: {error.localizedDescription()}\")\n    elif token_data:\n        # NSData object from Objective-C can be converted to Python bytes\n        python_token = token_data.bytes().tobytes()\n        print(f\"Successfully generated DeviceCheck token (first 10 bytes): {python_token[:10]}...\")\n    else:\n        print(\"No token data and no error received.\")\n    AppHelper.stopEventLoop()\n\ndef main():\n    device = DCDevice.currentDevice()\n\n    if not device.isSupported():\n        print(\"DeviceCheck is not supported on this device (e.g., simulator).\")\n        return\n\n    print(\"DeviceCheck is supported. Generating token...\")\n    # Call the asynchronous Objective-C method with a Python callable as handler\n    device.generateTokenWithCompletionHandler_(device_check_completion_handler)\n    \n    # Start the PyObjC event loop to process the asynchronous call\n    print(\"Starting event loop (waiting for token or error)...\")\n    AppHelper.runEventLoop()\n    print(\"Event loop stopped.\")\n\nif __name__ == \"__main__\":\n    main()","lang":"python","description":"This quickstart demonstrates how to access the current DCDevice, check if DeviceCheck is supported, and then generate a device token using an asynchronous Objective-C method. A Python function is used as the completion handler to process the token or any errors, and the PyObjCTools.AppHelper is used to manage the event loop necessary for asynchronous Objective-C calls in a script."},"warnings":[{"fix":"Upgrade Python to version 3.10 or later. Consider using a virtual environment to manage Python versions.","message":"PyObjC has dropped support for older Python versions. Version 12.0 removed support for Python 3.9, and version 11.0 removed support for Python 3.8. Users must ensure their Python environment meets the `>=3.10` requirement for PyObjC 12.1.","severity":"breaking","affected_versions":">=11.0"},{"fix":"Review custom Objective-C classes used with PyObjC, particularly those with 'init' methods, to ensure they correctly handle reference counts according to ARC guidelines. Update code that might have implicitly relied on previous PyObjC reference count handling quirks.","message":"PyObjC 11.1 changed how it models Objective-C's Automatic Reference Counting (ARC) for 'init' methods. Methods in the 'init' family now correctly 'steal a reference to self and return a new reference' in alignment with `clang`'s documentation. This change can affect applications relying on the previous, less accurate reference counting behavior, especially for singletons or in multithreaded contexts.","severity":"breaking","affected_versions":">=11.1"},{"fix":"Test DeviceCheck functionality exclusively on actual hardware to ensure proper behavior and avoid unexpected `isSupported()` return values.","message":"The `DeviceCheck` framework, and thus `pyobjc-framework-devicecheck`, only functions on physical macOS/iOS devices and will not work when run on a simulator. Calls to `DCDevice.currentDevice().isSupported()` will return `False` on simulators.","severity":"gotcha","affected_versions":"All"},{"fix":"Avoid subclassing `NSString` or `NSMutableString` directly. If string manipulation or custom string behavior is required, consider wrapping standard Python strings or using other Cocoa collection types.","message":"Subclassing `NSString` or `NSMutableString` in Python using PyObjC is not supported and will lead to application crashes. These classes are treated as 'final' within the PyObjC bridge due to special internal handling.","severity":"gotcha","affected_versions":"All"},{"fix":"Always use `buffer(value)` to safely bridge Python bytes-like objects to `NSData` subclasses. If you must use methods that take `bytesNoCopy`, ensure the `freeWhenDone` parameter is explicitly set to `False`.","message":"Specific `NSData` and `NSMutableData` initialization methods, such as `dataWithBytesNoCopy:length:` or `initWithBytesNoCopy:length:`, should not be used with Python buffers. Cocoa might attempt to `free()` the buffer when the `NSData` object is released, which is incompatible with Python's memory management and can cause crashes. For methods like `dataWithBytesNoCopy:length:freeWhenDone:`, the `freeWhenDone` argument *must* be `False`.","severity":"gotcha","affected_versions":"All"}],"env_vars":null,"last_verified":"2026-04-14T00:00:00.000Z","next_check":"2026-07-13T00:00:00.000Z"}