{"id":6144,"library":"pyobjc-framework-multipeerconnectivity","title":"PyObjC Framework: MultipeerConnectivity","description":"The `pyobjc-framework-multipeerconnectivity` library provides Python bindings for Apple's Multipeer Connectivity framework on macOS, enabling Python applications to discover nearby devices and communicate via Wi-Fi, Peer-to-Peer Wi-Fi, and Bluetooth personal area networks. It is part of the larger PyObjC project, allowing Python developers to interact with Objective-C APIs directly. The current version is 12.1, and releases generally align with macOS SDK updates and Python version compatibility.","status":"active","version":"12.1","language":"en","source_language":"en","source_url":"https://github.com/ronaldoussoren/pyobjc","tags":["macos","framework","objc","multipeerconnectivity","apple","p2p"],"install":[{"cmd":"pip install pyobjc-framework-multipeerconnectivity","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"This package provides bindings for a specific macOS framework and requires the core PyObjC bridge.","package":"pyobjc-core","optional":false}],"imports":[{"note":"Standard import for accessing all symbols within the Multipeer Connectivity framework.","symbol":"MultipeerConnectivity","correct":"from MultipeerConnectivity import *"},{"note":"Often required for basic macOS types like `NSObject`, `NSString`, `NSHost` used in Multipeer Connectivity contexts.","symbol":"Foundation","correct":"from Foundation import *"},{"note":"Used for running the Cocoa event loop in console applications, which is essential for delegate callbacks.","symbol":"AppHelper","correct":"from PyObjCTools import AppHelper"}],"quickstart":{"code":"import objc\nfrom Foundation import *\nfrom MultipeerConnectivity import *\nfrom PyObjCTools import AppHelper\nimport sys\n\n# Define a service type (must be 1-15 lowercase ASCII characters, no hyphens, no underscores)\nSERVICE_TYPE = \"my-p2p-app\"\n\nclass BrowserDelegate(NSObject):\n    \"\"\"\n    Delegate for MCNearbyServiceBrowser to handle found and lost peers.\n    \"\"\"\n    def browser_foundPeer_withDiscoveryInfo_(self, browser, peerID, info):\n        print(f\"[Browser] Found peer: {peerID.displayName()} (Info: {info})\")\n        # In a real app, you'd now invite the peer to a session.\n\n    def browser_lostPeer_(self, browser, peerID):\n        print(f\"[Browser] Lost peer: {peerID.displayName()}\")\n\nclass AdvertiserDelegate(NSObject):\n    \"\"\"\n    Delegate for MCNearbyServiceAdvertiser to handle invitations.\n    \"\"\"\n    def advertiser_didReceiveInvitationFromPeer_withContext_invitationHandler_(self, advertiser, peerID, context, invitationHandler):\n        print(f\"[Advertiser] Received invitation from {peerID.displayName()} (Context: {context})\")\n        # For this simple example, we decline any invitations.\n        invitationHandler(False, None) \n\n# 1. Create a peer ID for this device\nmyPeerID = MCPeerID.alloc().initWithDisplayName_(NSHost.currentHost().name())\nprint(f\"Starting MultipeerConnectivity as: {myPeerID.displayName()}\")\n\n# 2. Setup a browser to find other peers\nbrowserDelegate = BrowserDelegate.alloc().init()\nbrowser = MCNearbyServiceBrowser.alloc().initWithPeer_serviceType_(myPeerID, SERVICE_TYPE)\nbrowser.setDelegate_(browserDelegate)\nbrowser.startBrowsingForPeers()\nprint(f\"Started browsing for peers using service type: '{SERVICE_TYPE}'\")\n\n# 3. Setup an advertiser to be discovered by other peers\nadvertiserDelegate = AdvertiserDelegate.alloc().init()\nadvertiser = MCNearbyServiceAdvertiser.alloc().initWithPeer_discoveryInfo_serviceType_(myPeerID, None, SERVICE_TYPE)\nadvertiser.setDelegate_(advertiserDelegate)\nadvertiser.startAdvertisingPeer()\nprint(f\"Started advertising using service type: '{SERVICE_TYPE}'\")\n\nprint(\"\\n--- Running event loop. Press Ctrl+C to stop. ---\")\ntry:\n    AppHelper.runConsoleEventLoop(installInterrupt=True)\nexcept KeyboardInterrupt:\n    print(\"\\nStopping...\")\nfinally:\n    browser.stopBrowsingForPeers()\n    advertiser.stopAdvertisingPeer()\n    print(\"Stopped browsing and advertising.\")\n    sys.exit(0)","lang":"python","description":"This example demonstrates how to set up `MCNearbyServiceBrowser` and `MCNearbyServiceAdvertiser` to discover and be discovered by other devices using Multipeer Connectivity. It defines Python classes to act as delegates for handling discovery events and runs a console event loop to process callbacks. This simplified example focuses on peer discovery rather than full session management or data transfer."},"warnings":[{"fix":"Upgrade to Python 3.10 or later for PyObjC 12.x, or Python 3.9 or later for PyObjC 11.x.","message":"PyObjC has dropped support for older Python versions in recent major releases. Version 12.0 dropped Python 3.9, and version 11.0 dropped Python 3.8. Ensure your Python environment meets the minimum `requires_python` requirement.","severity":"breaking","affected_versions":">=11.0"},{"fix":"Review custom Python `__init__` implementations for Objective-C subclasses to ensure they correctly handle reference counts, especially if they are overriding `init` methods.","message":"The automatic reference counting (ARC) behavior for `init` family methods in Objective-C was corrected in PyObjC 11.1. 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 custom initializers in Python subclasses of Objective-C classes.","severity":"breaking","affected_versions":">=11.1"},{"fix":"If your Python subclass needs custom initialization, ensure you either implement `__new__` yourself or use Objective-C compatible initialization patterns (e.g., `init` methods) directly, carefully managing object creation and initialization steps.","message":"When subclassing Objective-C classes in Python, there were changes in how `__init__` and `__new__` interact in PyObjC 10.3. If you provide a custom `__new__` in your Python class (or its superclasses), `__init__` can be used. However, if you rely on the `__new__` provided by PyObjC, `__init__` cannot be used directly to initialize the instance.","severity":"gotcha","affected_versions":">=10.3"},{"fix":"Exercise caution when using PyObjC with free-threading in Python 3.13. Monitor PyObjC release notes for updates on free-threading support and report any issues encountered.","message":"PyObjC 11.0 introduced experimental support for Python 3.13's free-threading (PEP 703). While efforts have been made, users should be aware that this is an experimental feature and may not be fully stable or optimized. Earlier versions (e.g., PyObjC 10.3) explicitly did not support free threading.","severity":"gotcha","affected_versions":">=11.0, Python 3.13+"},{"fix":"Before upgrading PyObjC, verify that any specific frameworks you rely on are still present and supported, especially when targeting newer macOS versions. Consult the PyObjC release notes for details on removed bindings.","message":"Specific framework bindings can be removed from PyObjC if the underlying Apple framework is deprecated and removed from macOS SDKs. For example, the `IMServicePlugIn` bindings were removed in PyObjC 10.0 because the framework was removed in macOS 14. This applies to any `pyobjc-framework-*` package.","severity":"breaking","affected_versions":">=10.0"}],"env_vars":null,"last_verified":"2026-04-14T00:00:00.000Z","next_check":"2026-07-13T00:00:00.000Z"}