[사카마카] UINavigation에 대해 다르게 접근해보자.

2024. 5. 27. 22:33·사카마카 (살까말까 고민 될 때는 사카마카)
728x90

예전의 프로젝트에서는 ViewController의 UINavigationController나 navigationItem에 직접 접근하여 UINavigation을 사용하였다. 물론 이 방법이 정석이지만, 커스텀을 하다보면 버튼의 위치를 설정한다던지, 타이틀의 폰트를 변경한다던지 등 불편한 점이 많았다. 

 

Header View

직접 커스텀 View를 만들어서 사용하면 좋지 않을까? 하는 생각이 들었고, CollectionView의 Header & Footer가 생각이 났다. 

import UIKit

import RxCocoa
import RxSwift

import SnapKit
import Then

protocol FeedHeaderViewDelegate: AnyObject {
    func didAddVoteButtonTapped()
}

class FeedHeaderView: UIView {
    
    private let disposeBag = DisposeBag()
    weak var delegate: FeedHeaderViewDelegate?
    
    // MARK: - UI Components
    private let title = UILabel().then {
        let attributedString = NSMutableAttributedString(string: "사카", attributes: [.font: UIFont.h2, .foregroundColor: UIColor.Turquoise])
        attributedString.append(NSAttributedString(string: "마카", attributes: [.font: UIFont.h2_2, .foregroundColor: UIColor.black]))
        $0.attributedText = attributedString
    }
    
    private let addVoteButton = UIButton().then {
        $0.setImage(UIImage(systemName: "plus"), for: .normal)
        $0.tintColor = .nightGray
        $0.backgroundColor = .milkWhite
        $0.layer.cornerRadius = 5
    }
    
    // MARK: - Init
    override init(frame: CGRect) {
        super.init(frame: frame)
        setView()
        setConstraint()
        bind()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // MARK: - SetUp View
    private func setView() {
        backgroundColor = .clear
        
        [title, addVoteButton].forEach { addSubview($0) }
    }
    
    private func setConstraint() {
        title.snp.makeConstraints {
            $0.centerY.equalToSuperview()
            $0.leading.equalToSuperview().inset(20)
        }
        
        addVoteButton.snp.makeConstraints {
            $0.centerY.equalToSuperview()
            $0.width.height.equalTo(30)
            $0.trailing.equalToSuperview().inset(20)
        }
    }
    
    private func bind() {
        addVoteButton.rx.tap
            .subscribe(with: self, onNext: { owner, _ in
                owner.delegate?.didAddVoteButtonTapped()
            })
            .disposed(by: disposeBag)
    }
}

 

커스텀 View에 UI 요소와 제약조건을 설정하고, Button의 Tapped 이벤트를 delegate로 처리하도록 구현하였다.

 

import UIKit

import RxCocoa
import RxSwift

import SnapKit
import Then

class FeedViewController: BaseViewController {

    ... 
    
    // MARK: - UI Components
    private lazy var headerView = FeedHeaderView().then {
        $0.delegate = self
    }
    
    // MARK: - SetUp VC
    override func setViewController() {
        [headerView, feedCollectionView].forEach { view.addSubview($0) }
    }
    
    ... 
    
    override func setConstraints() {
        headerView.snp.makeConstraints {
            $0.top.equalTo(view.safeAreaLayoutGuide)
            $0.horizontalEdges.equalToSuperview()
            $0.height.equalTo(32)
        }
        
        feedCollectionView.snp.makeConstraints {
            $0.top.equalTo(headerView.snp.bottom).offset(20)
            $0.bottom.equalTo(view.safeAreaLayoutGuide).inset(20)
            $0.horizontalEdges.equalTo(view.safeAreaLayoutGuide).inset(20)
        }
    }
    
    ...
    
}

extension FeedViewController: FeedHeaderViewDelegate {
    func didAddVoteButtonTapped() {
        let vc = AddVoteViewController()
        self.navigationController?.pushViewController(vc, animated: true)
    }
}

해당 HeaderView를 사용하고자 하는 ViewController에서 headerView를 선언하고 추가해준다. 그리고 제약조건을 설정하고 HeaderView의 버튼 이벤트를 위임 받아서 구현해주면 된다. 

 

 

 

정상적으로 적용이 됐다 !

 

내 생각

1. 필요한 ViewController마다 일일이 구현해줘야 한다는 귀찮음이 있지만, 기존의 방법보다 직관적이고 관리하기가 쉽다는 장점이 더 큰 것 같다.

 

2. NavigationBar에 TextField를 넣는(검색 기능) 등 복잡하게 커스텀 할 때 사용하기 좋을 것 같다.

 

3. BackButton과 Title만 필요한 ViewController에서는 재사용 HeaderView를 만들어서 사용하면 더 좋을 것 같다.

'사카마카 (살까말까 고민 될 때는 사카마카)' 카테고리의 다른 글

[사카마카] 키보드 이벤트를 감지하여 화면의 레이아웃을 업데이트 해보자.  (0) 2024.06.01
[사카마카/문제해결] 앱 내에서 웹을 보여줄 때 발생하는 스킴 문제를 해결해보자.  (0) 2024.05.30
[사카마카] 앱 내에서 웹을 보여주는 방법에 대해 알아보자.  (0) 2024.05.30
[사카마카] Lottie로 애니메이션을 사용해보자.  (0) 2024.05.29
[사카마카/문제해결] CollectionViewCell의 버튼 이벤트 문제를 해결해보자.  (0) 2024.05.29
'사카마카 (살까말까 고민 될 때는 사카마카)' 카테고리의 다른 글
  • [사카마카/문제해결] 앱 내에서 웹을 보여줄 때 발생하는 스킴 문제를 해결해보자.
  • [사카마카] 앱 내에서 웹을 보여주는 방법에 대해 알아보자.
  • [사카마카] Lottie로 애니메이션을 사용해보자.
  • [사카마카/문제해결] CollectionViewCell의 버튼 이벤트 문제를 해결해보자.
여성일
여성일
  • 여성일
    성일노트
    여성일
  • 전체
    오늘
    어제
    • 분류 전체보기
      • Flyleaf - 독서를 여행처럼
        • 리팩토링
        • 트러블슈팅
        • 개발일지
      • 탭탭 - TapTap
        • 리팩토링
        • 트러블슈팅
        • 개발일지
      • 애플 디벨로퍼 아카데미
        • 챌린지 회고
        • 하루의 날씨
      • Swift Student Challenge 202..
      • AI를 잘쓰는 개발자가 될래요
      • 우리 같이 협업하자
      • 사카마카 (살까말까 고민 될 때는 사카마카)
      • Book2OnNon (모바일 서재)
      • 바꿔조 (환율 계산기)
      • iOS
        • iOS
        • Vapor
        • Design Pattern
        • CoreData
        • Tuist
        • RxSwift
        • ReactorKit
        • TCA
      • Swift
        • Swift 기본기
        • UIkit
        • SwiftUI
      • UX, 사용성
      • 원티드 프리온보딩 챌린지 iOS 과정
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.6
    여성일
    [사카마카] UINavigation에 대해 다르게 접근해보자.
    상단으로

    티스토리툴바