Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

날씨 앱 [STEP3-1] 요한 #53

Open
wants to merge 2 commits into
base: 2_Yohan
Choose a base branch
from

Conversation

dpwns1234
Copy link

@dpwns1234 dpwns1234 commented Dec 22, 2023

날씨 앱 [STEP3-1] 요한

리뷰어: @corykim0829

안녕하세요 코리! 요한입니다.
STEP3-1 PR 보냅니다. 잘 부탁립니다!!

구현내용

구현 사항

  • Compositional Layout 활용
  • FileManager와 NSCache를 사용해 이미지 캐싱

Compositional Layout 적용 코드

// WeatherViewController.swift
final class WeatherViewController {
    private var dataSource: WeatherDataSource? = nil
    
    ...
    
    // 받아온 데이터대로 snapshot, update
    func updateForecastWeatherView(_ manager: WeatherDataManager, with forecast: WeatherForecast) {
        var snapshot = NSDiffableDataSourceSnapshot<Section, WeatherForecast.WeatherList>()
        snapshot.appendSections([.main])
        snapshot.appendItems(forecast.list)
        self.dataSource?.apply(snapshot)

        updateView()
    }
    
    ...
    
    // dataSource의 데이터가 변경되면 update view
    private func configureDataSource() {
        let cellRegistration = UICollectionView.CellRegistration<WeatherCollectionViewCell, WeatherForecast.WeatherList> { (cell, indexPath, item) in
            self.bind(on: cell, indexPath: indexPath)
        }
        
        let headerRegistration = UICollectionView.SupplementaryRegistration
        <WeatherCollectionHeaderView>(elementKind: UICollectionView.elementKindSectionHeader) { (headerView, string, indexPath) in
            self.bind(on: headerView)
        }
        
        dataSource = WeatherDataSource(collectionView: collectionView) {
            (collectionView: UICollectionView, indexPath: IndexPath, identifier: WeatherForecast.WeatherList) -> UICollectionViewCell? in
            return collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: identifier)
        }
        
        dataSource?.supplementaryViewProvider = { (view, kind, index) in
            return self.collectionView.dequeueConfiguredReusableSupplementary(using: headerRegistration, for: index)
        }
    }
}

FileManager와 NSCache를 사용해 이미지 캐싱

// IconDataService.swift
final class IconDataService: DataServiceable {
    
    func downloadData(type service: ServiceType) throws {
        guard let url = service.makeURL() else { throw NetworkError.invailedURL }
        networkManager.downloadData(url: url) { result in
            switch result {
            case .success(let data):
                guard let image = UIImage(data: data) else {
                    print("이미지 변환에 실패했습니다.")
                    return
                }
                // 앱이 시작할 때 미리 image를 FileManager에 저장한다.
                ImageFileManager.saveImage(image: image, forKey: service.code)
            case .failure(let error):
                print(error)
            }
        }
    }
}

// WeatherViewController.swfit 
final class WeatherViewController {
    private func bindImage(imageView: UIImageView, code: String) {
            // 1. 먼저 Cache에 이미지가 있는지 확인
            if let image = ImageCacheManager.getCache(forKey: code) {
                imageView.image = image
            // 2. 없다면, FileManager에 있는지 확인
            } else {
                guard let image = ImageFileManager.getImage(forKey: code) else {
                    print("fileManager에 해당 image 없음")
                    return
                }
            // 3. Cache에 저장을 해 다음에 접근한다면 더 빠르게 접근할 수 있도록 해준다.
                ImageCacheManager.setCache(image: image, forKey: code)
                imageView.image = image
            }
        }

구현해보니, 날씨 이미지 아이콘은 개수도 많으며 변동되는 값이기 때문에 저장공간 이슈로 FileManager를 사용하는 것은 좋은 선택이 아니라고 생각하였습니다.

궁금한 점

FileManager를 통해 이미지를 저장할 경우 경우에 어플이 많은 용량을 차지하게 될 것 같습니다. 경우에 따라 다르지만 보통 FileManager는 이미지를 저장하는 것에 적합하지 않은 것인지 궁금합니다.

Copy link

@corykim0829 corykim0829 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수고많으셨습니다!

UICollectionView Compositional Layout과 DiffableDatasource를 잘 사용하셨네요!
이번 PR이 저번과 조금 꼬인 것 같아서 해당 라인에 제가 리뷰를 달 수 없어서 여기에 인용해서 리뷰를 달도록 하겠습니다!

아래 부분에서는 Identifier로 잘 사용하셨는데, enum 이름을 조금 더 구체하게 하면 더 좋을 것 같습니다! 다른 UICollectionView와 사용될 수도 있는 확장성까지 고려해서요!

extension WeatherViewController {
    enum Section {
        case main
    }
}

updateView 함수의 이름이 조금 어색하게 느껴집니다. snapShot이 적용될 때마다 updateView를 호출하면 실제 cell에 관련된 뷰가 업데이트 될 것 같은데, 해당 부분은 refreshControl를 업데이트 하고 있어서 함수명을 그와 관련되게 바꾸면 좋을 것 같습니다.

private func updateView() {
        DispatchQueue.main.async { [self] in
            collectionView.refreshControl?.endRefreshing()
        }
    }

이전에도 한번 언급했었는데, 현재 ViewController에 있는 bind 함수를 각 커스텀 클래스가 가져가면 코드가 더 깔끔해지고 가독성이 높아질 것 같아요!

또한 Image chaching 부분에서 ios16버전 이상에서만 사용되도록 분기 처리된 부분은 ios 16이하 버전도 시간이 되면 구현해보면 좋을 것 같습니다!

FileManager로 캐싱을 구현하면, 파일이 크면 앱에 부담이 가는건 맞습니다. 따라서 이미지 파일의 크기를 줄이거나, 디스크 캐싱 시 보관 기한을 적절히 설정해서 하면 좋을 것 같습니다!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants