Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drag and Drop - create an NSItemProvider from my Model

Let's go by parts!

I'm trying to implement Drag and Drop in my UICollectionViewController.

The datasource for the UICollectionView is an array of a custom Model Struct I've created.

As required I have set my collectionView.dragDelegate = self and by doing so I've implemented the required protocol function itemsForBeginning session: UIDragSession...

Here's where my problem starts:

struct Model {
    // some variables
    // Some initializations
}

var myModelDatasource: [Model] = [model1, model2, model3, ...] // it's a simple case example

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

    let itemProvider = NSItemProvider(object: item)
    let dragItem = UIDragItem(itemProvider: itemProvider) // <-- ERROR HERE, Even If i force cast as NSItemProviderWriting
    dragItem.localObject = item

    return [dragItem]
}

I cannot create a dragItem because of my model doesn't conform to type NSItemProviderWriting.

If I force a datasource to be of type String and cast the item to NSString it works, but not with my struct Model.

Does anyone know how to resolve this issue?

like image 473
Ivan Cantarino Avatar asked Jan 23 '18 21:01

Ivan Cantarino


1 Answers

You should use a class (not a struct) for your Model, because as you suggested you have to be conform to NSItemProviderWriting (which inherits from NSObjectProtocol):

The protocol you implement on a class to allow an item provider to retrieve data from an instance of the class.

Many APIs expect subclasses of NSObject, hence you have to use a class, Apple blog: struct vs class

So your Model should be something like:

class Model : NSObject, NSItemProviderWriting {
    public static var writableTypeIdentifiersForItemProvider: [String] {
        return [] // something here
    }

    public func loadData(withTypeIdentifier typeIdentifier: String, forItemProviderCompletionHandler completionHandler: @escaping (Data?, Error?) -> Swift.Void) -> Progress? {
        return nil // something here
    }
}
like image 71
Andrea Mugnaini Avatar answered Nov 13 '22 20:11

Andrea Mugnaini