[iOS] subway 주문 화면 만들기 [2]

Kiwi·2024년 4월 9일

iOS

목록 보기
5/15
post-thumbnail

스토리보드 하나를 가지고 협업하는 것은 무리였다... 그래서 우리 팀은 스토리보드 없이 코드로 UI를 구현하기로 결심했다. 그리고 UI 디자인 가이드를 피그마로 만들었다. 디자인가이드는 다음과 같다.

여기서 내가 맡은 부분은 상단부이고, 크기는 고정되어 있다. 내가 구현한 부분은 스토리보드로 구현했을 때와 코드가 거의 유사하고 특별히 추가되거나 하는 것은 없었지만 다른 팀원분의 코드와 결합하는 과정에서 고민할 부분이 많았다.

  • 코드로 autolayout 구현시 유의할점
  • 하나의 뷰에 여러 콜렉션뷰 넣기

✅ 코드로 autolayout 구현시 유의할 점

.translatesAutoresizingMaskIntoConstraints = false로 설정해야한다. 코드를 통해 뷰를 생성할 때는 이 속성이 기본적으로 true로 설정된다. 뷰가 자동으로 해당 부모의 뷰의 크기 및 위치에 맞게 조정되도록 해주는 것인데 이 속성이 true로 설정되어 있으면 autolayout의 제약조건이 적용되지 않는다. 그래서 이 속성을 꼭 false로 해줘야한다. 몇몇 뷰에 이 속성을 설정하지 않아 애를 많이 먹었다.

✅ 하나의 뷰에 여러 콜렉션뷰 넣기

subway화면의 중단부를 보면 여러개의 가로스크롤이 되는 콜렉션뷰가 사용된다. 가로스크롤을 위해 collectionViewFlowlayout을 설정해준다.

let topCollectionViewFlowLayout: UICollectionViewFlowLayout = {
        let flowlayout = UICollectionViewFlowLayout()
        flowlayout.scrollDirection = .horizontal
        flowlayout.minimumLineSpacing = 15
        flowlayout.sectionInset = UIEdgeInsets(top:0, left:0, bottom: 0, right: 0)
        return flowlayout
    }()

lazy var tabbarTop: UICollectionView = {
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: topCollectionViewFlowLayout)
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        return collectionView
    }()

이게 내가 맡은 부분인 topView에 해당하는 부분이라면 팀원분의 코드를 합치는 과정에서 문제가 생겼다. 추가된 팀원 코드는 다음과 같았다.

// middle view
    let collectionViewFlowLayout: UICollectionViewFlowLayout = {
        let flowlayout = UICollectionViewFlowLayout()
        flowlayout.scrollDirection = .horizontal
        flowlayout.minimumLineSpacing = 15
        flowlayout.sectionInset = UIEdgeInsets(top:0, left:0, bottom: 0, right: 0)
        return flowlayout
    }()
    
    lazy var breadHorizontalBar: UICollectionView = {
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: collectionViewFlowLayout)
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        return collectionView
    }()

여기서 확인해보면 collectionViewFlowLayout이 중복되어있는것을 확인할 수 있다. 그래서 중복된 코드를 줄이고자 하나의 collectionViewFlowLayout을 사용해서 모든 콜렉션뷰가 채택할 수 있도록 하게 했다.

	let collectionViewFlowLayout: UICollectionViewFlowLayout = {
        let flowlayout = UICollectionViewFlowLayout()
        flowlayout.scrollDirection = .horizontal
        flowlayout.minimumLineSpacing = 15
        flowlayout.sectionInset = UIEdgeInsets(top:0, left:0, bottom: 0, right: 0)
        return flowlayout
    }()
    
    lazy var breadHorizontalBar: UICollectionView = {
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: collectionViewFlowLayout)
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        return collectionView
    }()
    
    lazy var tabbarTop: UICollectionView = {
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: collectionViewFlowLayout)
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        return collectionView
    }()

같은 flowLayout을 채택한 후 dataSource와 delegate 프로토콜의 메서드를 구현할 때도 다음과 같이 했다.

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        if collectionView == tabbarTop {
            return menuList.count
        } else if collectionView == breadHorizontalBar {
            return breadList.count
        } ...
        
    }

if문으로 받는 collectionView를 구분해서 무사히 구현할 수 있었지만 문제가 발생했다. func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize 메서드르르 구현할 때 위와 같이 if문으로 collectionView만을 분리하니까 분리가 되지 않았다.


func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        if collectionView == tabbarTop {
            let text = menuList[indexPath.row]
            let font = UIFont.systemFont(ofSize: 20)
            let textWidth = text.size(withAttributes: [NSAttributedString.Key.font: font]).width
            let cellWidth = textWidth + 20
            return CGSize(width: cellWidth, height: 60)
        } else {
            let text = breadList[indexPath.row]
            let font = UIFont.systemFont(ofSize: 18)
            let textWidth = text.size(withAttributes: [NSAttributedString.Key.font: font]).width
            let cellWidth = textWidth + 10
            return CGSize(width: cellWidth, height: 20)
        }

위의 코드를 실행하면 if 문을 인식하지 못하고 무조건 else 문으로 빠져버린다. 글래서 tabbarTop이 다음과 같이 나온다.ㅠㅠ

profile
🐣 iOS Developer

3개의 댓글

comment-user-thumbnail
2024년 4월 11일

오 이 멋있던 섭웨이 앱을 지연님께서 참여하셨군요!! ㅎㅎㅎ 멋있습니다!! 오늘도 고생하셨습니다~!

답글 달기
comment-user-thumbnail
2024년 4월 11일

Ace 다운 코딩 실력이십니다 ~! 수고하셨어요

답글 달기
comment-user-thumbnail
2024년 4월 12일

오옹 스토리보드를 코드로 구현하셨군요 !
구현하신 코드를 잘 정리하셨네요.. 짱입니다 ! 오늘도 화이팅 ㅎㅎ!

답글 달기