[swift] IGListDiffKit을 이용한 상세 뷰 구현

IGListDiffKit은 iOS에서 사용할 수 있는 유명한 데이터 변화 추적 라이브러리입니다. 이 라이브러리를 활용하면 UITableView나 UICollectionView와 같은 리스트 뷰에서 데이터의 변경을 효율적으로 감지하고 업데이트할 수 있습니다. 이번 글에서는 IGListDiffKit을 이용하여 상세 뷰를 구현하는 방법에 대해 알아보겠습니다.

1. IGListDiffKit 설정하기

// IGListKit 라이브러리를 프로젝트에 추가합니다.
import IGListKit

2. IGListKit 상세 뷰모델 생성하기

IGListKit의 가장 핵심적인 부분은 뷰와 데이터를 연결하는 뷰모델입니다. 상세 뷰에 필요한 모든 데이터를 포함하는 뷰모델을 만들어야 합니다. 예를 들어, 사용자 프로필 정보를 보여주는 경우 프로필 이미지, 이름, 이메일 등을 뷰모델에 포함시켜야 합니다.

class ProfileViewModel: NSObject, ListDiffable {
    let name: String
    let profileImage: UIImage
    let email: String
    
    // 뷰모델 초기화 메서드
    init(name: String, profileImage: UIImage, email: String) {
        self.name = name
        self.profileImage = profileImage
        self.email = email
    }
    
    // IGListDiffable 프로토콜 구현
    func diffIdentifier() -> NSObjectProtocol {
        return name as NSObjectProtocol
    }
    
    func isEqual(toDiffableObject object: ListDiffable?) -> Bool {
        guard let object = object as? ProfileViewModel else { return false }
        return self.name == object.name && self.email == object.email
    }
}

3. IGListKit 상세 뷰 컨트롤러 구현하기

class ProfileViewController: UIViewController, ListAdapterDataSource {
    private var collectionView: UICollectionView!
    private var adapter: ListAdapter!
    private var viewModel: ProfileViewModel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // UICollectionView 초기화 및 설정
        let layout = UICollectionViewFlowLayout()
        self.collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: layout)
        self.view.addSubview(self.collectionView)
        
        // IGListKit adapter 초기화 및 설정
        self.adapter = ListAdapter(updater: ListAdapterUpdater(), viewController: self)
        self.adapter.collectionView = self.collectionView
        self.adapter.dataSource = self
        
        // 상세 뷰모델 설정
        self.viewModel = ProfileViewModel(name: "John Doe", profileImage: UIImage(named: "profile_image"), email: "johndoe@gmail.com")
        
        // 데이터 업데이트
        self.adapter.performUpdates(animated: true, completion: nil)
    }
    
    // MARK: - ListAdapterDataSource methods
    
    func objects(for listAdapter: ListAdapter) -> [ListDiffable] {
        return [self.viewModel]
    }
    
    func listAdapter(_ listAdapter: ListAdapter, sectionControllerFor object: Any) -> ListSectionController {
        return ProfileSectionController()
    }
    
    func emptyView(for listAdapter: ListAdapter) -> UIView? {
        return nil
    }
}

4. IGListKit 상세 뷰 섹션 컨트롤러 구현하기

class ProfileSectionController: ListSectionController {
    private var viewModel: ProfileViewModel!
    
    override func didUpdate(to object: Any) {
        self.viewModel = object as? ProfileViewModel
    }
    
    override func cellForItem(at index: Int) -> UICollectionViewCell {
        let cell = collectionContext?.dequeueReusableCell(of: ProfileCell.self, for: self, at: index) as! ProfileCell
        cell.configure(with: self.viewModel)
        return cell
    }
    
    override func sizeForItem(at index: Int) -> CGSize {
        return CGSize(width: collectionContext!.containerSize.width, height: 100)
    }
}

5. IGListKit 상세 뷰 셀 구현하기

class ProfileCell: UICollectionViewCell {
    private var profileImageView: UIImageView!
    private var nameLabel: UILabel!
    private var emailLabel: UILabel!
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        // 프로필 이미지 뷰 초기화 및 설정
        self.profileImageView = UIImageView(frame: CGRect(x: 10, y: 10, width: 80, height: 80))
        self.profileImageView.contentMode = .scaleAspectFill
        self.profileImageView.layer.cornerRadius = 40
        self.profileImageView.clipsToBounds = true
        self.addSubview(self.profileImageView)
        
        // 이름 라벨 초기화 및 설정
        self.nameLabel = UILabel(frame: CGRect(x: 100, y: 10, width: frame.width - 100, height: 20))
        self.nameLabel.font = UIFont.systemFont(ofSize: 18)
        self.addSubview(self.nameLabel)
        
        // 이메일 라벨 초기화 및 설정
        self.emailLabel = UILabel(frame: CGRect(x: 100, y: 40, width: frame.width - 100, height: 20))
        self.emailLabel.font = UIFont.systemFont(ofSize: 14)
        self.addSubview(self.emailLabel)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func configure(with viewModel: ProfileViewModel) {
        self.profileImageView.image = viewModel.profileImage
        self.nameLabel.text = viewModel.name
        self.emailLabel.text = viewModel.email
    }
}

위와 같이 IGListDiffKit을 활용하여 상세 뷰를 구현할 수 있습니다. IGListDiffKit은 데이터의 변경을 감지하고 효율적인 업데이트를 제공하기 때문에 많은 데이터를 다루는 화면에서 유용하게 사용될 수 있습니다. IGListDiffKit에 대한 더 자세한 정보는 공식 GitHub 페이지를 참조하시기 바랍니다.