onDrag - 拖动结束时没有反馈

问题描述 投票:0回答:1

我一直在探索 SwiftUI 的

onDrag
修饰符,但当它结束时似乎没有任何反馈这一事实让我有点困惑。有些人建议对
NSItemProvider
deinit
进行接线和操作,这解决了一些情况,但有一种情况特别不能解决,因为 SwiftUI 似乎正在泄漏
NSItemProvider
实例。这是重现该问题的最小设置:

import SwiftUI

struct DragDropDebugView: View {
    @State private var isDragging = false

    var body: some View {
        VStack {
            Text(isDragging ? "Dragging" : "Not dragging")
            Color.red
                .onDrag(
                    {
                        isDragging = true
                        return DraggableItemProvider {
                            self.isDragging = false
                        }
                    },
                    preview: {
                        Color.blue.frame(width: 50, height: 50)
                    }
                )
        }
    }
}

private final class DraggableItemProvider: NSItemProvider {
    private var deinitAction: () -> Void

    init(deinitAction: @escaping () -> Void) {
        print("DraggableItemProvider init")
        self.deinitAction = deinitAction
        super.init()
    }

    deinit {
        print("DraggableItemProvider deinit")
        deinitAction()
    }
}

如果我长按触发拖动操作,拖动项目并释放,此设置可以正常工作,我可以看到

DraggableItemProvider deinit
正在打印。如果我只是长按并释放而不将其拖动,则永远不会打印
deinit
,我可以在内存图中看到泄漏的实例:

有人知道解决这个问题的方法吗?

ios swiftui drag-and-drop drag
1个回答
0
投票

我将可用 API 的意图解释如下:

  1. “拖动对象”的范围仅限于其呈现和提供数据。
  2. “放置目标”的范围仅限于观察目标区域中兼容的拖动对象。

=>

  1. API 不提供任何方法来跟踪拖动对象发生的情况,除非通过可行的放置目的地观察到。
  2. NSItemProvider 的生命周期并不是拖动操作状态的可靠指示。 (我假设它迟早会被清理,并且不存在真正的内存泄漏。)

因此,接受这些限制,我们必须找到兼容的实现,或者完全找到另一个解决方案(即自定义拖动处理或库。)

这是一个简单、惯用的解决方案,其行为与您的尝试相似但不完全相同。

struct DragDropDebugView: View {
    @State private var isDragActive = false

    var body: some View {
        VStack {
            Text(isDragActive ? "Dragging" : "Not dragging")
            Color.red
                .draggable(Data())
        }
        .onDrop(of: [.data], isTargeted: $isDragActive) { _ in true }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.