前言

前段时间苹果刚推出了iOS15正式版,我也是第一时间就晋级了体会。期间体会到了一个十分有趣的交互如下视频。

DragAndDropKit-iOS15下一行代码集成跨应用间拖拽传递数据

如视频所示,iOS15下的苹果体系相册支撑将图片、视频,文本等直接拖拽复制到其他使用(目前亲测自带备忘录、腾讯QQ等是支撑的)。作为一个iOS工程师,第一时间对此产生了浓厚的爱好,第一时间查阅了官方文档,寻找完成方案,并以官方Api为根底,设计了DragAndDropKit,选用Swift编写,自带Drop、Drag命名空间,支撑链式语法,原则上两行代码就能够让您项目支撑拖拽资源共享到其他使用。

支撑版本

原则上支撑iPad OS 11 + , iPhone 是 iOS15+才支撑。

参考文档

drag and drop

下载地址

cocoaPods:


pod 'DragAndDropKit', '0.2.0'

github:

github.com/JerryFans/D…

DragAndDropKit演示与用法

DragAndDropKit-iOS15下一行代码集成跨应用间拖拽传递数据

Drag

拖拽本使用的data到其他完成了Drop协议的使用(亲测支撑体系相册、备忘录、网页里面的文本选中范围后直接拖拽等) DragAndDropKit本组件目前支撑拖拽UIImage、本地视频(途径下的视频)、网络图片、网络视频、文本等。目前支撑UIView及其类UIImageView、UILabel等、以及TableView、CollectionView快速拖动其子Cell。

UIView Drag Usage

最快只需两行代码即可完成拖拽,支撑链式写法


/*
你想拖拽时分给予的souce, 目前支撑NetworkImageDropSource、NetworkVideoDropSource、ImageDropSource、VideoDropSource、TextDropSource五种
*/
self.networkImageView.drag.dropSource = NetworkImageDropSource(imageUrl: "https://www.6hu.cc/wp-content/uploads/2023/02/1675900445-0433fdcff9f086e.jpg")
//开启拖拽
self.networkImageView.drag.enabled()

以及可选协议转链式闭包


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
}

UICollectionView & UITableView Drag Usage

UICollectionView、UITableView由于实习的协议不同,但本质写法是差不多的。

两者enabled后都有必要至少完成tableViewDidItemsForBeginning 或 collectionViewDidItemsForBeginning 闭包,回来相应的DragItem。DragItem封装的也是上面所说的5种DropSource。

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)
]
}

collectionView,如果要完成一些生命周期方法,能够完成一下生命周期闭包,同样是链式语法。


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")
}

DragAndDropKit-iOS15下一行代码集成跨应用间拖拽传递数据
|
DragAndDropKit-iOS15下一行代码集成跨应用间拖拽传递数据

Drop

从其他使用的接纳data到到本使用(亲测支撑体系相册、备忘录、QQ发送聊天等) DragAndDropKit本组件目前支撑Drop 接纳 UIImage、本地视频(途径下的视频)、网络图片、网络视频、文本等。目前也是支撑UIView及其类UIImageView、UILabel等、以及TableView、CollectionView快速拖动其子Cell。

Usage

支撑类型参数,所有UIView类别、TableView、CollectionView、均可赋值supportSources,用来声明drop接纳时分能支撑的类型数据,默许悉数支撑(Image、Video、Text)三种。(注:并不是体系api只支撑这三种,是这三种比较广泛,第一期先支撑此三种数据的接纳)


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

UIView Drop, didReceivedDropSource闭包有必要完成用以接纳到source后你对source的处理,其他可选。


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("请移入右上角图片中替换"),
.withoutAnimation(true),
.position(.top),
.autoDismissDuration(.seconds(value: 3)),
.bgColor(UIColor.jf.rgb(0x000000, alpha: 0.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 }
self.imageView.layer.borderWidth = 0.0
}
}

UICollectionView相似,也是collectionViewDidReceivedDropSource有必要处理,其他生命周期闭包,可选。


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)
}

UITableView相似,也是tableViewDidReceivedDropSource有必要处理,其他生命周期闭包,可选。


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)
}

效果:

DragAndDropKit-iOS15下一行代码集成跨应用间拖拽传递数据

后续支撑

  • tableView & collectionView 和体系相册相同支撑多选拖拽支撑(目前只能一个个拖cell)

  • 更多DropSource的支撑