본문 바로가기

iOS/PROJECT

[두깃] 저장소 추가화면 (CollectionView list + Diffable DataSource) 기능구현

+ 4.22 추가

사랑스러운 우리 시오를 떠나보내고 잠시 쉬었다가 기능 구현을 하느라 시간이 조금 오래 걸렸다.

 

저장소 추가 화면의 필요한 기능

 

1. searchBar 검색 시 검색 결과 스냅샷 apply

2. 체크 버튼 클릭 시 저장소 추가 (realm에)

3. 체크 버튼 해제 시 저장소에 저장된 할 일이 삭제된다고 alert 창

 

1. SearchBar 검색 구현

snapshot을 업데이트하기 전에 searchBar의 text로 필터링하여 생성한 GithubRepository 배열을 snapshot에 적용하였다.

-> 정렬을 그냥 $0.name < $1.name 으로 하면 대문자가 소문자보다 앞에 정렬되기 때문에 모두 소문자로 바꿔주고 정렬하였다.

func performQuery(with filter: String?) {
    let filteredGithubRepositories = filteredGithubRepositories(with: filter).sorted { $0.name.lowercased() < $1.name.lowercased() }
    updateSnapshot(with: filteredGithubRepositories)
}

func filteredGithubRepositories(with filter: String? = nil) -> [GithubRepository] {
    return githubRepositories.filter { $0.contains(filter) }
}

contains 함수는 GithubRepository 구조체에 구현하였다.

func contains(_ filter: String?) -> Bool {
    guard let filterText = filter else { return true }
    if filterText.isEmpty { return true }
    let lowercasedFilter = filterText.lowercased()
    return name.lowercased().contains(lowercasedFilter)
}

 

생성한 performQuery 함수는 UISearchBarDelegate 를 채택하여 입력을 받을 때마다 실행해주었다.

 

생각했던 점

검색 후에 저장소를 체크하면 updateSnapshot() 함수를 불러왔는데 이렇게 되면 모든 저장소가 다시 불려 와 진다.

따라서 snapshot을 업데이트할 때 현재 서치바의 현재 text로 performQuery를 실행한 후에 스냅샷을 업데이트하는 것으로 바꾸었다.

 

 

 

2, 3. 체크 버튼 클릭시 Realm에 저장소 추가

class RepositoryCheckButton: UIButton {
    var repositoryID: GithubRepository.ID?
}

버튼을 repositoryID를 가지고 있는 버튼으로 생성했기 때문에 현재 저장소의 ID를 쉽게 알 수 있었다.

 

버튼 클릭 시

-> 현재 버튼이 체크되어 있다면

    -> alert 창 안내

        -> 삭제 : realm 객체 삭제, UI 업데이트

        -> 취소

-> 현재 버튼이 체크되어 있지 않다면

    -> 새로운 Realm 저장소 객체 생성, UI 업데이트

 

UI 업데이트하는 부분에서 애를 먹었다.

Repository 객체의 isCheck 변수를 true로 바꿔주고 스냅샷을 업데이트하면 cell registration 핸들러에서

isCheck 변수를 확인하고 UI를 업데이트할 줄 알았는데 isCheck 변수만 바뀌었는지 업데이트가 되지 않았다.

 

해결한 방법 

새롭게 dataSource를 만들어서 적용시켰다.

체크 버튼 색이 바뀌는 것이라 애니메이션 적용이 티가 나지 않았기 때문에 가능했던 방법이었다.

하지만 저장소를 추가, 삭제할 때마다 데이터 소스를 생성하기 때문에 결코 올바른 구현 방법일지는.. 모르겠다.

-> 이렇게 업데이트하면 애니메이션 적용이 되지 않는다.

메인화면에 똑같이 UI를 업데이트하다가 reloadItems, reconfigureItems 을 발견했다. 이것을 사용하면 된다! 한줄로 간단히!

자세한 설명은 다음글에..

 

func createDatasource() {
    // cell registration
    let cellRegistration = UICollectionView.CellRegistration(handler: cellRegistartionHandler)

    dataSource = DataSource(collectionView: collectionView, cellProvider: { collectionView, indexPath, itemIdentifier in
        return collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: itemIdentifier)
    })

    // update snapshot
    performQuery(with: searchBar.text)

    // dataSource 적용
    collectionView.dataSource = dataSource
}