iOS/Toy project

[iOS : Toy Project] Diffable DataSource, Compositional Layout을 이용해 프로젝트 개선하기

yevdev 2022. 6. 4. 14:07

기존 Apple Framework List

https://yexjinitlog.tistory.com/98?category=1022295 

 

[iOS : Toy Project] Apple Framework List (1)

📌 다섯번째 프로젝트 (1) Apple Framework List 앱을 만들어보자 1️⃣ Data 확인 및 FrameworkViewController 만들기 - 이전 프로젝트들과 마찬가지로 패캠에서 제공해준 데이터들을 사용 - "FrameworkViewContr..

yexjinitlog.tistory.com

 

 

📌 여덟번째 프로젝트 

Apple Framework List 앱을 Diffable DataSource 및 Compositional Layout을 이용한 코드로 전환해보자 !

 

1️⃣ 기존 UICollectionView의 Data, Presentation 이슈
UICollectionViewDataSource  UICollectionViewDiffableDataSource
2️⃣ 기존 UICollectionView의 Layout 이슈
UICollectionViewFlowLayout → UICollectionViewCompositionalLayout

 

 

 

//  FrameworkListViewController.swift

class FrameworkListViewController: UIViewController {
    // ...
    
    var dataSource: UICollectionViewDiffableDataSource<Section, AppleFramework>!
    // ...
}

이러면 AppleFramework 데이터가 Hashble 하지 않다는 오류가 생길 것이다.

 

→ Hashble 하게 바꾸기

//  FrameworkData.swift

struct AppleFramework: Hashable {
    let name: String
    let imageName: String
    let urlString: String
    let description: String
}

 

typealias를 사용하여 AppleFramework를 item으로 표현하기

var dataSource: UICollectionViewDiffableDataSource<Section, Item>!

typealias Item = AppleFramework

typealias : Redirecting 해주는 것

Item은 AppleFramework 타입을 지칭하고 있다.

 

 

 

Diffable Datasource, Compositional Layout 전환 코드

//  FrameworkListViewController.swift

import UIKit

class FrameworkListViewController: UIViewController {
    
    // CollectionView 자체를 연결
    @IBOutlet weak var collectionView: UICollectionView!
    
    // 데이터를 일단 가져오기
    let list: [AppleFramework] = AppleFramework.list
    
    var dataSource: UICollectionViewDiffableDataSource<Section, Item>!
    
    typealias Item = AppleFramework
    
    enum Section {
        case main
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        collectionView.delegate = self
        navigationController?.navigationBar.topItem?.title = "🎀 Apple Frameworks"
        
    // Data, Presentation, Layout
//      (1) presentation -> diffable datasource
        dataSource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView, cellProvider: { collectionView, indexPath, item in
            guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "FrameworkCell", for: indexPath) as? FrameworkCell else {
                 return nil
            }
            cell.configure(item)    // item이 AppleFramework와 같음
            return cell
        })
        
//      (2) data -> snapshot
        var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
        snapshot.appendSections([.main])
        snapshot.appendItems(list, toSection: .main)
        // dataSource에 Snapshot을 적용시키기
        dataSource.apply(snapshot)
        
//      (3) layout -> compositional layout
        collectionView.collectionViewLayout = layout()
    }
    
    private func layout() -> UICollectionViewCompositionalLayout {
        // item, group, section, layout 만들기
        let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.33), heightDimension: .fractionalHeight(1))    // item의 width는 group너비의 1/3, height는 group높이과 같음
        let item = NSCollectionLayoutItem(layoutSize: itemSize)
        
        let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .fractionalWidth(0.33))    // group의 width는 section너비, height는 section너비의 1/3
        let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: item, count: 3)  // item을 3등분으로 균일하게 쓰겠다!
        
        let section = NSCollectionLayoutSection(group: group)
        // section 좌우에 안쪽패딩주기
        section.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16)
        
        let layout = UICollectionViewCompositionalLayout(section: section)
        return layout
    }
    
    
}

// item이 선택되었을 때 효과 넣기
extension FrameworkListViewController: UICollectionViewDelegate{
    
    // item이 선택되었을 때 호출되는 method
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let framework = list[indexPath.item] // 몇번째 item인지?
        print(">>>> selected : \(framework.name)")
    }
}

 

 

구현 화면

 


📌 정리,

  • Presentation → Diffable DataSource
  • Data → Snapshot
  • Layout → Compositional Layout
  • typealias : 실제 타입을 참조, 대신해서 사용하는 것을 허용해주는 것

 

 


Reference

패스트캠퍼스 온라인 강의