1️⃣ Navigation, TabBar Embeded!
- UINavigationContoller : Cocoa Touch 파일 → UINavigationController
- UITabBarController : Cocoa Touch 파일 → UITabBarController
2️⃣ Navigation을 TabBar 안에 속하게!
- Navigation View를 initial로
- TabBar안에 여러개의 view 연결
TabBar에 따라 " Navigation Bar Custom " 하기
import UIKit
class MainTabBarViewController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
// 네비게이션 좌측
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "헬로", style: .plain, target: nil, action: nil)
// 네비게이션 우측
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .bookmarks, target: nil, action: nil)
}
}
Delegate
- 언제 무엇이 탭되었는지 알 수 있음
1️⃣ 탭이 눌릴때마다 네비게이션 바 아이콘 바꾸기
// MainTabBarViewController.swift
import UIKit
// 탭이 눌릴때마다, 그에 맞는 네비게이션 바를 구성
// - 탭이 눌리는 것을 감지
// - 감지 후에, 그 탭에 맞게 네비게이션 바 구성을 업데이트
class MainTabBarViewController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
// 네비게이션 좌측
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "헬로", style: .plain, target: nil, action: nil)
// 네비게이션 우측
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .bookmarks, target: nil, action: nil)
// 탭이 눌리는 것을 감지
delegate = self
}
}
// 어떤 Controller가 탭 되었는지 알 수 있음
extension MainTabBarViewController: UITabBarControllerDelegate {
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
print("--> 어떤 \(viewController)")
switch viewController {
case is HomeViewController:
let titleItem = UIBarButtonItem(title: "헬로", style: .plain, target: nil, action: nil)
let feedItem = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: nil)
navigationItem.leftBarButtonItem = titleItem
navigationItem.rightBarButtonItem = feedItem
case is MyTownViewController:
let titleItem = UIBarButtonItem(title: "공릉동", style: .plain, target: nil, action: nil)
let feedItem = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: nil)
navigationItem.leftBarButtonItem = titleItem
navigationItem.rightBarButtonItem = feedItem
case is ChatViewController:
let titleItem = UIBarButtonItem(title: "채팅", style: .plain, target: nil, action: nil)
let feedItem = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: nil)
navigationItem.leftBarButtonItem = titleItem
navigationItem.rightBarButtonItem = feedItem
case is MyProfileViewController:
let titleItem = UIBarButtonItem(title: "나의 당근", style: .plain, target: nil, action: nil)
let feedItem = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: nil)
navigationItem.leftBarButtonItem = titleItem
navigationItem.rightBarButtonItem = feedItem
default:
let titleItem = UIBarButtonItem(title: "당근당근", style: .plain, target: nil, action: nil)
let feedItem = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: nil)
navigationItem.leftBarButtonItem = titleItem
navigationItem.rightBarButtonItem = feedItem
}
}
}
2️⃣ UIBarButtonItem을 CustomView로 만들기 ( 원하는 폰트, 이미지, 액션 세팅 )
1. 원하는 폰트
// CustomBarItem.swift
// -> CustomView
import Foundation
import UIKit
struct CustomBarItemConfiguration {
// 표현이 복잡하거나 한눈에 보기 어려울 때 typealias 사용
// closer 타입을 "Handler" 라는 이름의 타입으로 재설정
typealias Handler = () -> Void
let title: String?
let image: UIImage?
let handler: Handler
init(title: String? = nil, image: UIImage? = nil, handler: @escaping Handler) {
self.title = title
self.image = image
self.handler = handler
}
}
// CustomBarButton을 위한 UIButton을 상속한 CustomBarItem
final class CustomBarItem: UIButton {
// title, image, target action 필요
var customBarItemConfig: CustomBarItemConfiguration
init(config: CustomBarItemConfiguration) {
self.customBarItemConfig = config
super.init(frame: .zero)
setupStyle()
updateConfig()
}
private func setupStyle() {
self.titleLabel?.font = .systemFont(ofSize: 20, weight: .bold)
self.titleLabel?.textColor = .white
self.imageView?.tintColor = .white
}
private func updateConfig() {
self.setTitle(customBarItemConfig.title, for: .normal)
self.setImage(customBarItemConfig.image, for: .normal)
}
@objc func buttonTapped() {
customBarItemConfig.handler()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
2. 원하는 이미지
//
// MainTabBarViewController.swift
import UIKit
// 탭이 눌릴때마다, 그에 맞는 네비게이션 바를 구성
// - 탭이 눌리는 것을 감지
// - 감지 후에, 그 탭에 맞게 네비게이션 바 구성을 업데이트
class MainTabBarViewController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
// 네비게이션 좌측
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "헬로", style: .plain, target: nil, action: nil)
// 네비게이션 우측
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .bookmarks, target: nil, action: nil)
// UIBarButtonItem을 CustomView로 만들기
// - 사용자 클릭(interaction이 가능하게)
// 탭이 눌리는 것을 감지
delegate = self
}
}
// 각 탭에 맞게 네비게이션 아이템 구성하기
// - 홈: 타이틀, 피드, 서치
// - 동네활동: 타이틀, 피드
// - 내 근처 : 타이틀
// - 채팅: 타이틀, 피드
// - 나의 당근: 타이틀, 설정
// 어떤 Controller가 탭 되었는지 알 수 있음
extension MainTabBarViewController: UITabBarControllerDelegate {
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
print("--> 어떤 \(viewController)")
switch viewController {
case is HomeViewController:
let titleConfig = CustomBarItemConfiguration(title: "공릉동", handler: { })
let customTitleView = CustomBarItem(config: titleConfig)
let titleItem = UIBarButtonItem(customView: customTitleView)
let searchConfig = CustomBarItemConfiguration( image:UIImage(systemName: "magnifyingglass"), handler: {print("--> search tapped")})
let searchView = CustomBarItem(config: searchConfig)
let searchItem = UIBarButtonItem(customView: searchView)
let feedConfig = CustomBarItemConfiguration( image:UIImage(systemName: "bell"), handler: {print("--> feed tapped")})
let feedView = CustomBarItem(config: feedConfig)
let feedItem = UIBarButtonItem(customView: feedView)
navigationItem.leftBarButtonItem = titleItem
// 아이템 여러개 설정할 때는 Items로 하고 배열로 넣어주기
navigationItem.rightBarButtonItems = [feedItem, searchItem]
case is MyTownViewController:
let titleItem = UIBarButtonItem(title: "공릉동", style: .plain, target: nil, action: nil)
let feedItem = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: nil)
navigationItem.leftBarButtonItem = titleItem
navigationItem.rightBarButtonItem = feedItem
case is ChatViewController:
let titleItem = UIBarButtonItem(title: "채팅", style: .plain, target: nil, action: nil)
let feedItem = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: nil)
navigationItem.leftBarButtonItem = titleItem
navigationItem.rightBarButtonItem = feedItem
case is MyProfileViewController:
let titleItem = UIBarButtonItem(title: "나의 당근", style: .plain, target: nil, action: nil)
let feedItem = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: nil)
navigationItem.leftBarButtonItem = titleItem
navigationItem.rightBarButtonItem = feedItem
default:
let titleItem = UIBarButtonItem(title: "당근당근", style: .plain, target: nil, action: nil)
let feedItem = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: nil)
navigationItem.leftBarButtonItem = titleItem
navigationItem.rightBarButtonItem = feedItem
}
}
}
3. 돋보기랑 아이콘 사이 간격 벌리기
NSLayoutConstraint.activate([
searchView.widthAnchor.constraint(equalToConstant: 30)
])
NSLayoutConstraint.activate([
feedView.widthAnchor.constraint(equalToConstant: 30)
])
3️⃣ UIBarButtonItem → extension으로 중복 코드 줄이기
let searchView = CustomBarItem(config: searchConfig)
NSLayoutConstraint.activate([
searchView.widthAnchor.constraint(equalToConstant: 30)
])
let searchItem = UIBarButtonItem(customView: searchView)
↑ 코드를 줄여보자!
extension 할 파일 하나 더 만들기 → UIBarButtonItem + CustomView
// UIBarButtonItem+CustomView
import Foundation
import UIKit
extension UIBarButtonItem {
static func generate(with config: CustomBarItemConfiguration, width: CGFloat?) -> UIBarButtonItem {
let customView = CustomBarItem(config: config)
if let width = width {
NSLayoutConstraint.activate([
customView.widthAnchor.constraint(equalToConstant: width)
])
}
let barButtonItem = UIBarButtonItem(customView: customView)
return barButtonItem
}
}
case is HomeViewController:
let titleConfig = CustomBarItemConfiguration(
title: "공릉동",
handler: { }
)
let titleItem = UIBarButtonItem.generate(with: titleConfig, width: nil)
let searchConfig = CustomBarItemConfiguration(
image:UIImage(systemName: "magnifyingglass"),
handler: {print("--> search tapped")}
)
let searchItem = UIBarButtonItem.generate(with: searchConfig, width: 30)
let feedConfig = CustomBarItemConfiguration(
image:UIImage(systemName: "bell"),
handler: {print("--> feed tapped")}
)
let feedItem = UIBarButtonItem.generate(with: feedConfig, width: 30)
navigationItem.leftBarButtonItem = titleItem
navigationItem.rightBarButtonItems = [feedItem, searchItem] // 아이템 여러개 설정할 때는 Items로 하고 배열로 넣어주기
↑ 이렇게 줄어듦!
4️⃣ viewController에 따라서 navigation 업데이트 : 앱이 시작할 때, 네비게이션 아이템 설정을 완료
- viewWillAppear
// MainTabBarViewController.swift
import UIKit
// 앱이 시작할 때, 네비게이션 아이템 설정을 완료하고 싶다.
class MainTabBarViewController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
delegate = self
}
// TabBarContoller가 보여지기 시작하는 시점에
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
updateNavigationItem(vc: self.selectedViewController!)
}
// viewController에 따라서 navigation 업데이트
private func updateNavigationItem(vc: UIViewController) {
switch vc {
case is HomeViewController:
let titleConfig = CustomBarItemConfiguration(
title: "공릉동",
handler: { }
)
let titleItem = UIBarButtonItem.generate(with: titleConfig, width: nil)
let searchConfig = CustomBarItemConfiguration(
image:UIImage(systemName: "magnifyingglass"),
handler: {print("--> search tapped")}
)
let searchItem = UIBarButtonItem.generate(with: searchConfig, width: 30)
let feedConfig = CustomBarItemConfiguration(
image:UIImage(systemName: "bell"),
handler: {print("--> feed tapped")}
)
let feedItem = UIBarButtonItem.generate(with: feedConfig, width: 30)
navigationItem.leftBarButtonItem = titleItem
navigationItem.rightBarButtonItems = [feedItem, searchItem] // 아이템 여러개 설정할 때는 Items로 하고 배열로 넣어주기
case is MyTownViewController:
let titleConfig = CustomBarItemConfiguration(
title: "공릉동",
handler: { }
)
let titleItem = UIBarButtonItem.generate(with: titleConfig, width: nil)
let feedConfig = CustomBarItemConfiguration(
image:UIImage(systemName: "bell"),
handler: {print("--> feed tapped")}
)
let feedItem = UIBarButtonItem.generate(with: feedConfig, width: 30)
navigationItem.leftBarButtonItem = titleItem
navigationItem.rightBarButtonItems = [feedItem] // 아이템 여러개 설정할 때는 Items로 하고 배열로 넣어주기
case is ChatViewController:
let titleConfig = CustomBarItemConfiguration(
title: "채팅",
handler: { }
)
let titleItem = UIBarButtonItem.generate(with: titleConfig, width: nil)
let feedConfig = CustomBarItemConfiguration(
image:UIImage(systemName: "bell"),
handler: {print("--> feed tapped")}
)
let feedItem = UIBarButtonItem.generate(with: feedConfig, width: 30)
navigationItem.leftBarButtonItem = titleItem
navigationItem.rightBarButtonItems = [feedItem] // 아이템 여러개 설정할 때는 Items로 하고 배열로 넣어주기
case is MyProfileViewController:
let titleConfig = CustomBarItemConfiguration(
title: "나의 당근",
handler: { }
)
let titleItem = UIBarButtonItem.generate(with: titleConfig, width: nil)
let settingConfig = CustomBarItemConfiguration(
image: UIImage(systemName: "gearshape"),
handler: { print("--> setting tapped") }
)
let settingItem = UIBarButtonItem.generate(with: settingConfig, width: 30)
navigationItem.leftBarButtonItem = titleItem
navigationItem.rightBarButtonItems = [settingItem]
default:
let titleConfig = CustomBarItemConfiguration(
title: "나의 당근",
handler: { }
)
let titleItem = UIBarButtonItem.generate(with: titleConfig, width: nil)
navigationItem.leftBarButtonItem = titleItem
navigationItem.rightBarButtonItems = []
}
}
}
// 어떤 Controller가 탭 되었는지 알 수 있음
extension MainTabBarViewController: UITabBarControllerDelegate {
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
updateNavigationItem(vc: viewController)
}
}
5️⃣ 상세뷰로 들어갔을 때 navigation style 바꾸기
- Back 이라는 타이틀 삭제
navigationItem.backButtonDisplayMode = .minimal // 타이틀 말고 아이콘만 보이게 됨.
- 화살표 아이콘 커스텀
// MainNavigationViewController.swift
import UIKit
class MainNavigationViewController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
let backImage = UIImage(systemName: "arrow.backward")
navigationBar.backIndicatorImage = backImage
navigationBar.backIndicatorTransitionMaskImage = backImage
navigationBar.tintColor = .white
}
}
🚀 구현 완료 화면
'iOS' 카테고리의 다른 글
[iOS] CocoaPods 설치 및 Xcode 연동 (0) | 2022.10.21 |
---|---|
[iOS] 하나의 Storyboard에는 하나의 View controller 만! (0) | 2022.10.20 |
[iOS] UICollectionViewDelegate (0) | 2022.09.15 |
[iOS] iOS에서의 네트워크 (0) | 2022.07.14 |
[iOS] 네트워크 왕 기초 개념 (0) | 2022.07.14 |