Skip to content

Commit

Permalink
Merge pull request #58 from f-lab-edu/feature/setting-view
Browse files Browse the repository at this point in the history
세팅 뷰 추가
  • Loading branch information
MojitoBar authored Jan 3, 2024
2 parents f5c9f9f + 90127c5 commit 16fa73f
Show file tree
Hide file tree
Showing 14 changed files with 471 additions and 17 deletions.
53 changes: 53 additions & 0 deletions pins.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions pins/Data/Service/FirestorageService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,9 @@ final class FirestorageService: FirestorageServiceProtocol {
}

func downloadImage(urlString: String) async -> UIImage? {
if let cachedImage = ImageCacheManager.shared.getImage(forKey: urlString) {
if let cachedImage = DiskCacheManager.retrieveCachedImage(withFilename: urlString) {
return cachedImage
}

let storageReference = Storage.storage().reference(forURL: urlString)
let megaByte = Int64(2 * 1024 * 1024)

Expand All @@ -47,7 +46,7 @@ final class FirestorageService: FirestorageServiceProtocol {
os_log("Error downloading image: \(error)")
continuation.resume(returning: nil)
} else if let data = data, let image = UIImage(data: data) {
ImageCacheManager.shared.setImage(image, forKey: urlString)
DiskCacheManager.cacheImage(image, withFilename: urlString)
continuation.resume(returning: image)
} else {
continuation.resume(returning: nil)
Expand Down
17 changes: 17 additions & 0 deletions pins/Extension/UITableView+Extensions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// UITableView+Extensions.swift
// pins
//
// Created by 주동석 on 1/3/24.
//

import UIKit

extension UITableView {
func dequeueReusableCell<T: UITableViewCell>(forIndexPath indexPath: IndexPath) -> T where T: ReuseIdentifying {
guard let cell = dequeueReusableCell(withIdentifier: T.reuseIdentifier, for: indexPath) as? T else {
fatalError("Could not dequeue cell with identifier: \(T.reuseIdentifier)")
}
return cell
}
}
14 changes: 7 additions & 7 deletions pins/Presentation/View/MainMapView/MainMapView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ final class MainMapView: UIView {
button.accessibilityLabel = "내 위치로"
return button
}()
private let logoutButton: CustomButton = {
private let settingButton: CustomButton = {
let button = CustomButton()
button.setShadow()
button.setImage(systemName: "door.right.hand.open")
button.accessibilityLabel = "로그아웃"
button.setImage(systemName: "gearshape")
button.accessibilityLabel = "설정"
return button
}()

Expand All @@ -92,7 +92,7 @@ final class MainMapView: UIView {

// MARK: - Layouts
private func setLayout() {
[mapView, centerPinImage, createButton, cancelButton, searchButton, createModeButton, refeshButton, myLocationButton, logoutButton].forEach { addSubview($0) }
[mapView, centerPinImage, createButton, cancelButton, searchButton, createModeButton, refeshButton, myLocationButton, settingButton].forEach { addSubview($0) }

mapView
.leadingLayout(equalTo: leadingAnchor)
Expand Down Expand Up @@ -142,7 +142,7 @@ final class MainMapView: UIView {
.widthLayout(45)
.heightLayout(45)

logoutButton
settingButton
.leadingLayout(equalTo: leadingAnchor, constant: 16)
.topLayout(equalTo: safeAreaLayoutGuide.topAnchor, constant: 16)
.widthLayout(45)
Expand Down Expand Up @@ -221,7 +221,7 @@ final class MainMapView: UIView {
createButton.addAction(action, for: .touchUpInside)
}

func setLogoutButtonAction(_ action: UIAction) {
logoutButton.addAction(action, for: .touchUpInside)
func setSettingButtonAction(_ action: UIAction) {
settingButton.addAction(action, for: .touchUpInside)
}
}
30 changes: 30 additions & 0 deletions pins/Presentation/View/SettingView/DiskCacheItem.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// DiskCacheItem.swift
// pins
//
// Created by 주동석 on 12/24/23.
//

import OSLog
import UIKit

final class DiskCacheItem: SettingItemHandling {
var title: String = "메모리"
var onPresentAlert: ((UIAlertController) -> Void)?

init(title: String) {
self.title = title
}

func performAction() {
let alert = ConfirmManager.makeAlert(title: "캐시 지우기", message: "모든 캐시를 지우시겠습니까?") { [weak self] in
self?.removeDiskCache()
self?.title = "메모리 Zero KB 사용중"
}
onPresentAlert?(alert)
}

private func removeDiskCache() {
DiskCacheManager.clearCache()
}
}
36 changes: 36 additions & 0 deletions pins/Presentation/View/SettingView/LogoutItem.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// LogoutItem.swift
// pins
//
// Created by 주동석 on 12/24/23.
//

import OSLog
import UIKit
import FirebaseAuth

final class LogoutItem: SettingItemHandling {
var title: String = "로그아웃"
var navigationController: UINavigationController?
var onPresentAlert: ((UIAlertController) -> Void)?

init(navigationController: UINavigationController?) {
self.navigationController = navigationController
}

func performAction() {
let alert = ConfirmManager.makeAlert(title: "로그아웃", message: "정말 로그아웃 하시겠습니까?") { [weak self] in
self?.logout()
}
onPresentAlert?(alert)
}

private func logout() {
do {
try Auth.auth().signOut()
navigationController?.viewControllers = [LoginViewController()]
} catch {
os_log("logout \(error)")
}
}
}
98 changes: 98 additions & 0 deletions pins/Presentation/View/SettingView/SettingView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//
// SettingView.swift
// pins
//
// Created by 주동석 on 12/20/23.
//

import UIKit

final class SettingView: UIView {
enum SettingSection: Int {
case mainSection
}
typealias SettingDataSource = UITableViewDiffableDataSource<SettingSection, String>
typealias SettingSnapshot = NSDiffableDataSourceSnapshot<SettingSection, String>
// MARK: - 프로퍼티
private let titleLabel: UILabel = {
let label: UILabel = UILabel()
label.text = "설정"
label.textColor = .defaultText
label.font = UIFont.systemFont(ofSize: 18)
return label
}()
private let backButton: CustomButton = {
let button = CustomButton(backgroundColor: .defaultBackground)
button.setImage(systemName: "chevron.backward")
return button
}()
let tableView: UITableView = {
let tableView: UITableView = UITableView(frame: .zero, style: .plain)
tableView.register(SettingViewCell.self, forCellReuseIdentifier: "SettingViewCell")
tableView.backgroundColor = .defaultBackground
tableView.separatorInset.left = 0
return tableView
}()
private var dataSource: SettingDataSource!
private var viewModel: SettingViewModel!
// MARK: - 초기화
init(viewModel: SettingViewModel) {
super.init(frame: .zero)
backgroundColor = .defaultBackground
self.viewModel = viewModel

setBackButtonLayout()
setTitleLabelLayout()
setTableViewLayout()
configureDiffableDataSource()
performInitialDataPopulation()
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - 타이틀
private func setTitleLabelLayout() {
addSubview(titleLabel)
titleLabel
.topLayout(equalTo: safeAreaLayoutGuide.topAnchor)
.centerXLayout(equalTo: centerXAnchor)

}
// MARK: - 뒤로가기
private func setBackButtonLayout() {
addSubview(backButton)
backButton
.leadingLayout(equalTo: leadingAnchor, constant: 16)
.topLayout(equalTo: safeAreaLayoutGuide.topAnchor)
}

func setBackButtonAction(_ action: UIAction) {
backButton.addAction(action, for: .touchUpInside)
}
// MARK: - 테이블 뷰
private func setTableViewLayout() {
addSubview(tableView)
tableView
.topLayout(equalTo: titleLabel.bottomAnchor, constant: 16)
.bottomLayout(equalTo: bottomAnchor)
.leadingLayout(equalTo: leadingAnchor)
.trailingLayout(equalTo: trailingAnchor)
}

private func configureDiffableDataSource() {
dataSource = SettingDataSource(tableView: tableView, cellProvider: { [weak self] tableView, indexPath, _ in
guard let self else { fatalError("self is nil") }
let cell = tableView.dequeueReusableCell(forIndexPath: indexPath) as SettingViewCell
cell.setLabelText(self.viewModel.getTableStringData()[indexPath.row])
return cell
})
}

private func performInitialDataPopulation() {
var snapshot = SettingSnapshot()
snapshot.appendSections([.mainSection])
snapshot.appendItems(viewModel.getTableStringData())
dataSource.apply(snapshot, animatingDifferences: true)
}
}
37 changes: 37 additions & 0 deletions pins/Presentation/View/SettingView/SettingViewCell.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// SettingTableCell.swift
// pins
//
// Created by 주동석 on 12/20/23.
//

import UIKit

final class SettingViewCell: UITableViewCell, ReuseIdentifying {
private let label: UILabel = {
let label: UILabel = UILabel()
label.textColor = .defaultText
label.font = UIFont.systemFont(ofSize: 18)
return label
}()

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
backgroundColor = .defaultBackground
configureLabel()
}

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

private func configureLabel() {
addSubview(label)
label.leadingLayout(equalTo: leadingAnchor, constant: 16)
.centerYLayout(equalTo: centerYAnchor)
}

func setLabelText(_ text: String) {
label.text = text
}
}
10 changes: 3 additions & 7 deletions pins/Presentation/ViewController/MainViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,9 @@ final class MainViewController: UIViewController {
self?.viewModel.setCreateViewIsPresented(isPresented: false)
}))

mainMapView.setLogoutButtonAction(UIAction(handler: { [weak self] _ in
do {
try Auth.auth().signOut()
self?.navigationController?.viewControllers = [LoginViewController()]
} catch let signOutError as NSError {
os_log("Error signing out: %@", log: .ui, type: .error, signOutError)
}
mainMapView.setSettingButtonAction(UIAction(handler: { [weak self] _ in
let settingViewController: SettingViewController = SettingViewController()
self?.navigationController?.pushViewController(settingViewController, animated: true)
}))
}
}
Expand Down
57 changes: 57 additions & 0 deletions pins/Presentation/ViewController/SettingViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//
// SettingViewController.swift
// pins
//
// Created by 주동석 on 12/20/23.
//

import UIKit

final class SettingViewController: UIViewController {
private lazy var viewModel: SettingViewModel = {
let logoutItem = LogoutItem(navigationController: navigationController)
logoutItem.onPresentAlert = { [weak self] alert in
self?.present(alert, animated: true)
}
let cacheSize = DiskCacheManager.calculateCacheSize()
let formattedSize = DiskCacheManager.formatBytes(cacheSize)
let diskCacheItem = DiskCacheItem(title: "메모리 \(formattedSize) 사용중")
diskCacheItem.onPresentAlert = { [weak self] alert in
self?.present(alert, animated: true)
}
return SettingViewModel(tableData: [
logoutItem,
diskCacheItem
])
}()
private var settingView: SettingView {
view as! SettingView
}

override func viewDidLoad() {
super.viewDidLoad()
setAction()
setTableDelegate()
}

override func loadView() {
view = SettingView(viewModel: viewModel)
}

private func setAction() {
settingView.setBackButtonAction(UIAction(handler: { [weak self] _ in
self?.navigationController?.popViewController(animated: true)
}))
}

private func setTableDelegate() {
settingView.tableView.delegate = self
}
}

extension SettingViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let selectedItem = viewModel.getTableData()[indexPath.row]
selectedItem.performAction()
}
}
24 changes: 24 additions & 0 deletions pins/Presentation/ViewModel/SettingViewModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// SettingViewModel.swift
// pins
//
// Created by 주동석 on 12/24/23.
//

import Foundation

final class SettingViewModel {
private var tableData: [SettingItemHandling] = []

init(tableData: [SettingItemHandling]) {
self.tableData = tableData
}

func getTableData() -> [SettingItemHandling] {
return tableData
}

func getTableStringData() -> [String] {
return tableData.map { $0.title }
}
}
Loading

0 comments on commit 16fa73f

Please sign in to comment.