Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions iBox/Sources/Extension/UIView+Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,15 @@ extension Then where Self: AnyObject {
}

extension UIView: Then {}

extension UIView {

func toUserInterfaceStyle(_ theme: Theme) -> UIUserInterfaceStyle {
switch theme {
case .light: return UIUserInterfaceStyle.light
case .dark: return UIUserInterfaceStyle.dark
case .system: return UIUserInterfaceStyle.unspecified
}
}

}
3 changes: 1 addition & 2 deletions iBox/Sources/Model/MyPageItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Created by jiyeon on 1/3/24.
//

import UIKit
import Foundation

struct MyPageSection {
var title: String
Expand All @@ -15,5 +15,4 @@ struct MyPageSection {
struct MyPageItem {
var title: String
var description: String?
var viewController: UIViewController?
}
16 changes: 4 additions & 12 deletions iBox/Sources/Model/Theme.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,11 @@ enum Theme: Codable, CaseIterable {
}
}

func toImage() -> UIImage? {
func toImageString() -> String {
switch self {
case .light: UIImage(systemName: "circle")
case .dark: UIImage(systemName: "circle.fill")
case .system: UIImage(systemName: "circle.righthalf.filled")
}
}

func toUserInterfaceStyle() -> UIUserInterfaceStyle {
switch self {
case .light: UIUserInterfaceStyle.light
case .dark: UIUserInterfaceStyle.dark
case .system: UIUserInterfaceStyle.unspecified
case .light: "circle"
case .dark: "circle.fill"
case .system: "circle.righthalf.filled"
}
}
}
87 changes: 87 additions & 0 deletions iBox/Sources/Presenter/MyPage/MyPageView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import UIKit

class MyPageView: BaseView {

// MARK: - Properties

var delegate: MyPageViewDelegate?
private var viewModel: MyPageViewModel?

// MARK: - UI

let profileView = UIView().then {
Expand Down Expand Up @@ -38,8 +43,27 @@ class MyPageView: BaseView {
$0.sectionHeaderTopPadding = 0
}

// MARK: - Initializer

override init(frame: CGRect) {
super.init(frame: frame)
setupProperties()
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

// MARK: - BaseViewProtocol

private func setupProperties() {
tableView.delegate = self
tableView.dataSource = self

let tapGesture = UITapGestureRecognizer(target: self, action: #selector(profileViewTapped))
profileView.addGestureRecognizer(tapGesture)
}

override func configureUI() {
addSubview(profileView)
profileView.addSubview(profileImageView)
Expand Down Expand Up @@ -75,4 +99,67 @@ class MyPageView: BaseView {
}
}

// MARK: - Bind ViewModel

func bindViewModel(_ viewModel: MyPageViewModel) {
self.viewModel = viewModel
}

// MARK: - functions

@objc func profileViewTapped() {
delegate?.pushViewController(ProfileViewController())
}

}

extension MyPageView: UITableViewDelegate, UITableViewDataSource {

// 테이블 뷰의 섹션 개수 설정
func numberOfSections(in tableView: UITableView) -> Int {
guard let viewModel = viewModel else { return 0 }
return viewModel.myPageSectionViewModels.count
}

// 테이블 뷰의 행 개수 설정
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard let viewModel = viewModel else { return 0 }
return viewModel.myPageSectionViewModels[section].model.items.count
}

// 테이블 뷰 셀 구성
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let viewModel = viewModel,
let cell = tableView.dequeueReusableCell(withIdentifier: "MyPageItemCell")
as? MyPageItemCell else { return UITableViewCell() }
let item = viewModel.myPageSectionViewModels[indexPath.section].model.items[indexPath.row]
cell.titleLabel.text = item.title
cell.descriptionLabel.text = item.description
return cell
}

// 셀의 높이 설정
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 65
}

// 섹션 헤더의 View 설정
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView()
headerView.backgroundColor = .systemGroupedBackground
return headerView
}

// 섹션 헤더의 높이 설정
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 10
}

// 테이블 뷰 셀이 선택되었을 때 실행되는 메서드
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let viewModel = viewModel else { return }
let item = viewModel.myPageSectionViewModels[indexPath.section].model.items[indexPath.row]
delegate?.pushViewController(indexPath)
}

}
92 changes: 25 additions & 67 deletions iBox/Sources/Presenter/MyPage/MyPageViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,24 @@

import UIKit

protocol MyPageViewDelegate {
func pushViewController(_ indexPath: IndexPath)
func pushViewController(_ viewController: UIViewController)
}

class MyPageViewController: BaseNavigationBarViewController<MyPageView> {

// MARK: - properties
// MARK: - Properties

var myPageSections: [MyPageSection] = [
.init(title: "settings", items: [
MyPageItem(title: "테마", viewController: ThemeViewController())
]),
.init(title: "help", items: [
MyPageItem(title: "이용 가이드"),
MyPageItem(title: "앱 피드백"),
MyPageItem(title: "개발자 정보", description: "지쿠 😆✌🏻")
])
]
private let viewModel = MyPageViewModel()

// MARK: - life cycle

override func viewDidLoad() {
super.viewDidLoad()
guard let contentView = contentView as? MyPageView else { return }

contentView.tableView.delegate = self
contentView.tableView.dataSource = self

let tapGesture = UITapGestureRecognizer(target: self, action: #selector(profileViewTapped))
contentView.profileView.addGestureRecognizer(tapGesture)
contentView.delegate = self
contentView.bindViewModel(viewModel)
}

// MARK: - BaseNavigationBarViewControllerProtocol
Expand All @@ -41,58 +33,24 @@ class MyPageViewController: BaseNavigationBarViewController<MyPageView> {
setNavigationBarTitleLabelText("My Page")
}

// MARK: - functions

@objc func profileViewTapped(_ gesture: UITapGestureRecognizer) {
let viewController = ProfileViewController()
navigationController?.pushViewController(viewController, animated: true)
}

}

extension MyPageViewController: UITableViewDelegate, UITableViewDataSource {

// 테이블 뷰의 섹션 개수 설정
func numberOfSections(in tableView: UITableView) -> Int {
return myPageSections.count
}

// 테이블 뷰의 행 개수 설정
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myPageSections[section].items.count
}

// 테이블 뷰 셀 구성
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "MyPageItemCell")
as? MyPageItemCell else { return UITableViewCell() }
let item = myPageSections[indexPath.section].items[indexPath.row]
cell.titleLabel.text = item.title
cell.descriptionLabel.text = item.description
return cell
}

// 셀의 높이 설정
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 65
}

// 섹션 헤더의 View 설정
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView()
headerView.backgroundColor = .systemGroupedBackground
return headerView
}

// 섹션 헤더의 높이 설정
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 10
}

// 테이블 뷰 셀이 선택되었을 때 실행되는 메서드
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let item = myPageSections[indexPath.section].items[indexPath.row]
guard let viewController = item.viewController else { return }
extension MyPageViewController: MyPageViewDelegate {

func pushViewController(_ indexPath: IndexPath) {
if indexPath.section == 0 {
navigationController?.pushViewController(ThemeViewController(), animated: true)
} else {
switch indexPath.row {
case 0: print("이용 가이드 탭 !")
case 1: print("앱 피드백 탭 !")
case 2: print("개발자 정보 탭 !")
default: break;
}
}
}

func pushViewController(_ viewController: UIViewController) {
navigationController?.pushViewController(viewController, animated: true)
}

Expand Down
2 changes: 1 addition & 1 deletion iBox/Sources/Presenter/MyPage/Theme/ThemeCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class ThemeCell: UITableViewCell, BaseViewProtocol {

func bind(_ theme: Theme) {
titleLabel.text = theme.toString()
themeImageView.image = theme.toImage()
themeImageView.image = UIImage(systemName: theme.toImageString())
}

func setupSelectButton(_ selected: Bool) {
Expand Down
67 changes: 67 additions & 0 deletions iBox/Sources/Presenter/MyPage/Theme/ThemeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@
// Created by jiyeon on 1/3/24.
//

import Combine
import UIKit

import SnapKit

class ThemeView: BaseView {

// MARK: - Properties

private var viewModel: ThemeViewModel?
private var cancellables = Set<AnyCancellable>()

// MARK: - UI

let tableView = UITableView().then {
Expand All @@ -19,8 +25,24 @@ class ThemeView: BaseView {
$0.sectionHeaderTopPadding = 0
}

// MARK: - Initializer

override init(frame: CGRect) {
super.init(frame: frame)
setupProperties()
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

// MARK: - BaseViewProtocol

private func setupProperties() {
tableView.delegate = self
tableView.dataSource = self
}

override func configureUI() {
addSubview(tableView)

Expand All @@ -29,4 +51,49 @@ class ThemeView: BaseView {
}
}

// MARK: - Bind ViewModel

func bineViewModel(_ viewModel: ThemeViewModel) {
self.viewModel = viewModel
viewModel.$selectedIndex
.receive(on: RunLoop.main)
.sink { [weak self] selectedIndex in
guard let window = self?.window else { return }
UserDefaultsManager.theme.value = Theme.allCases[selectedIndex]
window.overrideUserInterfaceStyle = self?.toUserInterfaceStyle(UserDefaultsManager.theme.value) ?? .unspecified
self?.tableView.reloadData()
}.store(in: &cancellables)
}

}

extension ThemeView: UITableViewDelegate, UITableViewDataSource {

// 테이블 뷰의 행 개수 설정
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Theme.allCases.count
}

// 테이블 뷰 셀 구성
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let viewModel = viewModel,
let cell = tableView.dequeueReusableCell(withIdentifier: "ThemeCell")
as? ThemeCell else { return UITableViewCell() }
let theme = Theme.allCases[indexPath.row]
cell.bind(theme)
cell.setupSelectButton(viewModel.selectedIndex == indexPath.row)
return cell
}

// 셀의 높이 설정
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 55
}

// 테이블 뷰 셀이 선택되었을 때 실행되는 메서드
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let viewModel = viewModel else { return }
viewModel.selectedIndex = indexPath.row
}

}
Loading