以下內(nèi)容都是自己閱讀實踐所得鄙皇,如有誤請多指教,謝謝。
(示例代碼為Swift杆故,剛學(xué),請多指教)
Drag and Drop 簡單介紹
Drag and Drop是iOS11的一套基于UIKit的新API溉愁。它可以讓你拖動屏幕上的視圖進行一些操作处铛,包括但不限于移動,復(fù)制內(nèi)容拐揭。甚至可以在不同App之間進行Drag and drop撤蟆,就像WWDC上面演示的一樣: Introducing Drag and Drop,但是在iPhone上堂污,Drag and Drop僅支持單App枫疆。
接下來我將通過幾個Demo來講解如何去簡單開發(fā)Drag and Drop的應(yīng)用。
今天這篇文章將講解如何使用UIView的新屬性pasteConfiguration去最簡單的實現(xiàn)一個拖動進行粘貼的操作敷鸦,如圖:
Step1 給View添加Drag
UIDragInteraction & UIDropInteraction
這兩個可以說是Drag'n Drop 開發(fā)中最基本的類息楔,都繼承自UIInteraction,屬性上也基本相同扒披。
你可以把他們當(dāng)成UIGestureRecognizer值依,使用的時候只需要初始化一個UIDragInteraction/UIDropInteraction,設(shè)定好delegate碟案,再添加到相應(yīng)的view即可:
//Add an UIDragInteraction to support drag
dragImageView.addInteraction(UIDragInteraction.init(delegate: self))
此時你的view就可以支持長按進行拖動了(但是在iPhone上同樣的代碼卻不起作用愿险,不知道為什么,明白的小伙伴歡迎解答)
注意使用的時候需要將view的isUserInteractionEnabled設(shè)為true
Step2 給目的地上的View添加pasteConfiguration
在本例中我們創(chuàng)建兩個UIImageView价说,一個用來展示原始圖片并提供拖動(dragImageView)辆亏,拖到另一個上(pasteImageView)后,進行粘貼的操作鳖目。
這里只需要在dragImageView上添加UIDragInteraction即可扮叨,要讓pasteImageView支持Drop的話,上文已經(jīng)說到领迈,最簡單的方法就是配置pasteConfiguration屬性:
pasteImageView.pasteConfiguration = UIPasteConfiguration(forAccepting: UIImage.self)
以上代碼就是聲明pasteImageView支持drop功能彻磁,并且你可以把包含UIImage數(shù)據(jù)的對象拖到這個pasteImageView上來進行粘貼碍沐。當(dāng)然通過配置UIPasteConfiguration,可以支持很多不同的數(shù)據(jù)類型衷蜓。
同時必須重寫改view的paste方法累提,下文詳說
Step3 實現(xiàn)UIDragInteraction
這時運行demo會發(fā)現(xiàn)即時我們在圖片上按再長的時間,也沒有任何變化磁浇,也不能拖動斋陪。
因為我們必須提供一個被拖動的對象,當(dāng)然是數(shù)據(jù)層面上的置吓,用來告訴系統(tǒng)我們正在拖text呢 還是image呢鳍贾,以便其他支持Drop的view可以根據(jù)數(shù)據(jù)類型來決定是否能夠接收drop。
func dragInteraction(_ interaction: UIDragInteraction, itemsForBeginning session: UIDragSession) -> [UIDragItem] {
if interaction.view == dragImageView {
let dragImage = dragImageView.image
let itemProvider = NSItemProvider.init(object: dragImage!)
let dragItem = UIDragItem.init(itemProvider: itemProvider)
return [dragItem]
}
else if interaction.view == dragTextLabel {
let dragText = "Try drag me~"
let itemProvider = NSItemProvider.init(object: dragText as NSString)
let dragItem = UIDragItem.init(itemProvider: itemProvider)
return [dragItem]
}
else {
return []
}
}
這里涉及到兩個新類交洗,UIDragItem & NSItemProvider
NSItemProvider簡單來說就是用來在Drag and Drop骑科,或者Extension app 和Host app之間傳輸數(shù)據(jù)的類。
UIDragItem則是像對NSItemProvider的進一步封裝构拳,除了包含傳輸數(shù)據(jù)外咆爽,還可以自定義一些數(shù)據(jù)。
具體用法就是如上:
let dragImage = dragImageView.image
let itemProvider = NSItemProvider.init(object: dragImage!)
let dragItem = UIDragItem.init(itemProvider: itemProvider)
return [dragItem]
將我們要拖動的Image對象一層層包起來返回即可置森。
這時再運行demo就發(fā)現(xiàn)可以拖動了斗埂,而且當(dāng)圖片懸浮在pasteImageView上時可以看到右上角有加號,說明此處支持粘貼的操作凫海,但是鼠標(biāo)一松開就Crash了呛凶。
Step4 重寫Paste
上面的Crash信息顯示:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'pasteItemProviders: must be overridden if pasteConfiguration is not nil.'
上文就說必須重寫pasteItemProviders。
那我們重寫一下pasteImageView的pasteItemProviders方法行贪,讓它支持粘貼漾稀。
override func paste(itemProviders: [NSItemProvider]) {
for dragItem in itemProviders {
if dragItem.canLoadObject(ofClass: UIImage.self) {
dragItem.loadObject(ofClass: UIImage.self, completionHandler: { (image, error) in
if image != nil {
DispatchQueue.main.async {
self.tipLayer.removeFromSuperlayer()
self.customBorderLayer.removeFromSuperlayer()
self.image = (image as! UIImage)
}
}
})
}
}
}
以上操作就是先判斷這個NSItemProvider是否可以load UIImage這一類的數(shù)據(jù),如果可以我們就load出來進行界面更新等操作建瘫。
這時再運行一遍應(yīng)該就可以復(fù)制了崭捍。
-----
以上全部就是比較詳細的介紹了如何使用view的pasteConfiguration來簡單實現(xiàn)Drag to paste,留下一個拖動文字的功能可以自己嘗試實現(xiàn)一下啰脚。
小提示:textField不用配置pasteConfiguration,自己對于NSString類型的數(shù)據(jù)有默認實現(xiàn)殷蛇。