SwiftUI 从一个列表拖到另一个列表

Posted

技术标签:

【中文标题】SwiftUI 从一个列表拖到另一个列表【英文标题】:SwiftUI drag from one list to another list 【发布时间】:2020-05-25 08:53:05 【问题描述】:

我正在尝试在列表之间拖放。

我尝试过的:

我在 UIKIt 和使用 UIViewControllerRepresentable 中找到了一个解决方案。但这不是我想要的。

另一个解决方案是在列表中使用 .onDrag ,但它在 iPad 上有效,在 iPhone 上无效。

如何在 iPhone 上的两个列表之间移动项目?

【问题讨论】:

请阅读***.com/help/how-to-ask。和***.com/help/minimal-reproducible-example。这不是“我们免费为您编写代码”的平台,而是“我们帮助您编写代码” 这可能会帮助你:swiftui-lab.com/drag-drop-with-swiftui 【参考方案1】:

看看这个:

BUT -> 正如您所写,它不适用于列表(仅在 iPad 上)和 VStack 您可以从左到右或从右到左拖动。

import SwiftUI


struct BookmarksList2: View 
    @State private var links: [URL] = [
        URL(string: "https://www.apple.com")!
    ]

    var body: some View 
        VStack 
            ForEach(links, id: \.self)  url in
                Text(url.absoluteString)
                    .onDrag 
                        NSItemProvider(object: url as NSURL)
                
            
            .onInsert(of: ["public.url"], perform: drop)
            .onDrop(
                of: ["public.url"],
                delegate: BookmarksDropDelegate(bookmarks: $links)
            )
        
        .navigationBarTitle("Bookmarks")
    
    private func drop(at index: Int, _ items: [NSItemProvider]) 
           for item in items 
               _ = item.loadObject(ofClass: URL.self)  url, _ in
                   DispatchQueue.main.async 
                       url.map  self.links.insert($0, at: index) 
                   
               
           
       


struct BookmarksList3: View 
    @State private var links: [URL] = [
        URL(string: "https://www.google.com")!
    ]

    var body: some View 
        VStack 
            ForEach(links, id: \.self)  url in
                Text(url.absoluteString)
                    .onDrag 
                        NSItemProvider(object: url as NSURL)
                
            
            .onInsert(of: ["public.url"], perform: drop)
            .onDrop(
                of: ["public.url"],
                delegate: BookmarksDropDelegate(bookmarks: $links)
            )
        
        .navigationBarTitle("Bookmarks")
    

    private func drop(at index: Int, _ items: [NSItemProvider]) 
        for item in items 
            _ = item.loadObject(ofClass: URL.self)  url, _ in
                DispatchQueue.main.async 
                    url.map  self.links.insert($0, at: index) 
                
            
        
    


struct BookmarksDropDelegate: DropDelegate 
    @Binding var bookmarks: [URL]

    func performDrop(info: DropInfo) -> Bool 
        guard info.hasItemsConforming(to: ["public.url"]) else 
            return false
        

        let items = info.itemProviders(for: ["public.url"])
        for item in items 
            _ = item.loadObject(ofClass: URL.self)  url, _ in
                if let url = url 
                    DispatchQueue.main.async 
                        self.bookmarks.insert(url, at: 0)
                    
                
            
        

        return true
    


struct ContentView : View 

    var body: some View 

        HStack 
            BookmarksList2()
            Divider()
            BookmarksList3()
        
    


struct ContentView_Previews: PreviewProvider 
    static var previews: some View 
        ContentView()
    

【讨论】:

在 Xcode 12 beta 2 中,可以在同一个列表中拖放(使用 .onInsert),但是如果将项目拖到现有元素上,则在两个列表之间拖放不起作用,绘制到最后并放在那里,首先添加了另一个项目。在这种情况下,在调用自定义 drop 函数之前会发生崩溃。在我看来,SwiftUI 内部的列表内容管理有一个错误。

以上是关于SwiftUI 从一个列表拖到另一个列表的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SwiftUI 列表行中独立选择复选框按钮和 NavigationLink 到另一个视图

从 SwiftUI 中的列表中删除绑定

从嵌套结构 swift ui 创建列表

Swift 检测 UICollectionViewCell 是不是被拖到另一个 UICollectionViewCell 之上

如何在 SwiftUI 中将数据从视图传递到另一个视图?

在不使用导航链接的情况下获取 SwiftUI 列表中的选定项目