Skip to content

Commit

Permalink
[iOS#541] 카테고리 Feature 모듈화 (#543)
Browse files Browse the repository at this point in the history
* chore: Category Package 추가

* chore: Category 패키지 의존성 주입

* feat: Timer 모듈 Category 모듈 재사용 뷰 DesignSystem으로 이동

* chore: Timer 모듈 Category 모듈 분리

* chore: Service 패키지로 CategoryManager 이동

- Service 패키지 내부에 CategoryService 모듈 생성
- CategoryService 모듈을 외부에서 Library로 사용할 수 있게 설정

* feat: Category 패키지, Timer 패키지에 Service 의존성 추가

- Service 패키지 의존성 추가
- CategoryService 모듈 의존성 추가

* feat: CategoryService 모듈 적용

* feat: 카테고리 목록 재사용을 위한 CategoryInfoView 구현

- Timer Feature, Category Feature 각각의 Cell을 가지기 위해 공통 부분 CustomView로 수정

* feat: CategorySettingCollectionViewCell 구현

- Category Feature에서 사용하는 새로운 Cell
- 기존의 CategoryListCollectionViewCell를 재사용하지 않기 위해 Category Feature 내부에 구현

* feat: CategoryListSection, CategoryListItem 모델 구현

- 기존의 공통으로 재사용하던 CategorySettingSection, CategorySettingItem 대신 Timer Feature 내부에 새로운 SectionType, ItemType 생성

* feat: CategoryListCollectionViewCell 구현

- Timer Feature에서 사용하는 카테고리 CollectionViewCell

* feat: TimerViewController 변경사항 적용

- CategoryListCollectionViewCell 적용
- CategoryListSectionType, CaetgoryListItemType 적용

* chore: CategorySettingFooterView 위치 이동

- 기존 DesignSystem 모듈에서 Category 모듈로 이동

* chore: 기존 CategoryListCollcetionViewCell 삭제

* feat: Cell layer 설정 수정

* feat: 불필요한 public 접근제어자 삭제

* feat: Category Package 의존성 주입 경로 수정
  • Loading branch information
leemhyungyu authored Jun 18, 2024
1 parent 5598ca6 commit 73f6770
Show file tree
Hide file tree
Showing 30 changed files with 389 additions and 95 deletions.
8 changes: 8 additions & 0 deletions iOS/FlipMate/Feature/Category/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.DS_Store
/.build
/Packages
xcuserdata/
DerivedData/
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
29 changes: 29 additions & 0 deletions iOS/FlipMate/Feature/Category/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// swift-tools-version: 5.10
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "Category",
platforms: [.iOS(.v14)],
products: [
.library(name: "Category", targets: ["Category"]),
],

dependencies: [
.package(name: "Core", path: "../../Core"),
.package(name: "DesignSystem", path: "../../DesignSystem"),
.package(name: "Domain", path: "../../Domain"),
.package(name: "Service", path: "../../Service")
],

targets: [
.target(name: "Category", dependencies: [
.product(name: "Core", package: "Core"),
.product(name: "DesignSystem", package: "DesignSystem"),
.product(name: "Domain", package: "Domain"),
.product(name: "CategoryService", package: "Service")
]),
.testTarget(name: "CategoryTests", dependencies: ["Category"]),
]
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// CategorySettingCollectionViewCell.swift
//
//
// Created by 임현규 on 6/16/24.
//

import UIKit
import DesignSystem

final class CategorySettingCollectionViewCell: UICollectionViewCell {

// MARK: - UI Components
private let categoryView: CategoryInfoView = {
let view = CategoryInfoView(isTimerLabelHidden: true)
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .systemBackground
return view
}()

// MARK: - init
override init(frame: CGRect) {
super.init(frame: frame)
configureUI()
configureCategoryCellLayer()
}

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

// MARK: - UI Update Methods
func updateUI(_ subjectLabelText: String, _ circleBackgroundColor: UIColor?, _ timeLabelText: String?) {
categoryView.updateUI(subjectLabelText, circleBackgroundColor, timeLabelText)
}
}

// MARK: - Private Methods
private extension CategorySettingCollectionViewCell {
func configureUI() {
[ categoryView ] .forEach { contentView.addSubview($0) }

NSLayoutConstraint.activate([
categoryView.topAnchor.constraint(equalTo: contentView.topAnchor),
categoryView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
categoryView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
categoryView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
])
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public final class CategorySettingViewController: BaseViewController {
private lazy var collectionView: UICollectionView = {
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: setCollectionViewLayout())
collectionView.translatesAutoresizingMaskIntoConstraints = false
collectionView.register(CategoryListCollectionViewCell.self)
collectionView.register(CategorySettingCollectionViewCell.self)
collectionView.register(CategorySettingFooterView.self, kind: .footer)
return collectionView
}()
Expand Down Expand Up @@ -145,10 +145,9 @@ private extension CategorySettingViewController {
cellProvider: { collectionView, indexPath, itemIdentifier in
switch itemIdentifier {
case .categoryCell(let category):
let cell: CategoryListCollectionViewCell = collectionView
let cell: CategorySettingCollectionViewCell = collectionView
.dequeueReusableCell(for: indexPath)
cell.updateUI(category: category)
cell.setTimeLabelHidden(isHidden: true)
cell.updateUI(category.subject, UIColor(hexString: category.color), category.studyTime?.secondsToStringTime())
return cell
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Combine

import Domain
import Core
import CategoryService

public struct CategoryModifyViewModelActions {
public let didFinishCategoryModify: () -> Void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Foundation
import Combine

import Domain
import CategoryService

public struct CategoryViewModelActions {
let showModifyCategory: (CategoryPurpose, StudyCategory?) -> Void
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import XCTest
@testable import Category

final class CategoryTests: XCTestCase {
func testExample() throws {
// XCTest Documentation
// https://developer.apple.com/documentation/xctest

// Defining Test Cases and Test Methods
// https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods
}
}
8 changes: 8 additions & 0 deletions iOS/FlipMate/Feature/Service/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.DS_Store
/.build
/Packages
xcuserdata/
DerivedData/
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
25 changes: 25 additions & 0 deletions iOS/FlipMate/Feature/Service/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// swift-tools-version: 5.10
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "Service",
platforms: [.iOS(.v14)],
products: [
.library(name: "CategoryService", targets: ["CategoryService"]),
],

dependencies: [
.package(name: "Domain", path: "../Domain")
],

targets: [
.target(name: "CategoryService", dependencies: [
.product(name: "Domain", package: "Domain")
]),
.testTarget(name: "ServiceTests", dependencies: [
"CategoryService"
]),
]
)
Original file line number Diff line number Diff line change
@@ -1,24 +1,14 @@
//
// File.swift
//
// CategoryManager.swift
//
// Created by 권승용 on 5/31/24.
//
// Created by 임현규 on 6/14/24.
//

import Foundation
import Combine
import Domain

public protocol CategoryManageable {
var categoryDidChangePublisher: AnyPublisher<[StudyCategory], Never> { get }
func replace(categories: [StudyCategory])
func change(category: StudyCategory)
func removeCategory(categoryId: Int)
func append(category: StudyCategory)
func findCategory(categoryId: Int) -> StudyCategory?
func numberOfCategory() -> Int
}

public final class CategoryManager: CategoryManageable {
// MARK: - Properties
private lazy var categoryDidChangeSubject = CurrentValueSubject<[StudyCategory], Never>(categories)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// CategoryManageable.swift
//
//
// Created by 임현규 on 6/14/24.
//

import Foundation
import Combine
import Domain

public protocol CategoryManageable {
var categoryDidChangePublisher: AnyPublisher<[StudyCategory], Never> { get }
func replace(categories: [StudyCategory])
func change(category: StudyCategory)
func removeCategory(categoryId: Int)
func append(category: StudyCategory)
func findCategory(categoryId: Int) -> StudyCategory?
func numberOfCategory() -> Int
}
12 changes: 12 additions & 0 deletions iOS/FlipMate/Feature/Service/Tests/ServiceTests/ServiceTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import XCTest
@testable import Service

final class ServiceTests: XCTestCase {
func testExample() throws {
// XCTest Documentation
// https://developer.apple.com/documentation/xctest

// Defining Test Cases and Test Methods
// https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods
}
}
18 changes: 18 additions & 0 deletions iOS/FlipMate/FlipMate.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
/* Begin PBXBuildFile section */
2C04FF5C2BF78E6F0065075F /* DesignSystem in Frameworks */ = {isa = PBXBuildFile; productRef = 2C04FF5B2BF78E6F0065075F /* DesignSystem */; };
2C6549C02BFDD6E900105D5A /* Data in Frameworks */ = {isa = PBXBuildFile; productRef = 2C6549BF2BFDD6E900105D5A /* Data */; };
2C82BD7F2C18482D00CAD08B /* Category in Frameworks */ = {isa = PBXBuildFile; productRef = 2C82BD7E2C18482D00CAD08B /* Category */; };
2C8D20F62B7216EE00632718 /* AppFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C88DCF12B124238000B4686 /* AppFlowCoordinator.swift */; };
2C8D20F72B7216EE00632718 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 600908BD2AFCD7DF0065DFFB /* AppDelegate.swift */; };
2C8D20F82B7216EE00632718 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 600908BF2AFCD7DF0065DFFB /* SceneDelegate.swift */; };
Expand All @@ -30,6 +31,7 @@
2C8D21422B7216EF00632718 /* (null) in Sources */ = {isa = PBXBuildFile; };
2C8D21432B7216EF00632718 /* (null) in Sources */ = {isa = PBXBuildFile; };
2C8D21442B7216EF00632718 /* (null) in Sources */ = {isa = PBXBuildFile; };
2CB24F4B2C1C234400327FA0 /* CategoryService in Frameworks */ = {isa = PBXBuildFile; productRef = 2CB24F4A2C1C234400327FA0 /* CategoryService */; };
2CD272ED2B21A619000CB9E5 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2CD272EF2B21A619000CB9E5 /* Localizable.strings */; };
600908CA2AFCD7E00065DFFB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 600908C82AFCD7E00065DFFB /* LaunchScreen.storyboard */; };
600D81362B51344500670882 /* TimerViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60FBEE4D2B4B82B1006B1CF9 /* TimerViewModelTests.swift */; };
Expand Down Expand Up @@ -69,6 +71,7 @@
/* Begin PBXFileReference section */
2C04FF5A2BF78AAE0065075F /* DesignSystem */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = DesignSystem; path = FlipMate/DesignSystem; sourceTree = "<group>"; };
2C24ECCF2BFDD4E4000664BC /* Data */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Data; path = FlipMate/Data; sourceTree = "<group>"; };
2C82BD7D2C18406400CAD08B /* Category */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = Category; sourceTree = "<group>"; };
2C88DCF12B124238000B4686 /* AppFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppFlowCoordinator.swift; sourceTree = "<group>"; };
2C88DCF32B124272000B4686 /* AppDIContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDIContainer.swift; sourceTree = "<group>"; };
2C88DCF52B124292000B4686 /* TimerSceneDIContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimerSceneDIContainer.swift; sourceTree = "<group>"; };
Expand All @@ -80,6 +83,7 @@
2C88DD082B1274FA000B4686 /* CategorySettingCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategorySettingCoordinator.swift; sourceTree = "<group>"; };
2C88DD0A2B1340E4000B4686 /* CategoryDIContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryDIContainer.swift; sourceTree = "<group>"; };
2C9F622E2B17505B00AE63F9 /* FriendAddViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FriendAddViewModelTests.swift; sourceTree = "<group>"; };
2CB24F492C1C173D00327FA0 /* Service */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Service; path = Feature/Service; sourceTree = "<group>"; };
2CD272EE2B21A619000CB9E5 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
2CD272F02B21A622000CB9E5 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Localizable.strings; sourceTree = "<group>"; };
2CD272F12B21A62B000CB9E5 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Localizable.strings; sourceTree = "<group>"; };
Expand Down Expand Up @@ -128,11 +132,13 @@
60780C942C0C576800C1FC52 /* Chart in Frameworks */,
60C368E82BFBA1DA008C76ED /* Domain in Frameworks */,
604309E82BF1AFE800768D87 /* GoogleSignInSwift in Frameworks */,
2C82BD7F2C18482D00CAD08B /* Category in Frameworks */,
6037BB572C0AE23100BE37AC /* Timer in Frameworks */,
601F39742BF399B9001689A0 /* Core in Frameworks */,
60BB72782BEA709D00E2A7E9 /* FMImageProvider in Frameworks */,
604309E62BF1AFE800768D87 /* GoogleSignIn in Frameworks */,
2C6549C02BFDD6E900105D5A /* Data in Frameworks */,
2CB24F4B2C1C234400327FA0 /* CategoryService in Frameworks */,
6071B1C72BF73BF10044574F /* Network in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -181,6 +187,7 @@
2C04FF5A2BF78AAE0065075F /* DesignSystem */,
602BF08C2BF4FB5B0088050A /* Network */,
601F396A2BF3836F001689A0 /* Core */,
2CB24F492C1C173D00327FA0 /* Service */,
600908D32AFCD7E00065DFFB /* FlipMateTests */,
600908BB2AFCD7DF0065DFFB /* Products */,
601F396B2BF386DC001689A0 /* Frameworks */,
Expand Down Expand Up @@ -372,6 +379,7 @@
60FE503F2C01C7B600AA2475 /* Feature */ = {
isa = PBXGroup;
children = (
2C82BD7D2C18406400CAD08B /* Category */,
60590D9E2C0C3D9D0069B3E4 /* TabBar */,
60590DA32C0C46410069B3E4 /* Login */,
60FE50402C020EC200AA2475 /* Timer */,
Expand Down Expand Up @@ -414,6 +422,8 @@
60780C932C0C576800C1FC52 /* Chart */,
608920152C0C7F7100FFDB14 /* Social */,
609B1B922C0CCBB100F5A5A6 /* MyPage */,
2C82BD7E2C18482D00CAD08B /* Category */,
2CB24F4A2C1C234400327FA0 /* CategoryService */,
);
productName = FlipMate;
productReference = 600908BA2AFCD7DF0065DFFB /* FlipMate.app */;
Expand Down Expand Up @@ -895,6 +905,14 @@
isa = XCSwiftPackageProductDependency;
productName = Data;
};
2C82BD7E2C18482D00CAD08B /* Category */ = {
isa = XCSwiftPackageProductDependency;
productName = Category;
};
2CB24F4A2C1C234400327FA0 /* CategoryService */ = {
isa = XCSwiftPackageProductDependency;
productName = CategoryService;
};
601F39732BF399B9001689A0 /* Core */ = {
isa = XCSwiftPackageProductDependency;
productName = Core;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import UIKit
import Timer
import Domain
import Category

protocol CategoryFlowCoordinatorDependencies {
func makeCategorySettingViewController(actions: CategoryViewModelActions) -> UIViewController
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import UIKit
import Core
import Network
import Timer
import CategoryService

final class AppDIContainer {
lazy var provider: Provider = Provider(urlSession: URLSession.shared, keychainManager: KeychainManager())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import Timer
import Domain
import Network
import Data
import Category
import CategoryService

final class CategoryDIContainer: CategoryFlowCoordinatorDependencies {
struct Dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import Domain
import Network
import Core
import Data
import CategoryService

final class LoginDIContainer: LoginFlowCoordinatorDependencies {
struct Dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Network
import TabBar
import Timer
import Core
import CategoryService

final class TabBarDIContainer: TabBarFlowCoordinatorDependencies {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import Domain
import Network
import Data
import Core
import CategoryService

final class TimerSceneDIContainer: TimerFlowCoordinatorDependencies {
struct Dependencies {
Expand Down
Loading

0 comments on commit 73f6770

Please sign in to comment.