{"id":5802,"library":"pyobjc-framework-contacts","title":"PyObjC Contacts Framework","description":"PyObjC-framework-contacts provides Python bindings and wrappers for Apple's Contacts.framework on macOS. It allows Python developers to interact with the system's contact store, fetch, create, update, and delete contacts, and manage contact groups. The current version is 12.1, with a release cadence that generally follows macOS SDK updates and Python version support cycles.","status":"active","version":"12.1","language":"en","source_language":"en","source_url":"https://github.com/ronaldoussoren/pyobjc","tags":["macos","contacts","framework","pyobjc","cocoa"],"install":[{"cmd":"pip install pyobjc-framework-contacts","lang":"bash","label":"Install pyobjc-framework-contacts"}],"dependencies":[{"reason":"Core PyObjC bridge is required for all framework bindings.","package":"pyobjc","optional":false}],"imports":[{"symbol":"CNContactStore","correct":"from Contacts import CNContactStore"},{"symbol":"CNContact","correct":"from Contacts import CNContact"},{"symbol":"CNMutableContact","correct":"from Contacts import CNMutableContact"},{"note":"Many Cocoa collection types like NSArray, NSDictionary, etc., are found in Foundation.","symbol":"NSArray","correct":"from Foundation import NSArray"}],"quickstart":{"code":"from Contacts import CNContactStore, CNContactFetchRequest, CNContactGivenNameKey, CNContactFamilyNameKey\nfrom Foundation import NSArray\n\ndef list_contact_names():\n    \"\"\"Fetches and prints the names of all contacts.\"\"\"\n    store = CNContactStore.alloc().init()\n    \n    # Define the keys (properties) to fetch for each contact\n    keys_to_fetch = [CNContactGivenNameKey, CNContactFamilyNameKey]\n    \n    # CNContactFetchRequest expects an NSArray of keys\n    request = CNContactFetchRequest.alloc().initWithKeysToFetch_(NSArray.arrayWithArray_(keys_to_fetch))\n    \n    contacts = []\n    # Enumerate contacts: the third argument is a Python callable (block)\n    # that gets called for each contact found.\n    success, error = store.enumerateContactsWithFetchRequest_error_(\n        request, None, lambda contact, stop: contacts.append(contact)\n    )\n\n    if not success:\n        print(f\"Error fetching contacts: {error}\")\n        return\n\n    if contacts:\n        print(\"Found contacts:\")\n        for contact in contacts:\n            full_name = f\"{contact.givenName() or ''} {contact.familyName() or ''}\".strip()\n            if full_name:\n                print(f\"- {full_name}\")\n            else:\n                print(f\"- (Unnamed contact, ID: {contact.identifier()})\")\n    else:\n        print(\"No contacts found.\")\n\nif __name__ == '__main__':\n    # Note: Requires Contacts permission. First run might prompt for access.\n    list_contact_names()","lang":"python","description":"This quickstart demonstrates how to list the names of all contacts using `CNContactStore` and `CNContactFetchRequest`. It showcases basic object allocation (`alloc().init()`) and method calls specific to the Contacts framework within PyObjC. Running this code will likely trigger a macOS permission prompt for Contacts access if not already granted."},"warnings":[{"fix":"Upgrade to Python 3.10 or later, or use an older PyObjC version (e.g., PyObjC 11.x for Python 3.9 compatibility).","message":"PyObjC 12.0 (and thus pyobjc-framework-contacts 12.x) dropped support for Python 3.9. Ensure your Python environment meets the `requires_python` specification.","severity":"breaking","affected_versions":">=12.0"},{"fix":"Review custom Python subclasses of Cocoa objects, especially those overriding `init` methods, to ensure correct reference handling under the new ARC model. Most standard usage should be unaffected.","message":"PyObjC 11.1 introduced changes to align the core bridge's Automatic Reference Counting (ARC) behavior with `clang`'s documentation for initializer methods. Methods in the 'init' family now correctly steal a reference to self and return a new reference, which can affect custom memory management or subclassing patterns relying on the old behavior.","severity":"breaking","affected_versions":">=11.1"},{"fix":"If subclassing Cocoa classes in Python, be mindful of how `__init__` and `__new__` interact. Prefer using `alloc().init()` patterns where possible, or ensure your `__new__` implementation correctly handles initialization to avoid unexpected behavior or errors.","message":"In PyObjC 10.3, the ability to use `__init__` in custom Python subclasses was changed, particularly for classes relying on the `__new__` provided by PyObjC. While a fix in 10.3.1 restored `__init__` for user-implemented `__new__`, direct `__init__` calls on PyObjC-provided `__new__` are still restricted. This can affect how you initialize Python-defined subclasses of Cocoa objects.","severity":"gotcha","affected_versions":">=10.3, <10.3.2"},{"fix":"Before using `os.fspath()` with a Cocoa URL, ensure it refers to a local filesystem path. For other URL types, convert them to string representations explicitly if needed, or use Cocoa's own URL parsing and path access methods.","message":"As of PyObjC 10.1, calling `os.fspath()` directly with Cocoa URL objects (`NSURL`, `CFURLRef`) that refer to local filesystem paths will work, but for other types of URLs, it will raise a `TypeError`. This ensures better integration with standard Python filesystem APIs but requires careful handling for non-local or generic URLs.","severity":"gotcha","affected_versions":">=10.1"}],"env_vars":null,"last_verified":"2026-04-14T00:00:00.000Z","next_check":"2026-07-13T00:00:00.000Z"}