{"id":5407,"library":"pyobjc-framework-corebluetooth","title":"PyObjC CoreBluetooth Framework","description":"PyObjC provides Python bindings for Apple's macOS frameworks, allowing Python applications to interact with native macOS APIs. `pyobjc-framework-corebluetooth` specifically offers wrappers for the CoreBluetooth framework, enabling Python programs to communicate with Bluetooth Low Energy (BLE) devices. The current version is 12.1, and PyObjC typically releases new versions in sync with macOS SDK updates and Python version support changes.","status":"active","version":"12.1","language":"en","source_language":"en","source_url":"https://github.com/ronaldoussoren/pyobjc","tags":["macos","bluetooth","ble","corebluetooth","pyobjc","framework"],"install":[{"cmd":"pip install pyobjc-framework-corebluetooth","lang":"bash","label":"Install pyobjc-framework-corebluetooth"}],"dependencies":[{"reason":"This package provides the core bridge between Python and Objective-C; all PyObjC framework bindings depend on it.","package":"pyobjc-core"}],"imports":[{"symbol":"CBCentralManager","correct":"from CoreBluetooth import CBCentralManager"},{"symbol":"CBPeripheral","correct":"from CoreBluetooth import CBPeripheral"},{"symbol":"CBManagerDelegate","correct":"from CoreBluetooth import CBManagerDelegate"}],"quickstart":{"code":"import objc\nfrom Foundation import NSObject, NSLog\nfrom CoreBluetooth import CBCentralManager, CBManagerDelegate\n\n# Define a delegate for CBCentralManager\n# PyObjC automatically bridges Python classes inheriting from NSObject\n# and implementing a protocol into Objective-C delegates.\nclass MyCentralManagerDelegate(NSObject, protocols=[CBManagerDelegate]):\n    def init(self):\n        self = objc.super(MyCentralManagerDelegate, self).init()\n        if self is None:\n            return None\n        self.centralManager = None\n        return self\n\n    # This method is called when the central manager's state changes.\n    # It's typically the first delegate method called after initialization.\n    def centralManagerDidUpdateState_(self, central):\n        NSLog(\"Central Manager did update state: %d\", central.state())\n        # The state is an enum (e.g., CBManagerStatePoweredOn (5), CBManagerStatePoweredOff (4)).\n        # For better readability, you'd map the enum values to human-friendly strings.\n\ndef main():\n    delegate = MyCentralManagerDelegate.alloc().init()\n    # CBCentralManager holds a weak reference to its delegate.\n    # Ensure the Python delegate object is not garbage collected for the duration\n    # of the manager's lifecycle. Keeping `delegate` in a local scope like `main`\n    # is sufficient for this quick example.\n\n    # Initialize the CBCentralManager, passing our delegate.\n    # 'None' for the queue uses the main dispatch queue.\n    manager = CBCentralManager.alloc().initWithDelegate_queue_options_(\n        delegate, None, None\n    )\n\n    NSLog(\"Initialized CBCentralManager. Waiting for state update...\")\n    # CoreBluetooth operations are asynchronous and report via delegate methods.\n    # For a console application, you typically need to run a Cocoa event loop\n    # (e.g., using `PyObjCTools.AppHelper.runConsoleEventLoop()` from `pyobjc-tools`)\n    # to process callbacks. For this minimal example, we'll wait briefly to see\n    # the initial state update.\n    import time\n    time.sleep(1) # Give the system a moment to call the delegate\n    NSLog(\"Quickstart complete. For interactive BLE, use a proper event loop.\")\n\nif __name__ == \"__main__\":\n    main()\n","lang":"python","description":"This quickstart initializes a `CBCentralManager` and uses a Python class as its delegate. It demonstrates how to create a PyObjC-compatible delegate and receive the `centralManagerDidUpdateState_` callback, which is essential for any CoreBluetooth interaction. For full asynchronous operation and to handle ongoing events, a dedicated Cocoa event loop (e.g., using `PyObjCTools.AppHelper.runConsoleEventLoop()` from `pyobjc-tools`) is required."},"warnings":[{"fix":"Upgrade to a supported Python version (>=3.10 for PyObjC 12.x) or use an older PyObjC version compatible with your Python environment.","message":"PyObjC 12.0 dropped support for Python 3.9, and PyObjC 11.0 dropped support for Python 3.8. Always check the `requires_python` metadata for compatibility with your Python version.","severity":"breaking","affected_versions":"11.0, 12.0"},{"fix":"Ensure your development and deployment environment is macOS. Consider platform-agnostic libraries like `bleak` for cross-platform BLE development, or use `platform.system() == 'Darwin'` for conditional execution.","message":"`pyobjc-framework-corebluetooth` is a macOS-specific library. It relies on the underlying CoreBluetooth framework provided by Apple's operating system and will not function on Windows, Linux, or other non-macOS platforms.","severity":"gotcha","affected_versions":"All"},{"fix":"Review custom Python `init` methods in classes that bridge to Objective-C to ensure they correctly handle object retention and release, especially when overriding `NSObject`'s `init` or similar methods. Consult PyObjC's documentation on memory management.","message":"PyObjC 11.1 aligned the behavior of 'init' family methods (initializers) with clang's Automatic Reference Counting (ARC) documentation. These methods now correctly steal a reference to `self` and return a new reference. Code relying on previous object lifecycle assumptions for initializers might break.","severity":"breaking","affected_versions":"11.1 and later"},{"fix":"If encountering issues with `__init__` not being called or unexpected object instantiation behavior in bridged classes, ensure your `__new__` and `__init__` implementations conform to PyObjC's current guidelines. For many cases, `init()` (Objective-C style) should be used instead of `__init__`.","message":"Changes in PyObjC 10.3 and 10.3.1 altered the interaction between Python's `__init__` and `__new__` methods for bridged classes. Specifically, `__init__` could not be used when the PyObjC-provided `__new__` was active, though this was partially reverted in 10.3.1 for user-implemented `__new__`.","severity":"gotcha","affected_versions":"10.3, 10.3.1"},{"fix":"Use `PyObjCTools.AppHelper.runConsoleEventLoop()` from the `pyobjc-tools` package to keep the application's event loop active and process Objective-C callbacks. This is essential for most interactive PyObjC console applications.","message":"For console applications using PyObjC, the delegate callbacks and asynchronous events (like CoreBluetooth discoveries) require a running Cocoa event loop. Without it, delegate methods may not be called, or the program might exit prematurely.","severity":"gotcha","affected_versions":"All"}],"env_vars":null,"last_verified":"2026-04-13T00:00:00.000Z","next_check":"2026-07-12T00:00:00.000Z"}