preface

Some time ago, apple just released the official version of iOS15, and I upgraded my experience at the first time. Experience a very interesting interaction during the following video.

As shown in the video, iOS15 apple system album support pictures, videos, text and other direct drag copy to other applications (currently pro test with a memo, Tencent QQ is supported). As an iOS engineer, I was immediately interested in this. I consulted the official documents to find the implementation scheme. Based on the official Api, I designed DragAndDropKit, which was written by Swift, came with Drop and Drag namespaces, and supported chain syntax. In principle, two lines of code should allow your project to support dragging and sharing resources to other applications.

Support version

In principle, iPad OS 11 + is supported, and iPhone iOS15+ is supported.

Reference documentation

drag and drop

Download address

cocoaPods:

Pod 'DragAndDropKit', '0.1.0 from'Copy the code

github:

Github.com/JerryFans/D…

DragAndDropKit demo and usage

Drag

DragAndDropKit This component currently supports dragging and dropping UIImage, local video (video in the path), network image, network video, and text. UIView and its classes UIImageView, UILabel, TableView, CollectionView, etc.

UIView Drag Usage

Drag and drop can be implemented as soon as two lines of code, supporting chain writing

/* When you want to drag souce, Currently, NetworkImageDropSource, NetworkVideoDropSource, ImageDropSource, VideoDropSource, and TextDropSource are supported self.networkImageView.drag.dropSource = NetworkImageDropSource(imageUrl: "Http://image.jerryfans.com/sample.jpg") / / open drag self.net workImageView. Drag. Enabled ()Copy the code

And optional protocol chain closures


self.networkImageView.drag.enabled().didEndSession { interaction, session, operation in

}.didMoveSession { interaction, session in

}.didPreviewForDragSession { interaction, item, session in

return

}.didAllowsMoveOperationSession { interaction, session in

return false

}

Copy the code

UICollectionView & UITableView Drag Usage

UICollectionView, UITableView because the internship protocol is different, but the essence of writing is similar.

After both enabled must achieve at least tableViewDidItemsForBeginning or collectionViewDidItemsForBeginning closures, returned to the corresponding DragItem. DragItem encapsulates the same five dropSources described above.

tableView


tableView.drag.enabled().tableViewDidItemsForBeginning { [weak self] tableView, session, indexPath in

guard let self = self else { return [] }

//if you are the custom model, you should convert to DropSource Object (Text,Image or Video Drop Source)

let source = self.models[indexPath.row]

let itemProvider = NSItemProvider(object: source)

return [

UIDragItem(itemProvider: itemProvider)

]

}

Copy the code

CollectionView, if you want to implement some lifecycle methods, you can implement a lifecycle closure, again, chain syntax.

collectionView.drag.enabled() .collectionViewDidItemsForBeginning { [weak self] collectionView, session, indexPath in return self? .dragAndDropVM.dragItems(for: indexPath) ?? [] }.collectionViewWillBeginDragSession { collectionView, session in JFPopup.toast(hit: "collection view will begin drag") }.collectionViewDidEndDragSession { collectionView, session in JFPopup.toast(hit: "collection view did end drag") }Copy the code

|

Drop

DragAndDropKit This component supports Drop to receive UIImage, local video (video in path), network image, network video, text, etc. It also supports UIView and its classes UIImageView, UILabel, TableView, CollectionView, etc.

Usage

Support type parameters. All UIView categories, TableView, CollectionView, and supportSources can be assigned to declare the types of data that can be supported by DROP. By default, all three types of data (Image, Video, and Text) are supported. (Note: the system API does not only support these three kinds of data, but these three kinds of data are more extensive. The first phase will support the receipt of these three kinds of data.)


c.drop.supportSources = [.rawImage,.rawVideo,.text]

Copy the code

UIView Drop, didReceivedDropSource closures must be implemented to handle the source after you receive it, optionally.

self.view.drop.supportSources = [.rawImage] self.view.drop.enabled().didReceivedDropSource { [weak self] dropSources in for (_, item) in dropSources.enumerated() { if let imageSource = item as? ImageDropSource { self? .imageView.image = imageSource.image self? . ImageView. Layer. BorderWidth = 0.0 break}}}. DidEnterDropSession {interaction, Session in if session.localDragSession == nil {jfPopupview.popup.toast {[. Hit (" Please replace in image in upper right corner "), .withoutAnimation(true), .position(.top), .autoDismissDuration(.seconds(value: 3)), .bgColor(UIColor.jf.rgb(0x000000, alpha: 3))]}}}. DidUpdateDropSource {[weak self] interaction, session in guard let self = self else { return UIDropProposal(operation: UIDropOperation.cancel) } let dropLocation = session.location(in: self.view) let operation: UIDropOperation if self.imageView.frame.contains(dropLocation) { operation = session.localDragSession == nil ? .copy : .move self.checkIsMatch(match: true) } else { operation = .cancel self.checkIsMatch(match: false) } self.updateLayers(forDropLocation: dropLocation) return UIDropProposal(operation: operation) }.didEndDropSession { [weak self] interaction, session in guard let self = self else { return } let dropLocation = session.location(in: self.view) self.updateLayers(forDropLocation: dropLocation) self.checkIsMatch(match: false) }.didExitDropSession { [weak self] interaction, Session in guard let self = self else {return} the self. The imageView. Layer. BorderWidth = 0.0}}Copy the code

UICollectionView similar, is also collectionViewDidReceivedDropSource must deal with, other life cycle closures, optional.


c.drop.supportSources = [.rawImage,.rawVideo,.text]

c.drop.enabled().collectionViewDidReceivedDropSource { [weak self] collectionView, coordinator, dropSources in

let destinationIndexPath: IndexPath

if let indexPath = coordinator.destinationIndexPath {

destinationIndexPath = indexPath

} else {

let item = collectionView.numberOfItems(inSection: 0)

destinationIndexPath = IndexPath(item: item, section: 0)

}

var indexPaths = [IndexPath]()

for (index, item) in dropSources.enumerated() {

let indexPath = IndexPath(item: destinationIndexPath.item + index, section: destinationIndexPath.section)

self?.dragAndDropVM.addItem(item, at: indexPath.item)

indexPaths.append(indexPath)

}

self?.collectionView.insertItems(at: indexPaths)

}

Copy the code

UITableView similar, is also tableViewDidReceivedDropSource must deal with, other life cycle closures, optional.


t.drop.supportSources = [.rawImage,.rawVideo,.text]

t.drop.enabled().tableViewDidReceivedDropSource { [weak self] tableView, coordinator, dropSources in

guard let self = self else { return }

let destinationIndexPath: IndexPath

if let indexPath = coordinator.destinationIndexPath {

destinationIndexPath = indexPath

} else {

let item = tableView.numberOfRows(inSection: 0)

destinationIndexPath = IndexPath(row: item, section: 0)

}

var indexPaths = [IndexPath]()

for (index, item) in dropSources.enumerated() {

let indexPath = IndexPath(row: destinationIndexPath.item + index, section: destinationIndexPath.section)

self.models.insert(item, at: indexPath.row)

indexPaths.append(indexPath)

}

tableView.insertRows(at: indexPaths, with: .bottom)

}

Copy the code

Effect:

Subsequent support

  • TableView & collectionView supports multi-select drag and drop like system albums (currently only one cell can be dragged)

  • More DropSource support