3

I am trying to enable drag and drop within my app as a mechanism for triggering a function. I have a TableView that displays a list of users and I have a collectionView that can display 3 distinct types of data - but only 1 type at a time.

I want the collectionView to accept the "drop" from the tableView when it is displaying Type1 data and Type3 data, but not for Type2 data. Right now, my drag and drop is working - but it is working for all 3 data types and I don't want it to work for Type2 data.

So currently, the action I trigger just ignores the dropped data if it is displaying Type2 data - but I would like to prevent the CollectionView from even accepting it (if possible). I don't want the users to see the visual indication that a drop is possible.

I suspect that I should be using the dropProposal for this - but after reading the Apple docs and multiple hours of searching with Google and YouTube for examples - I'm at a complete loss.

I do know I'm supposed to post my broken code here with my question, but the only thing I've even thought of to try and control this was to manipulate the collectionView.dropDelegate based on the data type I was displaying. I'm fairly confident that the correct solution will be very different - but here's what I tried:

if collectionMode != "Type2" {
  collectionView.dropDelegate = self
} else {
  collectionView.dropDelegate = nil
}

If you can help point me to the answer, please do.

E_net4
  • 27,810
  • 13
  • 101
  • 139
Jim
  • 55
  • 1
  • 7
  • 2
    Have you tried checking at `collectionView(_:canHandle:)`? [Document](https://developer.apple.com/documentation/uikit/uicollectionviewdropdelegate/2897386-collectionview) – Bill Feb 21 '19 at 05:09
  • Hi, @Jim can you do false user interaction programmatically when collectionMode is type 2, try with this. – AtulParmar Feb 21 '19 at 05:12
  • 1
    I would suggest you to stop this thing in your tableView before beginning drag check if cell is in type 2 do not perform drag . – Abu Ul Hassan Feb 21 '19 at 07:40
  • @Bill Thanks so much! Your suggestion works perfectly for me with only 2 lines of code. If you post it as the answer, I'll accept it. I don't know why none of my searches turned this up. – Jim Feb 21 '19 at 20:32
  • @AbuUlHassan Thanks for your suggestion. I hadn't thought of that - and it's a good idea - but it wouldn't have worked for me in this case since I did have another destination on the screen which was still a valid drop destination even when the collectionView was in Type2. – Jim Feb 21 '19 at 20:33
  • in that case i have one more suggestion do not use drop delegate you are in need of Custom drag drop, i have already implemented among tableViews if you say i can share that one with you :). – Abu Ul Hassan Feb 22 '19 at 04:04
  • OR you can stop it when drop ends, check if dropped item type is 2 and dropped location is prevented collectionView just return. – Abu Ul Hassan Feb 22 '19 at 04:07
  • @Abu Ul Hassan Thank you but your most recent suggestion is what I'm already doing and it doesn't answer my question of how to prevent the drop indicator (the + sign) when dragged over an invalid drop target. The first comment (from Bill) is the perfect solution to my problem. The :canHandle function is provided for exactly my scenario. As soon as Bill reposts his comment as an answer, I'll accept it. – Jim Feb 26 '19 at 04:29

2 Answers2

0

Try this,

func collectionView(_ collectionView: UICollectionView, 
        dragSessionWillBegin session: UIDragSession){

     guard if collectionMode == "Mode2" else { return }
     :
     :
     // Do stuff

}
dahiya_boy
  • 9,298
  • 1
  • 30
  • 51
  • Unfortunately this approach prevents dragging completely. There were other drop destinations (that I admittedly didn't mention) that this approach would have prevented. Thanks though. – Jim Feb 21 '19 at 20:36
  • @Jim It will allow only **Mode2** to drag. Try `if collectionMode != "Mode2" { return }` – dahiya_boy Feb 22 '19 at 04:34
0

The right answer in this case was to use the collectionView(_:canHandle:) function in the UICollectionViewDropDelegate for the drop target:

func collectionView(_ collectionView: UICollectionView, canHandle session: UIDropSession) -> Bool {
    if self.collectionMode == "Type2" {return false}
    return true
}

Apple Documentation - collectionView(_:canHandle:)

Other suggestions to add the logic to the UICollectionViewDragDelegate would prevent dragging the cell ANYWHERE - which might be an okay, and even more efficient approach in some cases - however putting the logic in the drop delegate allows for greater flexibility and the case in which there are multiple drop targets and not all of them are to be invalidated.

The correct answer to this question was provided by @Bill (Thanks!) but he posted his response as a comment, not an answer.

Jim
  • 55
  • 1
  • 7