PyObjC Core
PyObjC Core is the essential bridge between Python and Objective-C, enabling Python applications to interact with macOS Cocoa frameworks. Version 12.1 is current, and releases typically align with new macOS SDKs and Python versions, with major versions appearing roughly annually and patches more frequently.
Warnings
- gotcha PyObjC is a macOS-specific bridge; it relies on macOS's Objective-C runtime and Cocoa frameworks. It will not work on Windows or Linux.
- breaking PyObjC frequently drops support for older Python versions (e.g., Python 3.9 dropped in v12.0, Python 3.8 in v11.0) to align with macOS SDKs and Python's own end-of-life cycles. Always check the 'requires_python' metadata for compatibility.
- breaking PyObjC 11.1 introduced significant changes to how initializer methods (`init` family) handle reference counting to align with `clang`'s Automatic Reference Counting (ARC) documentation. This can change memory management behavior and potentially cause leaks or crashes in existing code that made assumptions about object lifecycle during initialization.
- gotcha While PyObjC 11 introduced experimental support for Python's PEP 703 (free-threading) feature in Python 3.13, it is still experimental. Use with caution, as it may not be stable or fully optimized for production environments.
- gotcha `pyobjc-core` provides the fundamental bridge, but for most practical application development, you will also need specific framework bindings (e.g., `pyobjc-framework-Foundation`, `pyobjc-framework-AppKit`). The `pyobjc` meta-package installs `pyobjc-core` and many common frameworks and is generally recommended for ease of use.
Install
-
pip install pyobjc-core -
pip install pyobjc
Imports
- objc
import objc
- lookUpClass
from objc import lookUpClass
- python_class
from objc import python_class
Quickstart
import objc
from Foundation import NSString, NSDate, NSObject
# 1. Basic interoperability: Python string to Objective-C NSString
python_string = "Hello from PyObjC!"
objc_string = NSString.stringWithString_(python_string)
print(f"Python string: '{python_string}' (Type: {type(python_string)})\n")
print(f"Objective-C NSString: '{objc_string}' (Type: {type(objc_string)})\n")
# 2. Get current date as NSDate
current_nsdate = NSDate.date()
print(f"Current NSDate: {current_nsdate} (Type: {type(current_nsdate)})\n")
# 3. Define a Python class that inherits from an Objective-C class
@objc.python_class
class MyPythonObject(NSObject):
def init(self):
self = objc.super(MyPythonObject, self).init()
if self is None: return None
self.message = "I am a Python-backed Objective-C object!"
return self
# Expose a method callable from Objective-C (and Python)
@objc.selector('myCustomMethod')
def myCustomMethod(self):
return self.message
# Create an instance and call the method
# Note: alloc().init() is the standard Objective-C way to create objects.
python_objc_instance = MyPythonObject.alloc().init()
print(f"Message from Python-backed ObjC instance: {python_objc_instance.myCustomMethod()}\n")