You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI跨List拖拽崩溃:拖拽到单元格触发NSInternalInconsistencyException

SwiftUI跨List拖拽崩溃问题

问题描述

实现了两个SwiftUI List间的拖拽功能,拖拽到列表项间隙时正常,但拖拽到单元格本身时,应用会在释放拖拽前直接崩溃。

已移除dropDestination内所有代码逻辑,崩溃仍会发生,且dropDestination代码从未被调用。询问这是SwiftUI的bug还是实现问题。

崩溃复现

崩溃复现动图

代码实现

var body2: some View {
    HStack {
        VStack {
            Text("title-pending")
            
            List {
                ForEach(viewModel.pendingOrders) { order in
                    RestaurantOrderCardView(order: order)
                        .background(cardBackground)
                        .draggable(order)
                }
                .listRowSeparator(.hidden)
                .listRowBackground(Color.clear)
                .padding(.top)
            }
            .listStyle(.plain)
            .background(listBackground)
        }
        
        VStack {
            Text("title-in-preparation")
            
            List {
                ForEach(viewModel.inPreparationOrders) { item in
                    RestaurantOrderCardView(order: item)
                        .background(cardBackground)
                }
                .dropDestination(for: RestaurantOrder.self) { items, offset in
                    guard let firstItem = items.first else { return }
                    withAnimation {
                        viewModel.dropItem(firstItem, offset: offset)
                    }
                }
                .listRowSeparator(.hidden)
                .listRowBackground(Color.clear)
                .padding(.top)
            }
            .listStyle(.plain)
            .background {
                if !viewModel.inPreparationOrders.isEmpty {
                    listBackground
                }
            }
            .overlay {
                if viewModel.inPreparationOrders.isEmpty {
                    RoundedRectangle(cornerRadius: 8)
                        .foregroundColor(!inDropArea ? .grayBackgroundColor : .grayBackgroundColor.opacity(0.25))
                        .ignoresSafeArea()
                        .dropDestination(for: RestaurantOrder.self) { items, location in
                            guard let firstItem = items.first else { return false }
                            withAnimation {
                                viewModel.dropItem(firstItem, offset: 0)
                            }
                            return true
                        } isTargeted: { inDropArea in
                            withAnimation {
                                self.inDropArea = inDropArea
                            }
                        }
                }
            }
        }
    }
}

崩溃日志

2023-01-06 11:25:05.995303+0100 SimplifyStayAdmin[78761:2158775] *** Assertion failure in -[_UICollectionViewDragAndDropController _beginDragAndDropInsertingItemAtIndexPath:], _UICollectionViewDragAndDropController.m:620

2023-01-06 11:25:06.074407+0100 SimplifyStayAdmin[78761:2158775] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not get the cell at indexPath <NSIndexPath: 0x8846e25efd6dfbf1> {length = 2, path = 0 - 0} to start the reording portion of the Drag-and-drop'

*** First throw call stack:

(
    0   CoreFoundation                      0x000000018040e7c8 __exceptionPreprocess + 172
    1   libobjc.A.dylib                     0x0000000180051144 objc_exception_throw + 56
    2   Foundation                          0x0000000180b13b98 _userInfoForFileAndLine + 0
    3   UIKitCore                           0x0000000109a546ec -[_UICollectionViewDragAndDropController _beginDragAndDropInsertingItemAtIndexPath:] + 540
    4   UIKitCore                           0x0000000109a53064 -[_UICollectionViewDragAndDropController beginReorderingForItemAtIndexPath:cell:] + 204
    5   UIKitCore                           0x0000000109a1bad0 -[UICollectionView _beginInteractiveMovementForItemAtIndexPath:] + 196
    6   UIKit                               0x000000011803040c -[UICollectionViewAccessibility beginInteractiveMovementForItemAtIndexPath:] + 80
    7   UIKitCore                           0x0000000109a5c55c -[_UICollectionViewDragDestinationController _reorderingDisplayLinkDidTick] + 912
    8   QuartzCore                          0x0000000187dd04f8 _ZN2CA7Display11DisplayLink14dispatch_itemsEyyy + 808
    9   QuartzCore                          0x0000000187ec89a8 _ZL22display_timer_callbackP12__CFMachPortPvlS1_ + 336
    10  CoreFoundation                      0x000000018033ee94 __CFMachPortPerform + 172
    11  CoreFoundation                      0x000000018037387c __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 56
    12  CoreFoundation                      0x0000000180372e9c __CFRunLoopDoSource1 + 496
    13  CoreFoundation                      0x000000018036d43c __CFRunLoopRun + 2176
    14  CoreFoundation                      0x000000018036c7a4 CFRunLoopRunSpecific + 584
    15  GraphicsServices                    0x0000000188ff7c98 GSEventRunModal + 160
    16  UIKitCore                           0x000000010a1f237c -[UIApplication _run] + 868
    17  UIKitCore                           0x000000010a1f6374 UIApplicationMain + 124
    18  SwiftUI                             0x000000010e6150d4 OUTLINED_FUNCTION_51 + 496
    19  SwiftUI                             0x000000010e614f7c OUTLINED_FUNCTION_51 + 152
    20  SwiftUI                             0x000000010dd7ab60 OUTLINED_FUNCTION_10 + 88
    21  SimplifyStayAdmin                   0x000000010044d0c4 $s17SimplifyStayAdmin0abC3AppV5$mainyyFZ + 40
    22  SimplifyStayAdmin                   0x000000010044d378 main + 12
    23  dyld                                0x00000001080c1fa0 start_sim + 20
    24  ???                                 0x00000001081c9e50 0x0 + 4431060560
    25  ???                                 0x0869800000000000 0x0 + 606156362346397696
)

libc++abi: terminating with uncaught exception of type NSException

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not get the cell at indexPath <NSIndexPath: 0x8846e25efd6dfbf1> {length = 2, path = 0 - 0} to start the reording portion of the Drag-and-drop'

terminating with uncaught exception of type NSException

CoreSimulator 857.14 - Device: iPad (10th generation) (D79A0AD8-4970-4F84-A5F9-078DAFB697A3) - Runtime: iOS 16.2 (20C52) - DeviceType: iPad (10th generation)

解决方案

这是iOS 16.x版本SwiftUI List拖拽的已知bug,根源是底层UICollectionView尝试获取拖拽目标单元格时失败,可通过以下方式修复:

方案1:禁用目标List的内部重排序

给目标List添加环境变量,阻止系统触发内部重排序逻辑,避免与跨List拖拽冲突:

List {
    // 原有列表内容
}
.environment(\.editMode, .constant(.inactive))
.listStyle(.plain)

方案2:调整dropDestination的作用范围

不要将dropDestination附加在ForEach上,直接绑定到List本身,避免系统将单元格识别为重排序目标:

List {
    ForEach(viewModel.inPreparationOrders) { item in
        RestaurantOrderCardView(order: item)
            .background(cardBackground)
    }
    .listRowSeparator(.hidden)
    .listRowBackground(Color.clear)
    .padding(.top)
}
.dropDestination(for: RestaurantOrder.self) { items, offset in
    guard let firstItem = items.first else { return false }
    withAnimation {
        viewModel.dropItem(firstItem, offset: offset)
    }
    return true
}
.listStyle(.plain)

额外检查:如果RestaurantOrderCardView有自定义手势或交互逻辑,暂时移除测试是否干扰系统拖拽识别。

内容的提问来源于stack exchange,提问作者Dorian Pavetić

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 01:35:36