Ad

Drag And Drop - Detect My Model Type Identifier

- 1 answer

I'm implementing drag and drop in my UICollectionViewController which has as its datasource a custom Model I've created for test purposes

The Model goes as the following:

class UserClass: NSObject, NSItemProviderWriting, NSItemProviderReading {
    static var readableTypeIdentifiersForItemProvider: [String] { return [] }

    static func object(withItemProviderData data: Data, typeIdentifier: String) throws -> Self {
        return self.init(someData: "test")
    }

    static var writableTypeIdentifiersForItemProvider: [String] { return [] }

    func loadData(withTypeIdentifier typeIdentifier: String, forItemProviderCompletionHandler completionHandler: @escaping (Data?, Error?) -> Void) -> Progress? {
        return nil
    }

    required init(someData:String) {}
}

This is my UICollectionViewDragDelegate

// This is the cv datasource
var myModel: [UserClass] = [userClass1, userClass2, userClass3, userClass4, ...]

// UICollectionViewDragDelegate

func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
    let item = myModel[indexPath.item]

    let itemProvider = NSItemProvider(object: item)
    let dragItem = UIDragItem(itemProvider: itemProvider)
    dragItem.localObject = item

    return [dragItem]
}

// To add multiple items for the drag session
func collectionView(_ collectionView: UICollectionView, itemsForAddingTo session: UIDragSession, at indexPath: IndexPath, point: CGPoint) -> [UIDragItem] {
    let item = myModel[indexPath.item]
    let itemProvider = NSItemProvider(object: item)
    let dragItem = UIDragItem(itemProvider: itemProvider)
    dragItem.localObject = item

    return [dragItem]
}

Here is a custom UIView that will handle/receive the drop:

class CustomView: UIView {
    override init(frame: CGRect) {
        super.init(frame: frame)            
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

extension CustomView: UIDropInteractionDelegate {
    func dropInteraction(_ interaction: UIDropInteraction, canHandle session: UIDropSession) -> Bool {
        return session.hasItemsConforming(toTypeIdentifiers: [""]) // <-- Which type is my model type ? 
    }

    func dropInteraction(_ interaction: UIDropInteraction, sessionDidUpdate session: UIDropSession) -> UIDropProposal {
        let dropLocation = session.location(in: self)
        let operation: UIDropOperation

        if self.frame.contains(dropLocation) {
            operation = session.localDragSession == nil ? .copy : .move
        } else {
            operation = .cancel
        }


        let dropProposal = UIDropProposal(operation: operation)
        dropProposal.isPrecise = true
        return dropProposal
    }

    func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession) {
        print("drop detected\n")

        session.loadObjects(ofClass: UserClass.self) { (objects) in
            objects.forEach({ (object) in
                print("object description:", object)
            })
        }
    }
}

The drag itself works as expected, one or more items respond to the drag session and get lifted but somehow my custom view doesn't detect the drop, none of its functions fire.

What I think might be the problem is that I don't know which session.hasItemsConforming(tyTypeIdentifiers:[]) I should set here because I don't know which type my model is.

Can I get a hand on this?

Ad

Answer

You may decide in the following way, which kind of objects can handle the dragging:

  1. all the objects:

    func dropInteraction(_ interaction: UIDropInteraction, canHandle session: UIDropSession) -> Bool {
       return true
    }
    
  2. accept only objects of type CustomView:

    func dropInteraction(_ interaction: UIDropInteraction, canHandle session: UIDropSession) -> Bool {
       return session.canLoadObjects(ofClass: CustomView.self)
    } 
    

I guess the latter is more appropriate for your case.

Ad
source: stackoverflow.com
Ad