Ios 客户端应用程序错误-UITargetedPreview的视图或容器当前都不在窗口中

Ios 客户端应用程序错误-UITargetedPreview的视图或容器当前都不在窗口中,ios,swift,uikit,Ios,Swift,Uikit,我在试图修复的Xcode控制台中请求有关UIKit警告的帮助: 客户端应用程序错误-UITargetedPreview的视图或容器当前都不在窗口中。这违反了UIDraginInteraction API合同,可能会导致严重的视觉问题。 我有一个UITableView的拖动源,它实现了UITableViewDragDelegate。表视图位于拆分视图主视图中,目标位于拆分视图控制器中。拖放交互非常有效。问题是来自Xcode的相当可怕的错误 UIDragItem由以下内容生成: extension

我在试图修复的Xcode控制台中请求有关UIKit警告的帮助:

客户端应用程序错误-UITargetedPreview的视图或容器当前都不在窗口中。这违反了UIDraginInteraction API合同,可能会导致严重的视觉问题。

我有一个
UITableView
的拖动源,它实现了
UITableViewDragDelegate
。表视图位于拆分视图主视图中,目标位于拆分视图控制器中。拖放交互非常有效。问题是来自Xcode的相当可怕的错误

UIDragItem
由以下内容生成:

extension Store: NSItemProviderWriting {  

    var dragItem: UIDragItem {  
        let dragItem = UIDragItem(itemProvider: NSItemProvider(object: self))  
        dragItem.localObject = self  
        dragItem.previewProvider = {  
            let image = UIImageView(image: self.imageFront)  
            image.frame = CGRect(x: 0, y: 0, width: 40, height: 40) // magic number for store preview size  
            return UIDragPreview(view: image)  
        }  
        return dragItem  
    }  
}  
我尝试中断所有的
UIDragDelegate
方法,但是在生成预览时会出现警告,这似乎是在过程的后面

我将发布我的拖动方法,以查看是否缺少任何内容

提前谢谢

// MARK: - Table view drag delegate  

extension StoresTableViewController: UITableViewDragDelegate {  
    func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {  
        return [stores[indexPath.row].dragItem]  
    }  

    func tableView(_ tableView: UITableView, dragSessionWillBegin session: UIDragSession) {  
        guard let draggedStore = session.items.first?.localObject as? Store else { return }  
        if draggedStore.maxSimilarStores > session.items.count {  
            tableView.performBatchUpdates({  
                let index = stores.firstIndex(of: draggedStore)!  
                stores.remove(at: index)  
                stores.insert(draggedStore.copy() as! Store, at: index)  
                tableView.reloadRows(at: [IndexPath(row: index, section: 0)], with: .fade)  
            }, completion: nil)  
        }  
    }  

    func tableView(_ tableView: UITableView, itemsForAddingTo session: UIDragSession, at indexPath: IndexPath, point: CGPoint) -> [UIDragItem] {  
        guard let draggedStore = session.items.first?.localObject as? Store else { return [] }  
        let tableStore = stores[indexPath.row]  
        if draggedStore.name == tableStore.name && draggedStore.maxSimilarStores > session.items.count {  
            return [tableStore.dragItem]  
        } else {  
            return []  
        }  
    }  

    func tableView(_ tableView: UITableView, dragPreviewParametersForRowAt indexPath: IndexPath) -> UIDragPreviewParameters? {  
        guard let cell = tableView.cellForRow(at: indexPath) as? StoreTableViewCell else { return nil }  
        let parameters = UIDragPreviewParameters()  
        parameters.visiblePath = UIBezierPath(rect: cell.storeImageView.frame)  
        return parameters  
    }  
} 
我已经创建了一个调试项目来复制:


谢谢

我的解决方案是放弃
UITableViewDragDelegate
并从自定义的
UITableViewCell
实现拖动交互。我不确定这是否是正确的方法,但它已清除了错误

对于一个简单的拖放演示,我发现这个答案非常有用。显然,苹果公司的文件

我的线索是错误本身,抱怨缺少
UITargetedPreview
的视图或容器。从我所看到的
UITargetedPreview
不是
UITableViewDelegate
系统的一部分,我假设是因为
UITableViewDelegate
系统纯粹是为在
UITableView
本身内部绘制和放置而设计的

我的用途不同,我试图从
UITableView
拖动到任何地方

TLDR 新的
UITableView
删除所有
UITableViewDragDelegate
方法,并添加所需的自定义单元格初始值设定项:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "StoreCell", for: indexPath) as! StoreTableViewCell
        let dragInteraction = UIDragInteraction(delegate: cell)
        cell.addInteraction(dragInteraction)
        cell.store = stores[indexPath.row]
        {...}
        return cell
    }
自定义
UITableViewCell
为:

class StoreTableViewCell: UITableViewCell {

    var store: Store?

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    {...}
}

extension StoreTableViewCell: UIDragInteractionDelegate {
    func dragInteraction(_ interaction: UIDragInteraction, itemsForBeginning session: UIDragSession) -> [UIDragItem] {
        if let dragItem = store?.dragItem {
            return [dragItem]
        }
        return []
    }

    func dragInteraction(_ interaction: UIDragInteraction, previewForLifting item: UIDragItem, session: UIDragSession) -> UITargetedDragPreview? {
        if let store = store, let frontImage = store.imageFront {
            let imageView = UIImageView(image: frontImage)
            imageView.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
            let target = UIPreviewTarget(container: storeImageView, center: session.location(in: storeImageView))
            let parameters = UIPreviewParameters()
            parameters.backgroundColor = .clear
            let preview = UITargetedDragPreview(view: imageView, parameters: parameters, target: target)
            return preview
        }
        return nil
    }
}

请注意,
UIPreviewTarget
是自定义
UITableViewCell
中的图像(尽管我希望这可以是任何视图)我从
UIDragSession
中心设置预览中心。

我的解决方案是放弃
UITableViewDragDelegate
,并从自定义的
UITableViewCell
实现拖动交互。我不确定这是否是正确的方法,但它已清除了错误

对于一个简单的拖放演示,我发现这个答案非常有用。显然,苹果公司的文件

我的线索是错误本身,抱怨缺少
UITargetedPreview
的视图或容器。从我所看到的
UITargetedPreview
不是
UITableViewDelegate
系统的一部分,我假设是因为
UITableViewDelegate
系统纯粹是为在
UITableView
本身内部绘制和放置而设计的

我的用途不同,我试图从
UITableView
拖动到任何地方

TLDR 新的
UITableView
删除所有
UITableViewDragDelegate
方法,并添加所需的自定义单元格初始值设定项:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "StoreCell", for: indexPath) as! StoreTableViewCell
        let dragInteraction = UIDragInteraction(delegate: cell)
        cell.addInteraction(dragInteraction)
        cell.store = stores[indexPath.row]
        {...}
        return cell
    }
自定义
UITableViewCell
为:

class StoreTableViewCell: UITableViewCell {

    var store: Store?

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    {...}
}

extension StoreTableViewCell: UIDragInteractionDelegate {
    func dragInteraction(_ interaction: UIDragInteraction, itemsForBeginning session: UIDragSession) -> [UIDragItem] {
        if let dragItem = store?.dragItem {
            return [dragItem]
        }
        return []
    }

    func dragInteraction(_ interaction: UIDragInteraction, previewForLifting item: UIDragItem, session: UIDragSession) -> UITargetedDragPreview? {
        if let store = store, let frontImage = store.imageFront {
            let imageView = UIImageView(image: frontImage)
            imageView.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
            let target = UIPreviewTarget(container: storeImageView, center: session.location(in: storeImageView))
            let parameters = UIPreviewParameters()
            parameters.backgroundColor = .clear
            let preview = UITargetedDragPreview(view: imageView, parameters: parameters, target: target)
            return preview
        }
        return nil
    }
}
请注意,
UIPreviewTarget
是自定义
UITableViewCell
中的图像(尽管我希望这可以是任何视图),我从
UIDragSession
中心设置预览中心