@ WWDC 17
Lift ➣ Drag ➣ Set Down ➣ Data Transfer 순으로 진행됨
Lift | Drag | Set Down | Data Transfer |
---|---|---|---|
Long Press | Previews | Cancel | Representations |
Lift preview | Tap to add | Drop | Lazy delivery (Background, By File Provder) |
Spring-loading | Targeting | Progress |
Concepts - UIDragInteraction
-
A drag interaction is attached to a view
drag interaction이 뷰에 추가되고, drag interaction delegate를 이용해 interaction을 다룬다.
import UIKit let view: UIView = ... let delegate: UIDragInteractionDelegate = ... let dragInteration = UIDragInteraction(delegate: delegate) view.addInteraction(dragInteraction)
Concepts - UIDragInteraction
- The delegate provides drag items when the view lifts
- No drag items -> drag gesture fails
Concepts - UIDragItem
- A drag item represents a model object
- A drag item embodies
- Drag previews
- Item provider
Concepts - UIPasteConfiguration
-
UIResponders have a new paste configuration property
// Indicate you can accept or paste strings let config = UIPasteConfiguration(typeIdentifiersAcceptingClass: NSString.self) view.pasteConfiguration = config
// Will be called for both Drag and Drop, and Copy/Paste override func paste(itemProviders: [NSItemProvider]) { }
Concepts - UIDropInteraction
- A drop interaction is attached to a view
Conceppts - UIDropInteraction
- The delegate responds to drag events
Concepts - UIDropInteraction
- 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
Concepts - UIDropInteraction
- Or the drop is accepted
- The delegate is told to perform drop
- Delegate requests data representation of items
data transfer는 asynchronous하게 동작한다.
Get the items to drag
func dragInteraction(_ interaction: UIDragInteraction, itemsForBeginning session: UIDragSession) -> [UIDragItem] {
let itemProvider = NSItemProvider(object: "Hello World" as NSString)
let dragItem = UIDragItem(itemProvider: itemProvider)
return [dragItem]
}
Get the drop proposal
func dropInteraction(_ interaction: UIDropInteraction, sessionDidUpdate session: UIDropSession) -> UIDropProposal {
return UIDropProposal(operation: UIDropOperation)
}
UIDropOperation - enum
.cancel
.copy
.move
.forbidden
.move
- Delegates must cooperate to make it look like a move
- Only within a single app
- Drag interaction delegate must allow moves
- Drop interaction delegate checks
UIDropSession allowsMoveOperation
Perform the drop
func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession) {
session.loadObjects(ofClass: UIImage.self) { object in
for image in object 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) n
if object != nil {
DispatchQueue.main.async {
self.imageView.image = (object as! UIImage)
}
} else {
// Handle the error
}
}
}
}
-
Lift
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) }
func dragInteraction(_ interaction: UIDragInteraction, willAnimateLiftWith animator: UIDragAnimating, session: UIDragSession) { animator.addAnimations { self.view.backgroundColor = UIColor.gray } animator.addCompletion { position in if pposition == .end { // The lift ended normally, and a drag is now happening } else if position == .start { // The lift was cancelled and the animation retrned to the start } } }
-
Session begins and moves
func dragInteraction(_ interaction: UIDragInteraction, sessionWillBegin session: UIDragSession) func dragInteraction(_ interaction: UIDragInteraction, sessionAllowsMoveOperation session: UIDragSession) -> Bool func dragInteraction(_ interaction: UIDragInteraction, sessionDidMove session: UIDragSession)
-
Adding items during the session
func dragInteraction(_ interaction: UIDragInteraction, itemsForAddingTo session: UIDragSession, withTouchAt point: CGPoint) -> [UIDragItem] func dragInteraction(_ interaction: UIDragInteraction, ppreviewForLifting item: UIDragItem, session: UIDragSession) -> UITargetedDragPreview?
-
The session ends
func dragInteraction(_ interaction: UIDragInteraction, session: UIDragSession, willEndsWith 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: UIDropAnimating) 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)
-
Session enters the view
func dropInteraction(_ interaction: UIDropInteraction, canHandle session: UIDropSession) -> Bool { return session.canLoadObjects(ofClass: UIImage.self) }
import MobileCoreServices func dropInteraction(_ interaction: UIDropInteraction, canHandle session: UIDropSession) -> Bool { return session.hasItemsConforming(toTypeIdentifiers: [kUTTypeImagePNG as String]) }
-
Session enters and exits the view
func dropInteraction(_ interaction: UIDropInteraction, sessionDidEnter session: UIDropSession) func dropInteraction(_ interaction: UIDropInteraction, sessionDidUpdate session: UIDropSession) -> UIDropProposal func dropInteraction(_ interaction: UIDropInteraction, sessionDidExit session: UIDropSession)
-
Session ends over a different view
func dropInteraction(_ interaction: UIDropInteraction, sessionDidEnd session: UIDropSession)
-
Drop animations
func dropInteraction(_ interaction: UIDropInteraction, previewForDroppiing item: UIDragItem, withdefault defaultPreview: UITargetedDragPreview) -> UITargetedDragPreview? func dropInteraction(_ interaction: UIDropInteraction, item: UIDragItem, willAnimatedDropWith animator: UIDragAnimating) func dropInteraction(_ interaction: UIDropInteraction, concludeDrop session: UIDropSession)
-
Data transfer
let progress = item.itemProvider.loadObject(ofClass: UIImage.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.rogress
-
When session hovers over a view
let button = UIButton() button.isSpringLoaded = true let springLoadedInteraction = UISpringLoadedInteraction { (interaction, context) in // Activate springloading here } view.addInteraction(springLoadedInteraction)
-
Essential functions
func dragInteraction(_ interaction: UIDragInteraction, itemsForBeginning session: UIDragSession) -> [UIDragItem] func dropInteraction(_ interaction: UIDropInteraction, sessionDidUpdate session: UIDropSession) -> UIDropProposal func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession)
drag and drop을 커스텀하기 위해서는 위에서 봤던 다른 delegate들을 이용해서 커스텀한다. 필수적인 delegate method는 이 세 가지다!
- Explore the system
- Try adding a drop target
- Enable a drag source
- Spring load some of your controls
- Dig deeper into the Drag and Drop APIs
뺌!!1 이런 api들 있지롱 더 공부해봐랏! 뭔가 정말 introducing drag and drop이라 소개 정도의 영상이었다!