MultiPeer Connectivity Example Code Crashes in Swift 6

When working with this example code from Apple Implementing Interactions Between Users in Close Proximity, the example comes by default in Swift5, however when I switch to Swift6, the example would crash.

I also observed the same crash in my personal project (this is why I tried the example code), currently blocking me.

To repro:

  1. Download sample code from link
  2. Go to build settings and use Swift 6
  3. Go to AppDelegate and change @UIApplicationMain to @main as this is required for Swift 6.
  4. Run the sample app on 2 iOS devices.

Observe the crash:

Thread 1 Queue : com.apple.main-thread (serial)
Thread 5 Queue : TPC issue queue (serial)
com.apple.uikit.eventfetch-threadThread 11 Queue : com.apple.MCSession.syncQueue (serial)
Thread 15 Queue : com.apple.MCSession.callbackQueue (serial)
#0	0x00000001010738e4 in _dispatch_assert_queue_fail ()
#1	0x00000001010aa018 in dispatch_assert_queue$V2.cold.1 ()
#2	0x0000000101073868 in dispatch_assert_queue ()
#3	0x000000019381f03c in _swift_task_checkIsolatedSwift ()
#4	0x000000019387f21c in swift_task_isCurrentExecutorWithFlagsImpl ()
#5	0x000000019381ed88 in _checkExpectedExecutor ()
#6	0x0000000101016d48 in @objc MPCSession.session(_:peer:didChange:) ()
#7	0x000000024a09f758 in __56-[MCSession syncPeer:changeStateTo:shouldForceCallback:]_block_invoke ()
#8	0x000000010107063c in _dispatch_call_block_and_release ()
#9	0x000000010108a2d0 in _dispatch_client_callout ()
#10	0x0000000101078b4c in _dispatch_lane_serial_drain ()
#11	0x00000001010797d4 in _dispatch_lane_invoke ()
#12	0x0000000101085b20 in _dispatch_root_queue_drain_deferred_wlh ()
#13	0x00000001010851c4 in _dispatch_workloop_worker_thread ()
#14	0x00000001f01633b8 in _pthread_wqthread ()
Enqueued from com.apple.MCSession.syncQueue (Thread 11) Queue : com.apple.MCSession.syncQueue (serial)
#0	0x0000000101075be0 in dispatch_async ()
#1	0x000000024a09f660 in -[MCSession syncPeer:changeStateTo:shouldForceCallback:] ()
#2	0x000000024a0a365c in __63-[MCSession nearbyConnectionDataForPeer:withCompletionHandler:]_block_invoke ()
#3	0x000000010107063c in _dispatch_call_block_and_release ()
#4	0x000000010108a2d0 in _dispatch_client_callout ()
#5	0x0000000101078b4c in _dispatch_lane_serial_drain ()
#6	0x00000001010797d4 in _dispatch_lane_invoke ()
#7	0x0000000101085b20 in _dispatch_root_queue_drain_deferred_wlh ()
#8	0x00000001010851c4 in _dispatch_workloop_worker_thread ()
#9	0x00000001f01633b8 in _pthread_wqthread ()
#10	0x00000001f01628c0 in start_wqthread ()
Enqueued from com.apple.main-thread (Thread 1) Queue : com.apple.main-thread (serial)
#0	0x0000000101075be0 in dispatch_async ()
#1	0x000000024a0a352c in -[MCSession nearbyConnectionDataForPeer:withCompletionHandler:] ()
#2	0x000000024a0bb8c0 in __55-[MCNearbyServiceAdvertiser syncHandleInvite:fromPeer:]_block_invoke_2 ()
#3	0x0000000101018004 in thunk for @escaping @callee_unowned @convention(block) (@unowned ObjCBool, @unowned MCSession?) -> () ()
#4	0x0000000101017db0 in MPCSession.advertiser(_:didReceiveInvitationFromPeer:withContext:invitationHandler:) at /Users/lyt/Downloads/ImplementingInteractionsBetweenUsersInCloseProximity/NIPeekaboo/MultipeerConnectivitySupport/MPCSession.swift:161
#5	0x0000000101017f74 in @objc MPCSession.advertiser(_:didReceiveInvitationFromPeer:withContext:invitationHandler:) ()
#6	0x000000024a0bb784 in __55-[MCNearbyServiceAdvertiser syncHandleInvite:fromPeer:]_block_invoke ()
#7	0x000000010107063c in _dispatch_call_block_and_release ()
#8	0x000000010108a2d0 in _dispatch_client_callout ()
#9	0x00000001010ab4c0 in _dispatch_main_queue_drain.cold.5 ()
#10	0x0000000101080778 in _dispatch_main_queue_drain ()
#11	0x00000001010806b4 in _dispatch_main_queue_callback_4CF ()
#12	0x0000000195380520 in __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ ()
#13	0x0000000195332d14 in __CFRunLoopRun ()
#14	0x0000000195331c44 in _CFRunLoopRunSpecificWithOptions ()
#15	0x0000000234706498 in GSEventRunModal ()
#16	0x000000019acacddc in -[UIApplication _run] ()
#17	0x000000019ac51b0c in UIApplicationMain ()
#18	0x000000019ad8d860 in ___lldb_unnamed_symbol296044 ()
#19	0x000000010101a680 in static UIApplicationDelegate.main() ()
#20	0x000000010101a5f0 in static AppDelegate.$main() ()
#21	0x000000010101a7bc in main ()
#22	0x00000001923aae28 in start ()
com.apple.multipeerconnectivity.gcksession.recvproccom.apple.multipeerconnectivity.gcksession.sendproccom.apple.multipeerconnectivity.eventcallback.eventcbproccom.apple.CFSocket.privatecom.apple.CFStream.LegacyThreadcom.apple.NSURLConnectionLoader
Answered by DTS Engineer in 864588022
when I switch to Swift6, the example would crash

This doesn’t surprise me. The Multipeer Connectivity API hasn’t been updated for Swift concurrency [1]. Specifically, MCSession makes delegate callbacks on some unspecified serial queue, and Swift concurrency is that trapping because it’s expecting the callback to arrive on the main thread/queue/actor.

You can fix this by implementing a non-isolated conformance to MCSessionDelegate. Having said that, my advice is that you use this as excuse to move away from Multipeer Connectivity completely. It has at least one known crashing bug that… well… while I can’t predict the future, the fact that it’s remained unfixed for the last five years should tell you something |-:

If you decide you want to tackle this now, see Moving from Multipeer Connectivity to Network Framework for lots of advice.

Note I haven’t updated that post to use the new Network framework API we introduced in iOS 26 [2]. That’s because most folks are still supporting iOS 18, and thus can’t rely on the new API. Hopefully that’ll change next year.


Oh, and I’d appreciate you filing a bug against that sample. While Multipeer Connectivity is less than ideal, that sample should either stop using it or use it in a Swift 6 friendly way.

Please post your bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] And giving that it’s teetering on the edge of deprecation, I doubt it ever will be.

[2] See WWDC 2025 Session 250 Use structured concurrency with Network framework.

when I switch to Swift6, the example would crash

This doesn’t surprise me. The Multipeer Connectivity API hasn’t been updated for Swift concurrency [1]. Specifically, MCSession makes delegate callbacks on some unspecified serial queue, and Swift concurrency is that trapping because it’s expecting the callback to arrive on the main thread/queue/actor.

You can fix this by implementing a non-isolated conformance to MCSessionDelegate. Having said that, my advice is that you use this as excuse to move away from Multipeer Connectivity completely. It has at least one known crashing bug that… well… while I can’t predict the future, the fact that it’s remained unfixed for the last five years should tell you something |-:

If you decide you want to tackle this now, see Moving from Multipeer Connectivity to Network Framework for lots of advice.

Note I haven’t updated that post to use the new Network framework API we introduced in iOS 26 [2]. That’s because most folks are still supporting iOS 18, and thus can’t rely on the new API. Hopefully that’ll change next year.


Oh, and I’d appreciate you filing a bug against that sample. While Multipeer Connectivity is less than ideal, that sample should either stop using it or use it in a Swift 6 friendly way.

Please post your bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] And giving that it’s teetering on the edge of deprecation, I doubt it ever will be.

[2] See WWDC 2025 Session 250 Use structured concurrency with Network framework.

MultiPeer Connectivity Example Code Crashes in Swift 6
 
 
Q