[TIL] 11.02

Junyoung_Hong·2023년 11월 6일
0

TIL_11월

목록 보기
2/5
post-thumbnail

1. 딕셔너리 값 삭제 후, 재정렬

데이터와 관련해서 코드를 짤 때, 배열과 함께 딕셔너리도 많이 사용한다. 현재 진행하고 있는 프로젝트에서도 딕셔너리를 사용해서 이미지를 저장하고 불러오는 작업을 진행하고 있었다.

var selectedImage: [String: UIImage] = [:]

이렇게 딕셔너리 타입의 변수를 선언했다. 그 다음,

// 딕셔너리에 추가하는 코드 작성
let index = firebaseManager.selectedImage.count
firebaseManager.selectedImage[String(index)] = image
// 업데이트된 이미지 배열로 컬렉션 뷰를 새로고침
createNoticeBoardView.galleryCollectionView.reloadData()

갤러리에서 선택한 사진을, index 값을 추가시키면서 해당 딕셔너리에 추가하는 방법으로 진행을 했었다. 그런데 문제가 발생했었다.

1-1. 문제점

사진을 여러개 추가한 후, 중간의 사진을 삭제하면, 뒤에 있는 사진들이 cell에 보이지 않음

1-2. 문제점 예상 및 파악

예를 들어 사진을 3개를 추가한 상태라고 해보자. 그렇다면 "0": asdf, "1": qwer, "2": zxcv 이런 식으로 딕셔너리에 저장이 되어 있을 것이다. 그런데 중간 사진인 "1": qwer을 삭제하게 되면 "0": asdf, "2": zxcv 만 남게 되고, cell은 index가 0, 1이 된다. 즉, 딕셔너리와 cell의 순서가 맞지 않게 되는 것이다.

1-3. 해결방법

그렇다면 사진이 삭제되고 난 후에, 딕셔너리를 다시 재정렬 시키면 될것이다.

1단계

사진을 삭제하면, CollectionView를 업데이트하고, cell이 삭제되는 모습을 사용자에게 자연스럽게 보여주고, 효율적으로 업데이트 하기 위해 performBatchUpdates(_:completion:) 를 사용하자.

performBatchUpdates(_:completion:)의 사용방법은 다음과 같다.

collectionView.performBatchUpdates({
    // 이 블록 내에서 컬렉션 뷰의 변경 사항을 배치
    // 예를 들어, 아이템 추가, 삭제, 섹션의 삽입, 삭제 등을 실행
    collectionView.insertItems(at: [IndexPath])
    collectionView.deleteItems(at: [IndexPath])
    collectionView.reloadItems(at: [IndexPath])
    // 등등...
}, completion: { finished in
    // 변경 사항을 적용한 후에 실행할 작업을 여기에 작성
    // 'finished' 파라미터는 애니메이션이 완료되었는지 여부를 나타냄
    if finished {
        // 애니메이션이 완료된 후 실행할 코드
    }
})

프로젝트에 적용하면 다음과 같다.

self.createNoticeBoardView.galleryCollectionView.performBatchUpdates {

} completion: { _ in

}

2단계

이제 컬렉션 뷰의 변경 사항을 배치하자. 선택된 index에 해당하는 이미지를 딕셔너리에서 삭제하고, 해당 아이템을 CollectionView에서 삭제한다.

self.createNoticeBoardView.galleryCollectionView.performBatchUpdates {
    
    // 선택된 인덱스에 해당하는 이미지를 딕셔너리에서 삭제
    self.firebaseManager.selectedImage[String(indexPath.row)] = nil
    
    // 해당하는 아이템을 CollectionView에서 삭제
    self.createNoticeBoardView.galleryCollectionView.deleteItems(at: [indexPath])
} completion: { _ in

}

3단계

이제 딕셔너리의 키를 재정렬 해주자.

// 딕셔너리의 키를 재정렬
var newSelectedImage: [String: UIImage] = [:]
let sortedKeys = self.firebaseManager.selectedImage.keys.compactMap { Int($0) }.sorted()

// 재정렬할 때 사용할 새 인덱스
var newIndex = 0

for key in sortedKeys {
    if let image = self.firebaseManager.selectedImage[String(key)] {
        newSelectedImage[String(newIndex)] = image
        newIndex += 1
    }
}

우선 재정렬하기 위한 새로운 딕셔너리를 만든다. 그 다음 기존 딕셔너리의 키를 가져와서 compactMap을 사용하여 각 키를 Int로 변환하고, 변환에 성공한 키만 sorted()를 통해 오름차순으로 정렬한다.

재정렬을 위한 새로운 인덱스도 만들어준다. 정렬된 키 sortedKeys를 순회하면서 각 키에 해당하는 이미지를 원본 딕셔너리 self.firebaseManager.selectedImage에서 찾아 새로운 딕셔너리 newSelectedImage로 옮긴다. 여기서는 원본 딕셔너리의 키(String(key))를 사용하여 값을 가져온다.

그 다음 옵셔널 바인딩을 사용하여 self.firebaseManager.selectedImage[String(key)]에서 UIImage를 성공적으로 얻어내면 그 이미지를 newSelectedImageString(newIndex)를 키로 사용하여 삽입합니다.

마지막으로 새로운 딕셔너리에 항목을 추가할 때마다 newIndex를 1씩 증가시켜, 새로운 키가 연속적이고 오름차순이 되도록 한다.

1-4. 전체 코드

func removeLocal(_ indexPath: IndexPath) {
        // 로컬에서 이미지를 삭제하고 Collection View를 업데이트
        self.createNoticeBoardView.galleryCollectionView.performBatchUpdates {
            
            // 선택된 인덱스에 해당하는 이미지를 딕셔너리에서 삭제
            self.firebaseManager.selectedImage[String(indexPath.row)] = nil
            
            // 해당하는 아이템을 CollectionView에서 삭제
            self.createNoticeBoardView.galleryCollectionView.deleteItems(at: [indexPath])
        } completion: { _ in
            
            // 딕셔너리의 키를 재정렬
            var newSelectedImage: [String: UIImage] = [:]
            let sortedKeys = self.firebaseManager.selectedImage.keys.compactMap { Int($0) }.sorted()
            
            // 재정렬할 때 사용할 새 인덱스
            var newIndex = 0
            
            for key in sortedKeys {
                if let image = self.firebaseManager.selectedImage[String(key)] {
                    newSelectedImage[String(newIndex)] = image
                    newIndex += 1
                }
            }
            
            // 재정렬된 이미지 딕셔너리를 업데이트
            self.firebaseManager.selectedImage = newSelectedImage
            
            // self.createNoticeBoardView.galleryCollectionView.reloadData()
        }
    }
profile
iOS 개발자를 향해 성장 중

0개의 댓글