- drag and drop :在app之间或者app内生动地移动数据
- 响应快速,在需要的时候move or copy 数据
- 异步传输数据
- 安全,数据只对destination app 可见
- iPhone 只能在app内使用drag and drop
-
Phase of a drag session
-
Enabling a Drag
-
Lift Phase
-
Drag Items
- Enabling a Drop
- UIPasteConfiguration
UIResponders have a new paste configuration property
// Indicate you can accept or paste strings
let config = UIPasteConfiguration(typeIdentifiersForAcceptingClass: NSString.self)
view.pasteConfiguration = config
// Will be called for both Drag and Drop, and Copy/Paste
override func paste(itemProviders: [NSItemProvider]) { }
- UIDropInteraction
1. Drag Phase: The delegate responds to drag events.
2. Set Down Phase: On touch up, the drag session may be cancelled, The drag preview animates back.Or the drop is accepted, The delegate is told to perform drop.
3. Data Transfer Phase: Delegate requests data representation of items.
-
API Roadmap
- Drag and Drop Timeline
-
not accepted
-
accepted
-
- API Essentials
func dragInteraction(_ interaction: UIDragInteraction,
itemsForBeginning session: UIDragSession) -> [UIDragItem] {
let itemProvider = NSItemProvider(object: "Hello World" as NSString)
let dragItem = UIDragItem(itemProvider: itemProvider)
return [ dragItem ]
}
func dropInteraction(_ interaction: UIDropInteraction,
sessionDidUpdate session: UIDropSession) -> UIDropProposal {
return UIDropProposal(operation: UIDropOperation)
}
func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession) {
session.loadObjects(ofClass: UIImage.self) { objects in
for image in objects as! [UIImage] {
self.imageView.image = image
}
}
}
或者
func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession) {
for item in session.items {
item.itemProvider.loadObject(ofClass: UIImage.self) { (object, error) in
if object != nil {
DispatchQueue.main.async {
self.imageView.image = (object as! UIImage)
}
} else {
// Handle the error
}
}
}
- Drag Interaction Delegate
// Lift Phase
// Custom Preview, preview 不属于任何视图层级,所以需要target
func dragInteraction(_ interaction:UIDragInteraction,
previewForLifting item:UIDragItem, session:UIDragSession)
-> UITargetedDragPreview? {
let imageView = UIImageView(image: UIImage(named: "MyDragImage"))
let dragView = interaction.view!
let dragPoint = session.location(in: dragView)
let target = UIDragPreviewTarget(container: dragView, center: dragPoint)
return UITargetedDragPreview(view: imageView, parameters:UIDragPreviewParameters(),target:target)
}
// animator
func dragInteraction(_ interaction: UIDragInteraction, willAnimateLiftWith animator: UIDragAnimating,
session: UIDragSession) {
animator.addAnimations { self.view.backgroundColor = UIColor.gray }
animator.addCompletion { position in if position == .end {
// The lift ended normally, and a drag is now happening
}
else if position == .start {
// The lift was cancelled and the animation returned to the start
}
}
}
// Drag Phase
Session begins and moves
func dragInteraction(_ interaction: UIDragInteraction, sessionWillBegin session: UIDragSession)
func dragInteraction(_ interaction: UIDragInteraction, sessionAllowsMoveOperation session: UIDragSession) -> Bool
// And more methods asking questions about the new drag session
func dragInteraction(_ interaction: UIDragInteraction, sessionDidMove session: UIDragSession)
// Adding items during the session
func dragInteraction(_ interaction: UIDragInteraction, itemsForAddingTo session: UIDragSession,
withTouchAt point: CGPoint) -> [UIDragItem]
// custom preview
func dragInteraction(_ interaction:UIDragInteraction,
previewForLifting item:UIDragItem, session:UIDragSession)
-> UITargetedDragPreview?
// The drag session ends
func dragInteraction(_ interaction: UIDragInteraction, session: UIDragSession,
willEndWith operation: UIDropOperation)
// The session ends in a cancel
func dragInteraction(_ interaction: UIDragInteraction, previewForCancelling item: UIDragItem,
withDefault defaultPreview: UITargetedDragPreview) -> UITargetedDragPreview?
func dragInteraction(_ interaction: UIDragInteraction, item: UIDragItem,
willAnimateCancelWith animator: UIDragAnimating)
func dragInteraction(_ interaction: UIDragInteraction, session: UIDragSession
didEndWith operation: UIDropOperation)
// The session ends in a copy or move
func dragInteraction(_ interaction: UIDragInteraction, session: UIDragSession
didEndWith operation: UIDropOperation)
func dragInteraction(_ interaction: UIDragInteraction, sessionDidTransferItems session: UIDragSession)
- Drop Interaction Delegate
// Session enters the view
func dropInteraction(_ interaction: UIDropInteraction, canHandle session: UIDropSession) -> Bool {
return session.canLoadObjects(ofClass: UIImage.self)
// return session.hasItemsConforming(toTypeIdentifiers: [kUTTypeImagePNG as String])
}
// Session enters and exits the view, may be mutiple times
func dropInteraction(_ interaction: UIDropInteraction, sessionDidEnter session: UIDropSession)
func dropInteraction(_ interaction: UIDropInteraction,
sessionDidUpdate session: UIDropSession) -> UIDropProposal
func dropInteraction(_ interaction: UIDropInteraction, sessionDidExit session: UIDropSession)
// Springloading: When session hovers over a view
// UIKit自动触发action
let button = UIButton()
button.isSpringLoaded = true
// 自定义action
let springLoadedInteraction = UISpringLoadedInteraction { (interaction, context) in
// Activate springloading here
}
view.addInteraction(springLoadedInteraction)
// Session ends over a different view
func dropInteraction(_ interaction: UIDropInteraction, sessionDidEnd session: UIDropSession)
// Drop animations
func dropInteraction(_ interaction: UIDropInteraction, previewForDropping item: UIDragItem,
withDefault defaultPreview: UITargetedDragPreview) -> UITargetedDragPreview?
func dropInteraction(_ interaction: UIDropInteraction, item: UIDragItem,
willAnimateDropWith animator: UIDragAnimating)
func dropInteraction(_ interaction: UIDropInteraction, concludeDrop session: UIDropSession)
// Data transfer
func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession)
let progress = item.itemProvider.loadObject(ofClass: UImage.self) { (object, error) in
// Closure is called when object or error are available
}
let fractionCompleted = progress.fractionCompleted let isFinished = progress.isFinished progress.cancel()
let sessionProgress = session.progress