https://developer.apple.com/documentation/uikit/drag_and_drop/making_a_view_into_a_drop_destination
"Adopt drop interaction APIs to selectively consume dragged content."
드래그된 컨텐트를 선택적으로 소비하기 위해 드롭 상호작용 API를 채택합니다.
뷰에서 드롭 상호작용 딜리게이트(UIDropInteractionDelegate
)를 구현함으로써 해당 뷰가 드롭된 아이템을 받을 수 있도록 합니다.
Note
UITextView
,UITableView
,UICollectionView
클래스는 드래그 아이템 소비를 위한 그들 고유의 특화된 지원을 제공합니다. 해당 클래스 문서에 나와있습니다.
UIView
의 모든 인스턴스 혹은 서브클래스는 드롭 대상으로써 기능할 수 있습니다. 이렇게 하려면 아래 단계를 수행해야 합니다.
UIDropInteraction
인스턴스)을 생성합니다.UIDropInteractionDelegate
프로토콜을 따르는 객체)를 구체화합니다.아래처럼 수행할 수 있습니다.
func customEnableDropping(on view: UIView, dropInteractionDelegate: UIDropInteractionDelegate) {
let dropInteraction = UIDropInteraction(delegate: dropInteractionDelegate)
view.addInteraction(dropInteraction)
}
사용자가 드래그 세션에서 드롭 대상으로 터치 포인트를 이동할 때, 즉시 이를 거부할 수 있고, 혹은 시스템에게 딜리게이트 객체로 지속하도록 할 수도 있습니다. 응답은 아래처럼 제공할 수 있습니다.
func dropInteraction(_ interaction: UIDropInteraction, canHandle session: UIDropSession) -> Bool {
// Ensure the drop session has an object of the appropriate type
return session.canLoadObjects(ofClass: UIImage.self)
}
이 예시는 드롭 대상이 오직 UIImage
만 소비할 수 있음을 가정합니다. 메소드 구현은 반환문에서 이 타입을 테스트할 수 있습니다. 앱의 상태에 따라 드롭 세션을 거부하기 위해 이 메소드를 사용할 수도 있습니다. 드롭 세션은 UIDropSession
프로토콜을 따르는 시스템 관리 객체입니다. 드롭되는 아이템에 대한 정보를 위해 드롭 세션에 접근할 수도 있습니다.
dropInteraction(_:canHandle:)
메소드는 앱이 아이템을 받을 것인지에 대한 시스템의 물음에 응답할 수 있는, 앱의 유일한 기회입니다. 예를 들어 만약 앱이 소비할 수 있는 데이터 표현이 아닌 것을 포함하는 경우 드롭 세션을 선제적으로 거부하거나 소비하는 드래그 아이템이 앱 상태에서 적합하지 않은 경우 선제적으로 거부할 수 있습니다. 앱이 드롭된 아이템을 받거나 거부할 수 있는 선언적 기회는dropInteraction(_:sessionDidUpdate:)
프로토콜 메소드의 구현에 있습니다.
뷰가 드롭 세션으로부터 데이터를 받을 수 있는 기회가 있으려면, dropInteraction(_:sessionDidUpdate:)
프로토콜 메소드를 구현해야 합니다. 구현에서 drop proposal(UIDropOperation
열거형으로부터 온 상수인 동작 타입을 구체화하는 UIDropProposal
객체)을 반환해야 합니다.
아래처럼 구현합니다.
func dropInteraction(_ interaction: UIDropInteraction, sessionDidUpdate session: UIDropSession) -> UIDropProposal {
// Propose to the system to copy the item from the source app
return UIDropProposal(operation: .copy)
}
대신 앱이 드롭된 아이템을 거부하려는 경우 UIDropOperation.cancel
상수를 반황해야 합니다.
시스템은 사용자가 드래그 세션에서 터치 포인트를 드롭 가능한 뷰로 움직일 때 이 프로토콜 메소드를 호출합니다. 이는 뷰의 dropInteraction(_:canHandle:)
메소드에서 false
를 반환해 드롭을 거부하지 않는 한 메소드를 호출합니다(Consider Accepting the Drag Items를 살펴보시기 바랍니다).
Consider Acceptating the Drag Items는 이 글의 앞에서 나왔습니다.
드롭 상호작용 딜리게이트와 시스템 사이 대화의 마지막 단계는 사용자가 소스 앱으로부터 드래그했던 데이터를 언제 소비할 것인지에 관한 단계입니다. 아래는 드롭 상호작용 딜리게이트가 드래그 아이템을 로드하기 위해 드롭 세션을 요청하는 것을 보여주고 있습니다.
func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession) {
// Consume drag items (in this example, of type UIImage).
session.loadObjects(ofClass: UIImage.self) { imageItems in
let images = imageItems as! [UIImage]
self.imageView.image = images.first
}
// Perform additional UI updates as needed.
}
dropInteraction(_:performDrop:)
메소드는 대상 앱의 드래그 아이템 표현 요청에 대한 유일한 기회입니다. 아이템을 받는 것은 잠재적으로 시간을 소비하며, 비동기로 작동합니다. 아이템을 받기 위해 이 메소드 내부에서 기다리지 않도록 해야 합니다. 대신 이 메소드로부터 빠르게 반환합니다.
Note
위에서 보이는 것처럼 메인 스레드를 자동으로 사용하는loadObjects(ofClass:completion:)
편의 메소드를 사용하지 않는다면, UI 작동을 명시적으로 메인 스레드에 디스패치해야 합니다. 예를 들어DispatchQueue.main.async
함수를 사용할 수 있습니다.
드롭 세션에 대한 터치 지점이 드롭 대상으로 설정한 뷰로 움직이면, 시스템은 드롭 상호작용 딜리게이트와의 대화를 초기화합니다. 이 대화는 앱에게 드롭을 수락하거나 거부할 수 있는 기회를 주고, 드래그 아이템을 소비할 준비를 하게 해주며, 모델과 UI를 업데이트할 수 있는 기회도 줍니다. 아래가 예시입니다.
그림은 드래그 아이템을 소비하는 단계를 설명하고 있습니다.
UIDropSession
프로토콜을 따르는 객체)을 인스턴스화합니다.dropInteraction(_:canHandle:)
메소드를 호출합니다. 앱이 드래그 아이템을 소비할 수 있는지, 소비할 것인지에 대해 확인해야 합니다.dropInteraction(_:sessionDidEnter:)
프로토콜 메소드를 호출합니다. 드래그 아이템을 소비할 준비를 합니다.dropInteraction(_:sessionDidUpdate:)
프로토콜 메소드를 호출합니다. 구현은 UIDropProposal
을 반환하거나, 시스템이 세션을 끝냅니다.dropInteraction(_:performDrop:)
메소드를 호출합니다. 이는 드래그 아이템의 표현을 요청하는 앱의 유일한 기회입니다.소스 앱과 대상 앱 사이에서 데이터 표현 규약을 전달하기 위해 드래그 아이템을 사용합니다.
https://developer.apple.com/documentation/uikit/drag_and_drop/understanding_a_drag_item_as_a_promise
https://velog.io/@panther222128/Understanding-a-Drag-Item-as-a-Promise
드래그를 위한 아이템 제공을 위해 드래그 상호작용 API를 채택합니다.
https://developer.apple.com/documentation/uikit/drag_and_drop/making_a_view_into_a_drag_source
https://velog.io/@panther222128/Making-a-View-into-a-Drag-Source