Making a View into a Drop Destination

Panther·2021년 8월 3일
0

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를 채택합니다.

Overview

뷰에서 드롭 상호작용 딜리게이트(UIDropInteractionDelegate)를 구현함으로써 해당 뷰가 드롭된 아이템을 받을 수 있도록 합니다.

Note
UITextView, UITableView, UICollectionView 클래스는 드래그 아이템 소비를 위한 그들 고유의 특화된 지원을 제공합니다. 해당 클래스 문서에 나와있습니다.

Enable a View as a Drop Destination

UIView의 모든 인스턴스 혹은 서브클래스는 드롭 대상으로써 기능할 수 있습니다. 이렇게 하려면 아래 단계를 수행해야 합니다.

  1. 드롭 상호작용(UIDropInteraction 인스턴스)을 생성합니다.
  2. 드롭 상호작용의 딜리게이트(UIDropInteractionDelegate 프로토콜을 따르는 객체)를 구체화합니다.
  3. 뷰의 상호작용 속성에 상호작용을 추가합니다.

아래처럼 수행할 수 있습니다.

func customEnableDropping(on view: UIView, dropInteractionDelegate: UIDropInteractionDelegate) {
    let dropInteraction = UIDropInteraction(delegate: dropInteractionDelegate)
    view.addInteraction(dropInteraction)
}

Consider Accepting the Drag Items

사용자가 드래그 세션에서 드롭 대상으로 터치 포인트를 이동할 때, 즉시 이를 거부할 수 있고, 혹은 시스템에게 딜리게이트 객체로 지속하도록 할 수도 있습니다. 응답은 아래처럼 제공할 수 있습니다.

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:) 프로토콜 메소드의 구현에 있습니다.

Provide the Required Drop Proposal

뷰가 드롭 세션으로부터 데이터를 받을 수 있는 기회가 있으려면, 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는 이 글의 앞에서 나왔습니다.

Consume the Data in 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 함수를 사용할 수 있습니다.

Understand a Drop Destination in Context

드롭 세션에 대한 터치 지점이 드롭 대상으로 설정한 뷰로 움직이면, 시스템은 드롭 상호작용 딜리게이트와의 대화를 초기화합니다. 이 대화는 앱에게 드롭을 수락하거나 거부할 수 있는 기회를 주고, 드래그 아이템을 소비할 준비를 하게 해주며, 모델과 UI를 업데이트할 수 있는 기회도 줍니다. 아래가 예시입니다.

그림은 드래그 아이템을 소비하는 단계를 설명하고 있습니다.

  1. 사용자가 손가락을 화면으로 이동함으로써 드래그 세션의 터치 지점은 앱에서 설정된 뷰 내부가 됩니다. 시스템이 드롭 동작을 관리하기 위해 드롭 세션(그림에는 나타나지 않았지만 UIDropSession 프로토콜을 따르는 객체)을 인스턴스화합니다.
  2. 시스템은 드롭 상호작용 딜리게이트의 dropInteraction(_:canHandle:) 메소드를 호출합니다. 앱이 드래그 아이템을 소비할 수 있는지, 소비할 것인지에 대해 확인해야 합니다.
  3. 시스템은 딜리게이트의 dropInteraction(_:sessionDidEnter:) 프로토콜 메소드를 호출합니다. 드래그 아이템을 소비할 준비를 합니다.
  4. 시스템은 딜리게이트의 dropInteraction(_:sessionDidUpdate:) 프로토콜 메소드를 호출합니다. 구현은 UIDropProposal을 반환하거나, 시스템이 세션을 끝냅니다.
  5. 만약 사용자가 드롭 완료 의도를 확인하면, 시스템은 딜리게이트의 비동기 dropInteraction(_:performDrop:) 메소드를 호출합니다. 이는 드래그 아이템의 표현을 요청하는 앱의 유일한 기회입니다.

See Also


First Steps

Understanding a Drag Item as a Promise

소스 앱과 대상 앱 사이에서 데이터 표현 규약을 전달하기 위해 드래그 아이템을 사용합니다.

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

Making a View into a Drag Source

드래그를 위한 아이템 제공을 위해 드래그 상호작용 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


0개의 댓글