Supporting Drag and Drop in Collection Views

Panther·2021년 8월 27일
0

https://developer.apple.com/documentation/uikit/views_and_controls/collection_views/supporting_drag_and_drop_in_collection_views

"Initiate drags and handle drops from a collection view."

컬렉션 뷰로부터 드래그를 시작하고 드롭을 처리합니다.

Overview

컬렉션 뷰는 표시되는 아이템으로 작동하는 특수한 API를 통해 드래그 앤 드롭을 지원합니다. 드래그를 지원하려면 드래그 딜리게이트 객체(UICollectionViewDragDelegate 프로토콜을 채택하는 객체)를 정의하고, 정의한 객체를 컬렉션 뷰의 dragDelegate 속성에 할당해야 합니다. 드롭을 처리하려면 드롭 딜리게이트 객체(UICollectionViewDropDelegate 프로토콜을 채택하는 객체)를 정의하고, 정의한 객체를 컬렉션 뷰의 dropDelegate 속성에 할당해야 합니다.

Drag Items from the Collection View

컬렉션 뷰는 대부분의 드래그 관련 상호작용을 관리하지만, 어떤 아이템이 드래그되는지를 구체화할 필요가 있습니다. 드래그 제스쳐가 발생하면 컬렉션 뷰는 드래그 세션을 생성하고, 드래그 딜리게이트 객체의 collectionView(_:itemsForBeginning:at:) 메소드를 호출합니다. 이 메소드로부터 비어있지 않은 배열을 반환하면 컬렉션 뷰는 구체화한 아이템의 드래그를 시작합니다. 특정 인덱스 경로로부터 아이템 드래그를 사용자에게 허용하지 않으려면 비어있는 배열을 반환해야 합니다.

Note
추가적인 드래그 관련 상호작용을 관리하려면 UICollectionViewDragDelegate 프로토콜의 다른 메소드를 사용하시기 바랍니다. 예를 들어 드래그되고 있는 아이템의 모양을 커스터마이징할 수 있으며, 사용자가 현재 드래그 세션에 아이템을 추가할 수 있게 구현할 수도 있습니다.

collectionView(_:itemsForBeginning:at:) 메소드의 구현에서 아래처럼 하시기 바랍니다.

  1. 하나 혹은 하나 이상의 NSItemProvider 객체를 생성합니다. 컬렉션 뷰의 아이템에 대한 데이터를 나타내기 위해 아이템 제공자를 사용해야 합니다.
  2. 각각의 아이템 제공자 객체를 UIDragItem 객체로 감싸야 합니다.
  3. 각 드래그 아이템의 localObject 속성에 값을 할당하는 것을 고려해야 합니다. 이 단계는 선택적이지만 같은 앱 내에서 드래그 앤 드롭을 더 빠르게 만들어줍니다.
  4. 메소드로부터 드래그 아이템을 반환합니다.

어떤 아이템이 드래그될지 결정하기 위해 제공된 인덱스 경로를 사용하시기 바랍니다. 아이템이 현재 선택된 아이템들 집합의 일부분이라면 컬렉션 뷰는 자동으로 선택된 아이템 모두를 드래그합니다. 아이템이 현재 선택의 부분이 아닌 경우 컬렉션 뷰는 이를 드래그 operation에 추가합니다.

드래그 시작에 대한 더 많은 정보는 UICollectionViewDragDelegate를 보시기 바랍니다.

UICollectionViewDragDelegate
https://developer.apple.com/documentation/uikit/uicollectionviewdragdelegate
https://velog.io/@panther222128/UICollectionViewDragDelegate

Receive Dropped Content

컨텐트가 bounds 내부로 드래그되면 컬렉션 뷰는 드래그된 데이터를 받을지 결정하기 위해 드롭 딜리게이트를 참고합니다. 초기에 컬렉션 뷰는 데이터 소스에서 특정 데이터를 통합시킬지 결정하기 위해 드롭 딜리게이트의 collectionView(_:canHandle:) 메소드만 호출합니다. 데이터를 통합할 수 있다면 컬렉션 뷰는 어느 곳에 데이터가 드롭될 수 있는지 결정하기 위해 다른 메소드를 호출하기 시작합니다.

사용자의 손가락이 움직일 때 컬렉션 뷰는 잠재적 드롭 위치를 추적하고, 각각의 변화에 대해 collectionView(_:dropSessionDidUpdate:withDestinationIndexPath:) 메소드를 호출해서 딜리게이트에게 알려줍니다. 이 메소드의 구현은 선택적이지만 권장되는 사항이며, 드래그되는 아이템이 어떻게 통합될 것인지에 대한 시각적 피드백을 표시할 수 있도록 해주기 때문입니다. 구현 내용 중 구체화된 인덱스 경로에서 드롭의 응답을 어떻게 할지에 대한 정보와 함께 UICollectionViewDropProposal 객체를 생성해야 합니다. 메소드가 자주 호출되기 때문에 가능한 빠르게 proposal을 반환해야 합니다. 이 메소드를 구현하지 않으면 컬렉션 뷰는 드롭을 어떻게 처리하는지에 대한 시각적 피드백을 제공하지 않습니다.

사용자가 스크린으로부터 손가락을 떼서 드롭을 수행하면 컬렉션 뷰는 드롭 딜리게이트의 collectionView(_:performDropWith:) 메소드를 호출합니다. 드롭된 데이터를 처리하려면 이 메소드를 구현해야 합니다. 구현에서 드래그된 데이터를 가져오고 컬렉션 뷰의 데이터 소스를 업데이트해야 하며, 컬렉션 뷰 자체에 필요한 아이템을 삽입해야 합니다. 아이템이 컬렉션 뷰 자체에서 기인한 것이라면, 기존 컬렉션 뷰 API를 사용해서 직접 아이템을 재정렬할 수 있습니다. 컬렉션 뷰 밖으로부터 온 컨텐트의 경우 데이터를 가져오고 삽입하려면 localObject 속성(앱 내부에서 기인한 컨텐트에 대한) 혹은 NSItemProvider 객체를 사용해야 합니다.

collectionView(_:performDropWith:) 메소드의 구현에서 아래처럼 해야 합니다.

  1. 제공된 드롭 조정자 객체에서 items 속성을 반복해야 합니다.
  2. 각 아이템에 대해 컨텐트를 어떻게 처리할지 결정해야 합니다.
    • 아이템의 sourceIndexPath가 값을 포함하는 경우 아이템은 컬렉션 뷰에서 기인한 것입니다. 아이템의 현재 위치를 삭제하기 위한 batch 업데이트를 사용하고 새 인덱스 경로에 삽입해야 합니다.
    • 드래그 아이템의 localObject 속성이 집합이면 아이템은 앱의 어떤 곳으로부터 기인한 것으로 아이템을 삽입하거나 기존 아이템을 업데이트해야 합니다.
    • 다른 옵션 사용이 불가능한 경우 데이터를 비동기로 가져오기 위해 드래그 아이템의 itemProvider 속성에서 NSItemProvider를 사용해야 하고, 아이템을 삽입하거나 업데이트해야 합니다.
  3. 데이터 소스를 업데이트하고 컬렉션 뷰에 필수적인 아이템을 삽입하거나 이동합니다.

앱에서 이미 로컬인 아이템의 경우 컬렉션 뷰의 데이터 소스와 인터페이스를 직접 업데이트할 수 있습니다. 예를 들어 삭제를 위해 batch 업데이트를 사용할 수 있고, 다음으로 컬렉션 뷰로부터 기인한 아이템을 삽입할 수 있습니다. 완료되면 드래그된 컨텐트를 컬렉션 뷰로 삽입하는 애니메이션 처리를 위해 드롭 조정자의 drop(_:toItemAt:) 메소들르 호출합니다.

NSItemProvider 객체를 사용해서 가져와야 하는 데이터의 경우 실제 데이터를 가져올 수 있을 때까지 컬렉션 뷰에 플레이스홀더를 삽입해야 합니다. 새 아이템이 컬렉션 뷰로 삽입할 때에만 플레이스홀더 삽입이 필수적입니다. 플레이스홀더는 실제 데이터가 사용 가능해질 때까지 표시하길 원하는 기본값 컨텐트를 나타내면서, 컬렉션 뷰에서 임시 아이템 역할을 합니다. 예를 들어 컨텐트가 현재 로딩 중임을 나타내는 텍스트 필드를 갖고 있는 플레이스홀더 셀을 제공할 수 있습니다.

컬렉션 뷰에 플레이스홀더를 삽입하려면 아래처럼 해야 합니다.

  1. 컬렉션 뷰에 플레이스홀더를 삽입하기 위해 제공된 UICollectionViewDropCoordinator 객체의 drop(_:to:) 메소드를 호출합니다.
  2. NSItemProvider 객체로부터 비동기로 데이터 로드를 시작합니다.

NSItemProvider 객체가 실제 데이터를 반환하면 삽입을 수행하고 플레이스홀더 셀과 최종 셀을 교환해야 합니다. 구체적으로 플레이스홀더 생성 후 받은 컨텍스트 객체의 commitInsertion(dataSourceUpdates:) 메소드를 호출합니다. 해당 메소드에 전달하는 블록에서 모델 객체와 컬렉션 뷰의 데이터 소스를 업데이트합니다. 이 메소드가 반환할 때 컬렉션 뷰는 자동으로 플레이스홀더를 삭제하고 최종 아이템을 삭제합니다. 이는 업데이트된 아이템이 새 아이템으로 반영되도록 합니다.

드롭 조정자의 destinationIndexPath 속성으로 구체화된 위치에 플레이스홀더를 삽입해야 합니다.

See Also


Drag and Drop

UICollectionViewDropPlaceholder

컬렉션 뷰에 드롭되는 아이템에 대한 플레이스홀더입니다.

https://developer.apple.com/documentation/uikit/uicollectionviewdropplaceholder
https://velog.io/@panther222128/UICollectionViewDropPlaceholder

UICollectionViewDropProposal

컬렉션 뷰에서 드롭 처리에 대한 제안된 해결책입니다.

https://developer.apple.com/documentation/uikit/uicollectionviewdropproposal
https://velog.io/@panther222128/UICollectionViewDropProposal

UICollectionViewPlaceholder

컬렉션 뷰에서 드래그 혹은 드롭되는 아이템에 대한 플레이스홀더입니다.

https://developer.apple.com/documentation/uikit/uicollectionviewplaceholder
https://velog.io/@panther222128/UICollectionViewPlaceholder


0개의 댓글