PyObjC: IOBluetoothUI Framework
pyobjc-framework-iobluetoothui provides Python wrappers for Apple's IOBluetoothUI.framework on macOS, allowing Python applications to interact with Bluetooth-related user interface components. It is part of the larger PyObjC project, which bridges Python and the Objective-C runtime. The current version is 12.1, with releases typically tied to new macOS SDKs and Python version support cycles.
Warnings
- breaking PyObjC frequently drops support for older Python versions. 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 or release notes when upgrading.
- breaking PyObjC 11.1 introduced a significant change in how Automatic Reference Counting (ARC) is modeled for initializer methods. Methods in the 'init' family now correctly steal a reference to self and return a new reference, aligning with `clang`'s documentation. This can affect object lifecycle management if you relied on previous PyObjC behavior.
- gotcha Interactions between Python's `__init__` and `__new__` methods in PyObjC classes saw changes in versions 10.3 and 10.3.1. While 10.3 initially dropped `__init__` support when `__new__` was provided by PyObjC, 10.3.1 reintroduced `__init__` support for classes with user-implemented `__new__`. However, classes relying on PyObjC's default `__new__` still cannot use `__init__` for initialization.
- gotcha PyObjC 11.0 introduced experimental support for Python 3.13's free-threading (PEP 703), but PyObjC 10.3 explicitly stated that it does *not* support free threading in Python 3.13. Using PyObjC in a free-threaded Python 3.13 environment might lead to undefined behavior or crashes until full support is officially announced.
- breaking PyObjC framework bindings are tied to macOS SDKs. As Apple deprecates and removes frameworks, PyObjC will also remove their bindings. For example, the 'IMServicePlugIn' bindings were removed in PyObjC 10.0 due to their removal in macOS 14. Be aware that specific framework wrappers might disappear in new major PyObjC versions.
Install
-
pip install pyobjc-framework-iobluetoothui
Imports
- IOBluetoothServiceBrowserController
from IOBluetoothUI import IOBluetoothServiceBrowserController
- NSApplication
from AppKit import NSApplication
- NSObject
from Foundation import NSObject
- AppHelper
from PyObjCTools import AppHelper
Quickstart
from Foundation import NSObject
from AppKit import NSApplication
from PyObjCTools import AppHelper
from IOBluetoothUI import IOBluetoothServiceBrowserController
class AppDelegate(NSObject):
def applicationDidFinishLaunching_(self, notification):
print("Application finished launching. Showing Bluetooth Service Browser...")
self.browserController = IOBluetoothServiceBrowserController.withServiceBrowserController_()
if self.browserController:
# Options can be specified here, e.g., 0 for default
self.browserController.setOptions_(0)
# showModal_ blocks until the browser dialog is dismissed
self.browserController.showModal_(None)
print("Bluetooth Service Browser dismissed.")
else:
print("Failed to create IOBluetoothServiceBrowserController.")
# In a real app, you might want to quit the app or keep it running
# For this quickstart, we'll quit after the modal dialog is dismissed.
NSApplication.sharedApplication().terminate_(None)
def main():
app = NSApplication.sharedApplication()
delegate = AppDelegate.alloc().init()
app.setDelegate_(delegate)
# Run the Cocoa event loop
AppHelper.runEventLoop()
if __name__ == "__main__":
main()