티스토리 뷰

iOS

iOS) UICollectionView Programmatically

Ekko0701 2022. 10. 10. 18:13

UICollectionView를 Programmatically 하게 사용하는 방법이다.

 

원래 cellForItemAt에서 cell의 요소에 접근하는 방식을 cell.titleLabel.text = "" 이런 식으로 사용했는데

이번엔 다른 방법으로 접근해보고자 한다.

 

먼저 Collection View Cell은 다음과 같이 만들었다.

MyCollectionViewCell.swift

//
//  MyCollectionViewCell.swift
//

import Foundation
import UIKit

class MyCollectionViewCell: UICollectionViewCell {
    static let identifier = "MyCollectionViewCell"
    
    private let label: UILabel = {
        let label = UILabel()
        label.textColor = .white
        label.textAlignment = .center
        label.font = .systemFont(ofSize: 25, weight: .semibold)
        return label
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        //  Congifure Label
        contentView.addSubview(label)
        contentView.layer.cornerRadius = 6
        contentView.layer.borderWidth = 1.5
        contentView.layer.borderColor = UIColor.quaternaryLabel.cgColor
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        label.frame = contentView.bounds    // label의 프레임을 cell의 바운드와 같게 조정
    }
}

 

다음으로 ViewController에 CollectionView를 추가해주자.

ViewController.swift

//
//  ViewController.swift

import UIKit
import SnapKit

class ViewController: UIViewController {

    let cellMultiplier: CGFloat = 0.5
    
    //  Create UICollectionView
    private let collectionView: UICollectionView = {
        //  Configure Layout
        var layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal
        
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        collectionView.backgroundColor = .black
        return collectionView
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        configureLayout()
        configureCollectionView()
    }

    //  SetUp AutoLayout with SnapKit
    func configureLayout() {
    	// Add SubView
        view.addSubview(collectionView)
    
        collectionView.snp.makeConstraints { make in
            make.width.equalToSuperview()
            make.height.equalTo((view.frame.size.height / 5 ) * 3)
            make.top.leading.equalTo(view.safeAreaLayoutGuide)
        }
    }
    
    func configureCollectionView() {
        // Attach CollectionView Delegate & DataSource
        collectionView.delegate = self
        collectionView.dataSource = self
        
        // Regist Cell
        collectionView.register(MyCollectionViewCell.self, forCellWithReuseIdentifier: MyCollectionViewCell.identifier)
    }
}

extension ViewController: UICollectionViewDelegate {
    
}

extension ViewController: UICollectionViewDataSource {
    
    /// Number of Section
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    
    /// Non-Optional
    /// NumberOfItemsInSection
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        <#code#>
    }
    
    /// Non-Optional
    /// CellForItemAt
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        <#code#>
    }
}

extension ViewController: UICollectionViewDelegateFlowLayout {
    
    /// Cell Size
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        
        let width: CGFloat = view.frame.size.width * cellMultiplier
        let height: CGFloat = view.frame.size.height * cellMultiplier
        
        let size: CGSize = CGSize(width: width, height: height)
        
        return size
    }
}

 

UICollectionViewDataSource의 numberOfItemsInSection과 cellForItemAt은 이제부터 채워보자.

 

그전에 cell에 들어갈 Data Model부터 생성

//
//  CollectionViewCellViewModel.swift

import Foundation
import UIKit

struct CollectionViewCellViewModel {
    let name: String
    let backgroundColor: UIColor
}

 

그리고 위에서 만들었던 MyCollectionViewCell.swift에 다음과 같은 코드를 추가한다.

func configure(with viewModel: CollectionViewCellViewModel) {
    contentView.backgroundColor = viewModel.backgroundColor
    label.text = viewModel.name
}

이를 통해 CollectionViewCellViewModel의 name과 backgroundColor를 Cell에 적용해준다.

 

다시 ViewController.swift로 이동해 CollectionViewCellViewModel 배열을 만들어 주자.

private var viewModels: [CollectionViewCellViewModel] = [
    CollectionViewCellViewModel(name: "Red", backgroundColor: .systemRed),
    CollectionViewCellViewModel(name: "Orange", backgroundColor: .systemOrange),
    CollectionViewCellViewModel(name: "Yellow", backgroundColor: .systemYellow),
    CollectionViewCellViewModel(name: "Green", backgroundColor: .systemGreen),
    CollectionViewCellViewModel(name: "Blue", backgroundColor: .systemBlue),
    CollectionViewCellViewModel(name: "Purple", backgroundColor: .systemPurple),
]

 

데이터까지 만들었으니 DataSource의 메서드를 마저 채워주자.

/// Non-Optional
/// NumberOfItemsInSection
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    viewModels.count
}

/// Non-Optional
/// CellForItemAt
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    guard let cell = collectionView.dequeueReusableCell(
        withReuseIdentifier: MyCollectionViewCell.identifier,
        for: indexPath
    ) as? MyCollectionViewCell else {
        fatalError()
    }
    
    cell.configure(with: viewModels[indexPath.row])
    
    return cell
}

 

cellForItemRowAt의 cell.configure(with: viewModels [indexPath.row])를 통해 cell을 업데이트해 준다.

 

끝~!

 

전체코드

더보기

ViewController.swift

//
//  ViewController.swift

import UIKit
import SnapKit

class ViewController: UIViewController {

    private var viewModels: [CollectionViewCellViewModel] = [
        CollectionViewCellViewModel(name: "Red", backgroundColor: .systemRed),
        CollectionViewCellViewModel(name: "Orange", backgroundColor: .systemOrange),
        CollectionViewCellViewModel(name: "Yellow", backgroundColor: .systemYellow),
        CollectionViewCellViewModel(name: "Green", backgroundColor: .systemGreen),
        CollectionViewCellViewModel(name: "Blue", backgroundColor: .systemBlue),
        CollectionViewCellViewModel(name: "Purple", backgroundColor: .systemPurple),
    ]
    
    let cellMultiplier: CGFloat = 0.5
    
    //  Create UICollectionView
    private let collectionView: UICollectionView = {
        //  Configure Layout
        var layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal
        
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        collectionView.backgroundColor = .black
        return collectionView
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        configureLayout()
        configureCollectionView()
    }

    //  SetUp AutoLayout with SnapKit
    func configureLayout() {
        view.addSubview(collectionView)
        
        collectionView.snp.makeConstraints { make in
            make.width.equalToSuperview()
            make.height.equalTo((view.frame.size.height / 5 ) * 3)
            make.top.leading.equalTo(view.safeAreaLayoutGuide)
        }
    }
    
    func configureCollectionView() {
        // Attach CollectionView Delegate & DataSource
        collectionView.delegate = self
        collectionView.dataSource = self
        
        // Regist Cell
        collectionView.register(MyCollectionViewCell.self, forCellWithReuseIdentifier: MyCollectionViewCell.identifier)
    }
}

extension ViewController: UICollectionViewDelegate {
    
}

extension ViewController: UICollectionViewDataSource {
    
    /// Number of Section
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    
    /// Non-Optional
    /// NumberOfItemsInSection
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        viewModels.count
    }
    
    /// Non-Optional
    /// CellForItemAt
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = collectionView.dequeueReusableCell(
            withReuseIdentifier: MyCollectionViewCell.identifier,
            for: indexPath
        ) as? MyCollectionViewCell else {
            fatalError()
        }
        
        cell.configure(with: viewModels[indexPath.row])
        
        return cell
    }
}

extension ViewController: UICollectionViewDelegateFlowLayout {
    
    /// Cell Size
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        
        let width: CGFloat = view.frame.size.width * cellMultiplier
        let height: CGFloat = view.frame.size.height * cellMultiplier
        
        let size: CGSize = CGSize(width: width, height: height)
        
        return size
    }
}

 

MyCollectionViewCell.swift

//
//  MyCollectionViewCell.swift
//

import Foundation
import UIKit



class MyCollectionViewCell: UICollectionViewCell {
    static let identifier = "MyCollectionViewCell"
    
    private let label: UILabel = {
        let label = UILabel()
        label.textColor = .white
        label.textAlignment = .center
        label.font = .systemFont(ofSize: 25, weight: .semibold)
        return label
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        //  Congifure Label
        contentView.addSubview(label)
        contentView.layer.cornerRadius = 6
        contentView.layer.borderWidth = 1.5
        contentView.layer.borderColor = UIColor.quaternaryLabel.cgColor
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        label.frame = contentView.bounds    // label의 프레임을 cell의 바운드와 같게 조정
    }
    
    func configure(with viewModel: CollectionViewCellViewModel) {
        contentView.backgroundColor = viewModel.backgroundColor
        label.text = viewModel.name
    }
}

 


Auto Carousel Effect를 구현하다가 빠르게 써보았다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함