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

SwiftUI拖放实现中performDrop后onDrag被自动重复调用的问题求助

SwiftUI拖放实现中performDrop后onDrag被自动重复调用的问题求助

我在SwiftUI的VStack中实现列表项的拖放重排序功能时,碰到了一个诡异的问题:每当完成一次拖放操作(performDrop方法执行完毕后),被拖拽的那个列表项的onDrag闭包会被自动触发一次,可我明明已经松开了拖拽手势,完全没有再次触发拖拽的操作。

先贴我的DropDelegate实现代码:

private struct StandardDropDelegate: DropDelegate {
    let destinationItem: StandardReorderedListItem
    @Binding var sourceContent: [StandardReorderedListItem]
    @Binding var draggedItem: StandardReorderedListItem?
    
    func dropUpdated(info: DropInfo) -> DropProposal? {
        return DropProposal(operation: .move)
    }
    
    func performDrop(info: DropInfo) -> Bool {
        print("dropped item: \(String(describing: draggedItem))\n===========================")
        self.draggedItem = nil
        return true
    }
    
    func dropEntered(info: DropInfo) {
        guard let draggedItem,
              let fromIndex = sourceContent.firstIndex(of: draggedItem),
              let toIndex = sourceContent.firstIndex(of: destinationItem),
              fromIndex != toIndex else { return }
        
        withAnimation(.easeInOut) {
            self.sourceContent.move(fromOffsets: IndexSet(integer: fromIndex),
                                    toOffset: (toIndex > fromIndex ? (toIndex + 1) : toIndex))
        }
    }
}

然后是列表视图的实现代码:

public struct StandardReorderedListView: View {
    @Binding private var content: [StandardReorderedListItem]
    @State private var draggedItem: StandardReorderedListItem?
    private let type: ReorderedListType = .standard
    
    public init(_ content: Binding<[StandardReorderedListItem]>) {
        self._content = content
    }
    
    @ViewBuilder public var body: some View {
        ScrollView(.vertical) {
            VStack {
                ForEach(content) { item in
                    ReorderedListItemView(state: .constant(.active), // Don't care
                                          isDragging: Binding(get: {
                                              self.draggedItem?.id == item.id
                                          }, set: { _ in }),
                                          label: item.label,
                                          itemType: type,
                                          icon: item.icon,
                                          action: item.action)
                    .onDrag {
                        print("drag item: \(item)\n===========================")
                        self.draggedItem = item
                        return NSItemProvider(object: item.id.uuidString as NSString )
                    }
                    .onDrop(of: [.text], delegate: StandardDropDelegate(destinationItem: item,
                                                                         sourceContent: $content,
                                                                         draggedItem: $draggedItem))
                }
            }
        }
    }
}

下面是控制台的输出日志,能清晰看到每次performDrop执行后,onDrag会被莫名触发一次:

drag item: StandardReorderedListItem(id: 3BDFE0B4-58DF-42C0-8FAB-109D3BFD191E, label: "Item 1", icon: Optional(SwiftUI.Image(provider: SwiftUI.ImageProviderBox<SwiftUI.Image.NamedImageProvider>)), action: Optional((Function)))
===========================
dropped item: Optional(StandardReorderedListItem(id: 3BDFE0B4-58DF-42C0-8FAB-109D3BFD191E, label: "Item 1", icon: Optional(SwiftUI.Image(provider: SwiftUI.ImageProviderBox<SwiftUI.Image.NamedImageProvider>)), action: Optional((Function))))
===========================
drag item: StandardReorderedListItem(id: 3BDFE0B4-58DF-42C0-8FAB-109D3BFD191E, label: "Item 1", icon: Optional(SwiftUI.Image(provider: SwiftUI.ImageProviderBox<SwiftUI.Image.NamedImageProvider>)), action: Optional((Function)))
===========================

补充说明:因为需要兼容iOS 15及以上版本,所以我没法用新的Transferable API,只能用这种传统的拖放实现方式。有没有大佬能帮我分析下问题出在哪,以及怎么解决这个自动触发onDrag的问题?感谢!


内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 12:12:59