diff --git a/Projects/Data/Data.xcodeproj/project.pbxproj b/Projects/Data/Data.xcodeproj/project.pbxproj index ca9f575..88983d5 100644 --- a/Projects/Data/Data.xcodeproj/project.pbxproj +++ b/Projects/Data/Data.xcodeproj/project.pbxproj @@ -7,8 +7,11 @@ objects = { /* Begin PBXBuildFile section */ - 3D7C36B11F2F7C3A87B33C09 /* gitkeep.swift in Sources */ = {isa = PBXBuildFile; fileRef = 918D54447E8741D1A3F36725 /* gitkeep.swift */; }; + 43E9C2380F425520C1FA1AD2 /* CourseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAAC2885ACFE998578DC25E8 /* CourseDTO.swift */; }; + 684AAEA9796EED3F9FC592FC /* NetworkConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D46FD93B80D052843AD5063 /* NetworkConfiguration.swift */; }; + 901ACA7B98089AB702ADA830 /* Domain.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 06FAA1459D11CCE724C34195 /* Domain.framework */; }; B2F8FBFA915F696CCCA4152A /* Alamofire.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A3B0D3D8C7049B6856791C1D /* Alamofire.framework */; }; + E1BFC73FB539432F6E12CD94 /* CourseRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0730BC3657E24BCEA511A3C /* CourseRepository.swift */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -26,9 +29,12 @@ /* Begin PBXFileReference section */ 033B57EACF093CA22F91EAB9 /* Data-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "Data-Info.plist"; sourceTree = ""; }; + 06FAA1459D11CCE724C34195 /* Domain.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Domain.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 4E75197C294DE74F5162FAA7 /* Data.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Data.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 918D54447E8741D1A3F36725 /* gitkeep.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = gitkeep.swift; sourceTree = ""; }; + 5D46FD93B80D052843AD5063 /* NetworkConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkConfiguration.swift; sourceTree = ""; }; A3B0D3D8C7049B6856791C1D /* Alamofire.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Alamofire.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + AAAC2885ACFE998578DC25E8 /* CourseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseDTO.swift; sourceTree = ""; }; + B0730BC3657E24BCEA511A3C /* CourseRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseRepository.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -37,6 +43,7 @@ buildActionMask = 2147483647; files = ( B2F8FBFA915F696CCCA4152A /* Alamofire.framework in Frameworks */, + 901ACA7B98089AB702ADA830 /* Domain.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -48,10 +55,27 @@ children = ( A3B0D3D8C7049B6856791C1D /* Alamofire.framework */, 4E75197C294DE74F5162FAA7 /* Data.framework */, + 06FAA1459D11CCE724C34195 /* Domain.framework */, ); name = Products; sourceTree = ""; }; + 647255CD65221C9CD4A43DED /* DTO */ = { + isa = PBXGroup; + children = ( + AAAC2885ACFE998578DC25E8 /* CourseDTO.swift */, + ); + path = DTO; + sourceTree = ""; + }; + 73F3ED55BFDC2EF15878F5B6 /* Repository */ = { + isa = PBXGroup; + children = ( + B0730BC3657E24BCEA511A3C /* CourseRepository.swift */, + ); + path = Repository; + sourceTree = ""; + }; 8A6D38DA6706D1F4DD8A055B = { isa = PBXGroup; children = ( @@ -60,6 +84,14 @@ ); sourceTree = ""; }; + A46DA33BCE1E2288153B2AC3 /* Network */ = { + isa = PBXGroup; + children = ( + 5D46FD93B80D052843AD5063 /* NetworkConfiguration.swift */, + ); + path = Network; + sourceTree = ""; + }; AABE3A120DFAA5B30C74694C /* InfoPlists */ = { isa = PBXGroup; children = ( @@ -79,7 +111,9 @@ C590795A2658F92D49B27E8D /* Sources */ = { isa = PBXGroup; children = ( - 918D54447E8741D1A3F36725 /* gitkeep.swift */, + 647255CD65221C9CD4A43DED /* DTO */, + A46DA33BCE1E2288153B2AC3 /* Network */, + 73F3ED55BFDC2EF15878F5B6 /* Repository */, ); path = Sources; sourceTree = ""; @@ -159,7 +193,9 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 3D7C36B11F2F7C3A87B33C09 /* gitkeep.swift in Sources */, + 43E9C2380F425520C1FA1AD2 /* CourseDTO.swift in Sources */, + 684AAEA9796EED3F9FC592FC /* NetworkConfiguration.swift in Sources */, + E1BFC73FB539432F6E12CD94 /* CourseRepository.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Projects/Data/Project.swift b/Projects/Data/Project.swift index e76918c..9e4c924 100644 --- a/Projects/Data/Project.swift +++ b/Projects/Data/Project.swift @@ -10,6 +10,7 @@ let project = Project( bundleId: "io.tuist.Data", sources: ["Sources/**"], dependencies: [ + .project(target: "Domain", path: "../Domain"), .external(name: "Alamofire") ] ) diff --git a/Projects/Data/Sources/DTO/CourseDTO.swift b/Projects/Data/Sources/DTO/CourseDTO.swift new file mode 100644 index 0000000..7ff488a --- /dev/null +++ b/Projects/Data/Sources/DTO/CourseDTO.swift @@ -0,0 +1,49 @@ +// +// CourseDTO.swift +// Data +// +// Created by 박지윤 on 7/8/25. +// + +import Foundation +import Domain + +public struct HomeCourseDTO: Decodable { + public let list: [CourseDTO]? +} + +public struct CourseDTO: Decodable { + public let courseInfoDTO: [CourseInfoDTO]? +} + +public struct CourseInfoDTO: Decodable { + public let courseLv: Int? + public let courseDescription: String? + public let stepList: [StepInfoDTO]? +} + +public struct StepInfoDTO: Decodable { + public let stepLv: Int? + public let stepTitle: String? + public let stepDescription: String? + public let stepStatus: String? +} + +extension CourseDTO { + func toDomain() -> CourseVO { + return CourseVO(courseLv: 1, + courseDescription: "courseDescription", + stepLv: 1, + stepTitle: "stepTitle", + stepDescription: "stepDescription", + stepStatus: "SOLVED") + } +} + +extension HomeCourseDTO { + func toHome() -> HomeCourseVO { + let courseList = list ?? [] + return .init(list: Array(courseList + .map{$0.toDomain()})) + } +} diff --git a/Projects/Data/Sources/Network/NetworkConfiguration.swift b/Projects/Data/Sources/Network/NetworkConfiguration.swift new file mode 100644 index 0000000..e1ee221 --- /dev/null +++ b/Projects/Data/Sources/Network/NetworkConfiguration.swift @@ -0,0 +1,11 @@ +// +// NetworkConfiguration.swift +// Data +// +// Created by 박지윤 on 7/8/25. +// + +enum NetworkConfiguration { + static let appID = "" + static let baseUrl = "https://" +} diff --git a/Projects/Data/Sources/Repository/CourseRepository.swift b/Projects/Data/Sources/Repository/CourseRepository.swift new file mode 100644 index 0000000..05cd338 --- /dev/null +++ b/Projects/Data/Sources/Repository/CourseRepository.swift @@ -0,0 +1,57 @@ +// +// CourseRepository.swift +// Data +// +// Created by 박지윤 on 7/8/25. +// + +import Domain +import RxSwift +import Alamofire + +public class DefaultCourseRepository: CourseRepository { + public init() {} + + public func getCourses() -> Single { + return request( + endpoint: NetworkConfiguration.baseUrl, + id: 4, + responseType: CourseDTO.self + ) + .map { dto in + return CourseVO( + courseLv: 1, + courseDescription: "courseDescription", + stepLv: 1, + stepTitle: "stepTitle", + stepDescription: "stepDescription", + stepStatus: "SOLVED" + ) + } + } + + private func request(endpoint: String, id: Int, responseType: T.Type) -> Single { + return Single.create { single in + let url = "\(NetworkConfiguration.baseUrl)\(endpoint)" + let parameters: Parameters = [ + "id": id + ] + + let request = AF.request(url, + method: .get, + parameters: parameters, + encoding: URLEncoding.queryString) + .validate() + .responseDecodable(of: responseType) { response in + switch response.result { + case .success(let value): + single(.success(value)) + case .failure(let error): + single(.failure(error)) + } + } + + return Disposables.create { request.cancel() } + } + } + } diff --git a/Projects/Data/Sources/gitkeep.swift b/Projects/Data/Sources/gitkeep.swift deleted file mode 100644 index 79e59c9..0000000 --- a/Projects/Data/Sources/gitkeep.swift +++ /dev/null @@ -1,7 +0,0 @@ -// -// gitkeep.swift -// Data -// -// Created by 박지윤 on 7/8/25. -// - diff --git a/Projects/Domain/Domain.xcodeproj/project.pbxproj b/Projects/Domain/Domain.xcodeproj/project.pbxproj index dad565e..016720c 100644 --- a/Projects/Domain/Domain.xcodeproj/project.pbxproj +++ b/Projects/Domain/Domain.xcodeproj/project.pbxproj @@ -3,12 +3,15 @@ archiveVersion = 1; classes = { }; - objectVersion = 56; + objectVersion = 55; objects = { /* Begin PBXBuildFile section */ 0BCC97781DA6EE874B081DBE /* RxSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9A2E30672E510822AAF38EAD /* RxSwift.framework */; }; - 850D3256EE250153F112D564 /* gitkeep.swift in Sources */ = {isa = PBXBuildFile; fileRef = F05702E18938E331F26864D0 /* gitkeep.swift */; }; + 5EB8590C9D2C002D0BDBC021 /* CourseVO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 747DBBCAB797E5E0A82177F2 /* CourseVO.swift */; }; + 69DAD609572D32F2BA3845AE /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E1DA9A49E79A791F7A526A1 /* String+Extension.swift */; }; + BBED9ACB62B271298F7028F8 /* CourseUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F904C836B5CD2D4DA5EAE38D /* CourseUseCase.swift */; }; + D510BC17C4583615CB60439E /* CourseRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCA3E06ED2A8180A63919B6C /* CourseRepository.swift */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -25,9 +28,12 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 2E1DA9A49E79A791F7A526A1 /* String+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extension.swift"; sourceTree = ""; }; + 747DBBCAB797E5E0A82177F2 /* CourseVO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseVO.swift; sourceTree = ""; }; 9A2E30672E510822AAF38EAD /* RxSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RxSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; BD15A37E85BAE3A36B2CE72C /* Domain-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "Domain-Info.plist"; sourceTree = ""; }; - F05702E18938E331F26864D0 /* gitkeep.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = gitkeep.swift; sourceTree = ""; }; + DCA3E06ED2A8180A63919B6C /* CourseRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseRepository.swift; sourceTree = ""; }; + F904C836B5CD2D4DA5EAE38D /* CourseUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseUseCase.swift; sourceTree = ""; }; FD49F277B86481D3D105FAC8 /* Domain.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Domain.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -60,11 +66,21 @@ name = Products; sourceTree = ""; }; + 266DBF54466AF3D041290301 /* Extension */ = { + isa = PBXGroup; + children = ( + 2E1DA9A49E79A791F7A526A1 /* String+Extension.swift */, + ); + path = Extension; + sourceTree = ""; + }; 28B694539E22431DAF52B883 /* Sources */ = { isa = PBXGroup; children = ( + 266DBF54466AF3D041290301 /* Extension */, BC1A55AF7DC675AFEA6E7C12 /* RepositoryProtocol */, 2BE278B80FDD95404961E580 /* UseCase */, + 9C17CEB3595F4C3FA69C5BAF /* VO */, ); path = Sources; sourceTree = ""; @@ -72,6 +88,7 @@ 2BE278B80FDD95404961E580 /* UseCase */ = { isa = PBXGroup; children = ( + F904C836B5CD2D4DA5EAE38D /* CourseUseCase.swift */, ); path = UseCase; sourceTree = ""; @@ -93,10 +110,18 @@ name = Project; sourceTree = ""; }; + 9C17CEB3595F4C3FA69C5BAF /* VO */ = { + isa = PBXGroup; + children = ( + 747DBBCAB797E5E0A82177F2 /* CourseVO.swift */, + ); + path = VO; + sourceTree = ""; + }; BC1A55AF7DC675AFEA6E7C12 /* RepositoryProtocol */ = { isa = PBXGroup; children = ( - F05702E18938E331F26864D0 /* gitkeep.swift */, + DCA3E06ED2A8180A63919B6C /* CourseRepository.swift */, ); path = RepositoryProtocol; sourceTree = ""; @@ -139,6 +164,8 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; + TargetAttributes = { + }; }; buildConfigurationList = 5B17347D429F14C389327C78 /* Build configuration list for PBXProject "Domain" */; compatibilityVersion = "Xcode 14.0"; @@ -173,7 +200,10 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 850D3256EE250153F112D564 /* gitkeep.swift in Sources */, + 69DAD609572D32F2BA3845AE /* String+Extension.swift in Sources */, + D510BC17C4583615CB60439E /* CourseRepository.swift in Sources */, + BBED9ACB62B271298F7028F8 /* CourseUseCase.swift in Sources */, + 5EB8590C9D2C002D0BDBC021 /* CourseVO.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -347,7 +377,10 @@ SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( + "$(inherited)", + DEBUG, + ); SWIFT_COMPILATION_MODE = singlefile; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; diff --git a/Projects/Domain/Sources/Extension/String+Extension.swift b/Projects/Domain/Sources/Extension/String+Extension.swift new file mode 100644 index 0000000..2718f14 --- /dev/null +++ b/Projects/Domain/Sources/Extension/String+Extension.swift @@ -0,0 +1,18 @@ +// +// String+Extension.swift +// Domain +// +// Created by 박지윤 on 7/8/25. +// + +import Foundation + +extension String { + func formatDateString() -> String { + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" + guard let date = dateFormatter.date(from: self) else { return self } + dateFormatter.dateFormat = "yyyy년 MM월 dd일" + return dateFormatter.string(from: date) + } +} diff --git a/Projects/Domain/Sources/RepositoryProtocol/CourseRepository.swift b/Projects/Domain/Sources/RepositoryProtocol/CourseRepository.swift new file mode 100644 index 0000000..146d953 --- /dev/null +++ b/Projects/Domain/Sources/RepositoryProtocol/CourseRepository.swift @@ -0,0 +1,12 @@ +// +// CourseRepository.swift +// Domain +// +// Created by 박지윤 on 7/8/25. +// + +import RxSwift + +public protocol CourseRepository { + func getCourses() -> Single +} diff --git a/Projects/Domain/Sources/RepositoryProtocol/gitkeep.swift b/Projects/Domain/Sources/RepositoryProtocol/gitkeep.swift deleted file mode 100644 index 9be55b4..0000000 --- a/Projects/Domain/Sources/RepositoryProtocol/gitkeep.swift +++ /dev/null @@ -1,7 +0,0 @@ -// -// gitkeep.swift -// Domain -// -// Created by 박지윤 on 7/8/25. -// - diff --git a/Projects/Domain/Sources/UseCase/CourseUseCase.swift b/Projects/Domain/Sources/UseCase/CourseUseCase.swift new file mode 100644 index 0000000..6a5d396 --- /dev/null +++ b/Projects/Domain/Sources/UseCase/CourseUseCase.swift @@ -0,0 +1,24 @@ +// +// CourseUseCase.swift +// Domain +// +// Created by 박지윤 on 7/8/25. +// + +import RxSwift + +public protocol CourseUseCase { + func getCourses() -> Single +} + +public final class DefaultCourseUseCase: CourseUseCase { + let repository: CourseRepository + + public init(repository: CourseRepository) { + self.repository = repository + } + + public func getCourses() -> Single { + return repository.getCourses() + } +} diff --git a/Projects/Domain/Sources/VO/CourseVO.swift b/Projects/Domain/Sources/VO/CourseVO.swift new file mode 100644 index 0000000..b838ed3 --- /dev/null +++ b/Projects/Domain/Sources/VO/CourseVO.swift @@ -0,0 +1,32 @@ +// +// CourseVO.swift +// Domain +// +// Created by 박지윤 on 7/8/25. +// + +public struct HomeCourseVO { + public let list: [CourseVO] + + public init(list: [CourseVO]) { + self.list = list + } +} + +public struct CourseVO { + public let courseLv: Int? + public let courseDescription: String? + public let stepLv: Int? + public let stepTitle: String? + public let stepDescription: String? + public let stepStatus: String? + + public init(courseLv: Int?, courseDescription: String?, stepLv: Int?, stepTitle: String?, stepDescription: String?, stepStatus: String?) { + self.courseLv = courseLv + self.courseDescription = courseDescription + self.stepLv = stepLv + self.stepTitle = stepTitle + self.stepDescription = stepDescription + self.stepStatus = stepStatus + } +} diff --git a/Projects/Home/Sources/ViewModel/HomeViewModel.swift b/Projects/Home/Sources/ViewModel/HomeViewModel.swift index a7592d9..78bc57a 100644 --- a/Projects/Home/Sources/ViewModel/HomeViewModel.swift +++ b/Projects/Home/Sources/ViewModel/HomeViewModel.swift @@ -5,8 +5,27 @@ // Created by 박지윤 on 7/1/25. // -import Foundation +import Domain +import RxSwift -public class HomeViewModel { - public init() {} +protocol HomeViewModelProtocol { + func getCourses() +} + +public class HomeViewModel: HomeViewModelProtocol { + private let disposeBag = DisposeBag() + private let courseUseCase: CourseUseCase + public init(courseUseCase: CourseUseCase) { + self.courseUseCase = courseUseCase + getCourses() + } + + func getCourses() { + courseUseCase.getCourses() + .subscribe(onSuccess: { response in + print(response) + }, onFailure: { _ in + + }).disposed(by: disposeBag) + } } diff --git a/Projects/LearnMate/Derived/InfoPlists/LearnMateTests-Info.plist b/Projects/LearnMate/Derived/InfoPlists/LearnMateTests-Info.plist index 6c40a6c..1eed55f 100644 --- a/Projects/LearnMate/Derived/InfoPlists/LearnMateTests-Info.plist +++ b/Projects/LearnMate/Derived/InfoPlists/LearnMateTests-Info.plist @@ -2,6 +2,13 @@ + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable diff --git a/Projects/LearnMate/LearnMate.xcodeproj/project.pbxproj b/Projects/LearnMate/LearnMate.xcodeproj/project.pbxproj index f7d0301..34bde02 100644 --- a/Projects/LearnMate/LearnMate.xcodeproj/project.pbxproj +++ b/Projects/LearnMate/LearnMate.xcodeproj/project.pbxproj @@ -97,10 +97,10 @@ 42CABF80B6D6BC7DECCE8094 /* Chat.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Chat.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 4827AE49C7B9592C6AA4F708 /* AppCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCoordinator.swift; sourceTree = ""; }; 50486214C077FA786A3BE37D /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; - 596AE34B2413431CA8E09857 /* LearnMate-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "LearnMate-Info.plist"; sourceTree = ""; }; 626AE29E08BEF53B78AA9179 /* Common.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Common.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 69B232119647519D26142C64 /* Then.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Then.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 7459B5071C1C3E12A6519672 /* Diary.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Diary.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 75AF6F9390E20101F1F4BFB3 /* LearnMate-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "LearnMate-Info.plist"; sourceTree = ""; }; 775DFA54CE473464C0AC8D57 /* LearnMateTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "LearnMateTests-Info.plist"; sourceTree = ""; }; 7C422FE2DDF9127C2F4B2DF0 /* RxSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RxSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 89F58ED76FC4C0973305766F /* DependencyInjector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DependencyInjector.swift; sourceTree = ""; }; @@ -152,10 +152,17 @@ path = Sources; sourceTree = ""; }; + 1E95FEDCBD464D7BF64D5488 /* Support */ = { + isa = PBXGroup; + children = ( + 75AF6F9390E20101F1F4BFB3 /* LearnMate-Info.plist */, + ); + path = Support; + sourceTree = ""; + }; 2CE74D9D55F5B62BE83D0A4B /* InfoPlists */ = { isa = PBXGroup; children = ( - 596AE34B2413431CA8E09857 /* LearnMate-Info.plist */, 775DFA54CE473464C0AC8D57 /* LearnMateTests-Info.plist */, ); path = InfoPlists; @@ -174,6 +181,7 @@ children = ( 3A71D5C5E07EF937467BAF41 /* Derived */, 02DEB0AB87622688EABA33D7 /* Sources */, + 1E95FEDCBD464D7BF64D5488 /* Support */, ); name = Project; sourceTree = ""; @@ -378,7 +386,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_IDENTITY = "iPhone Developer"; ENABLE_PREVIEWS = YES; - INFOPLIST_FILE = "Derived/InfoPlists/LearnMate-Info.plist"; + INFOPLIST_FILE = "Support/LearnMate-Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -403,7 +411,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_IDENTITY = "iPhone Developer"; ENABLE_PREVIEWS = YES; - INFOPLIST_FILE = "Derived/InfoPlists/LearnMate-Info.plist"; + INFOPLIST_FILE = "Support/LearnMate-Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/Projects/LearnMate/Project.swift b/Projects/LearnMate/Project.swift index c169b6c..63ee577 100644 --- a/Projects/LearnMate/Project.swift +++ b/Projects/LearnMate/Project.swift @@ -8,14 +8,7 @@ let project = Project( destinations: .iOS, product: .app, bundleId: "io.tuist.LearnMate", - infoPlist: .extendingDefault( - with: [ - "UILaunchScreen": [ - "UIColorName": "", - "UIImageName": "", - ], - ] - ), + infoPlist: .file(path: "Support/LearnMate-Info.plist"), sources: ["Sources/**"], resources: ["Resources/**"], dependencies: [ diff --git a/Projects/LearnMate/Sources/Application/SceneDelegate.swift b/Projects/LearnMate/Sources/Application/SceneDelegate.swift index 8dfdbcf..77ef709 100644 --- a/Projects/LearnMate/Sources/Application/SceneDelegate.swift +++ b/Projects/LearnMate/Sources/Application/SceneDelegate.swift @@ -28,7 +28,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { /// AppCoordinator 실행 appCoordinator = DefaultAppCoordinator(dependency: .init(navigationController: navigationController, injector: injector)) - injector.assemble([HomeAssembly()]) + injector.assemble([DataAssembly(), + DomainAssembly(), + HomeAssembly()]) appCoordinator?.start() } diff --git a/Projects/LearnMate/Sources/Coordinator/AppCoordinator.swift b/Projects/LearnMate/Sources/Coordinator/AppCoordinator.swift index c5d748d..f8223f7 100644 --- a/Projects/LearnMate/Sources/Coordinator/AppCoordinator.swift +++ b/Projects/LearnMate/Sources/Coordinator/AppCoordinator.swift @@ -49,7 +49,7 @@ final class DefaultAppCoordinator: AppCoordinator{ func setTabBarCoordinator() { let dependency = DefaultTabBarController.Dependency.init( navigationController: navigationController, - homeViewController: dependency.injector.resolve(HomeViewController.self), + injector: dependency.injector, finishDelegate: self) let tabBarCoordinator = DefaultTabBarController(dependency: dependency) childCoordinators.append(tabBarCoordinator) diff --git a/Projects/LearnMate/Sources/Coordinator/TabBarCoordinator.swift b/Projects/LearnMate/Sources/Coordinator/TabBarCoordinator.swift index 0b534ba..691e3d2 100644 --- a/Projects/LearnMate/Sources/Coordinator/TabBarCoordinator.swift +++ b/Projects/LearnMate/Sources/Coordinator/TabBarCoordinator.swift @@ -16,7 +16,7 @@ protocol TabBarCoordinator: Coordinator { final class DefaultTabBarController: TabBarCoordinator { public struct Dependency { let navigationController: UINavigationController - let homeViewController: HomeViewController + let injector: Injector weak var finishDelegate: CoordinatorFinishDelegate? } @@ -70,7 +70,7 @@ final class DefaultTabBarController: TabBarCoordinator { switch page { case .home: // 추후 homeCoordinator 로 변경 - let homeViewController = dependency.homeViewController + let homeViewController = dependency.injector.resolve(HomeViewController.self) tabNavigationController.pushViewController(homeViewController, animated: true) default: let viewController = UIViewController() diff --git a/Projects/LearnMate/Sources/DI/DataAssembly.swift b/Projects/LearnMate/Sources/DI/DataAssembly.swift index 70d62ce..4a3bb0d 100644 --- a/Projects/LearnMate/Sources/DI/DataAssembly.swift +++ b/Projects/LearnMate/Sources/DI/DataAssembly.swift @@ -5,3 +5,14 @@ // Created by 박지윤 on 7/2/25. // +import Swinject +import Domain +import Data + +public struct DataAssembly: Assembly { + public func assemble(container: Container) { + container.register(CourseRepository.self) { _ in + return DefaultCourseRepository() + } + } +} diff --git a/Projects/LearnMate/Sources/DI/DomainAssembly.swift b/Projects/LearnMate/Sources/DI/DomainAssembly.swift index 4f1215a..8a6aedf 100644 --- a/Projects/LearnMate/Sources/DI/DomainAssembly.swift +++ b/Projects/LearnMate/Sources/DI/DomainAssembly.swift @@ -5,3 +5,14 @@ // Created by 박지윤 on 7/2/25. // +import Domain +import Swinject + +public struct DomainAssembly: Assembly { + public func assemble(container: Container) { + container.register(CourseUseCase.self) { resolver in + let repository = resolver.resolve(CourseRepository.self)! + return DefaultCourseUseCase(repository: repository) + } + } +} diff --git a/Projects/LearnMate/Sources/DI/HomeAssembly.swift b/Projects/LearnMate/Sources/DI/HomeAssembly.swift index 3107ab6..bd0e47c 100644 --- a/Projects/LearnMate/Sources/DI/HomeAssembly.swift +++ b/Projects/LearnMate/Sources/DI/HomeAssembly.swift @@ -7,14 +7,16 @@ import Swinject import Home +import Domain /// Assembly: Swinject의 DI 등록을 위한 프로토콜 public struct HomeAssembly: Assembly { /// assemble(container:): 어떤 객체를 어떻게 등록할지 정의 public func assemble(container: Container) { /// HomeViewModel을 DI 컨테이너에 등록 - container.register(HomeViewModel.self) { _ in - return HomeViewModel() + container.register(HomeViewModel.self) { resolver in + let useCase = resolver.resolve(CourseUseCase.self)! + return HomeViewModel(courseUseCase: useCase) } /// ViewModel을 DI 통해 주입받아 Controller를 생성함 diff --git a/Projects/LearnMate/Derived/InfoPlists/LearnMate-Info.plist b/Projects/LearnMate/Support/LearnMate-Info.plist similarity index 100% rename from Projects/LearnMate/Derived/InfoPlists/LearnMate-Info.plist rename to Projects/LearnMate/Support/LearnMate-Info.plist diff --git a/Projects/LearnMate/Support/LearnMateTests-Info.plist b/Projects/LearnMate/Support/LearnMateTests-Info.plist new file mode 100644 index 0000000..6c40a6c --- /dev/null +++ b/Projects/LearnMate/Support/LearnMateTests-Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/Projects/Stats/Stats.xcodeproj/project.pbxproj b/Projects/Stats/Stats.xcodeproj/project.pbxproj index 25b9eb9..749c48c 100644 --- a/Projects/Stats/Stats.xcodeproj/project.pbxproj +++ b/Projects/Stats/Stats.xcodeproj/project.pbxproj @@ -3,10 +3,11 @@ archiveVersion = 1; classes = { }; - objectVersion = 56; + objectVersion = 55; objects = { /* Begin PBXBuildFile section */ + 0EE277B79FBEC34A0544D11A /* StatsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 262C32C6D896BB95974278B9 /* StatsTests.swift */; }; 4B6D51F363D1279B180CF8AA /* RxSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9F5C919B7ADBE7CF891BA91 /* RxSwift.framework */; }; 60ADBBB18C4595891176CC90 /* SnapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B94183B28A8C793642DADC39 /* SnapKit.framework */; }; 60FC5FABF42F5D852F89D053 /* CommonUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2AB70B6EFD6D585A83AADB33 /* CommonUI.framework */; }; @@ -14,6 +15,7 @@ B54E8B37C084373CD92B1965 /* Then.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5729434906CF79F7287DD44 /* Then.framework */; }; D43C7F6C1BB124AFC899FA58 /* Domain.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 590AF65626975F119779B7A1 /* Domain.framework */; }; D7374FD2F5A0B7E0F9FBB33D /* Stats.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 037FBEBD55D0F5F6D1D4A147 /* Stats.framework */; }; + EFDF35B300015A4D70E939B4 /* gitkeep.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFA3148B805294B3A9B81125 /* gitkeep.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -51,17 +53,16 @@ /* Begin PBXFileReference section */ 037FBEBD55D0F5F6D1D4A147 /* Stats.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Stats.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 262C32C6D896BB95974278B9 /* StatsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsTests.swift; sourceTree = ""; }; 2AB70B6EFD6D585A83AADB33 /* CommonUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CommonUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 590AF65626975F119779B7A1 /* Domain.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Domain.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 79D14B0C00FE4123C84634BC /* Stats-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "Stats-Info.plist"; sourceTree = ""; }; 80D329EB884528FE8A6AE0DC /* Common.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Common.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 884D719A849321C4DC3818F8 /* StatsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = StatsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 959AFCC22E1CB930006F9875 /* StatsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsTests.swift; sourceTree = ""; }; - 959AFCC32E1CB93F006F9875 /* gitkeep.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = gitkeep.swift; sourceTree = ""; }; - 959AFCC42E1CB944006F9875 /* gitkeep.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = gitkeep.swift; sourceTree = ""; }; B40D4CD15BA07E7522946E48 /* StatsTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "StatsTests-Info.plist"; sourceTree = ""; }; B5729434906CF79F7287DD44 /* Then.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Then.framework; sourceTree = BUILT_PRODUCTS_DIR; }; B94183B28A8C793642DADC39 /* SnapKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SnapKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + EFA3148B805294B3A9B81125 /* gitkeep.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = gitkeep.swift; sourceTree = ""; }; F9F5C919B7ADBE7CF891BA91 /* RxSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RxSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -90,6 +91,14 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 301777750BDAD37E3EF02CA5 /* Tests */ = { + isa = PBXGroup; + children = ( + 262C32C6D896BB95974278B9 /* StatsTests.swift */, + ); + path = Tests; + sourceTree = ""; + }; 833F2882CD758C44D17ACD6A /* Derived */ = { isa = PBXGroup; children = ( @@ -113,37 +122,12 @@ name = Products; sourceTree = ""; }; - 959AFCBF2E1CB927006F9875 /* Resources */ = { - isa = PBXGroup; - children = ( - 959AFCC32E1CB93F006F9875 /* gitkeep.swift */, - ); - path = Resources; - sourceTree = ""; - }; - 959AFCC02E1CB927006F9875 /* Sources */ = { - isa = PBXGroup; - children = ( - 959AFCC42E1CB944006F9875 /* gitkeep.swift */, - ); - path = Sources; - sourceTree = ""; - }; - 959AFCC12E1CB92D006F9875 /* Tests */ = { - isa = PBXGroup; - children = ( - 959AFCC22E1CB930006F9875 /* StatsTests.swift */, - ); - path = Tests; - sourceTree = ""; - }; C8FA3CF6603247F95E25F16D /* Project */ = { isa = PBXGroup; children = ( - 959AFCC12E1CB92D006F9875 /* Tests */, - 959AFCBF2E1CB927006F9875 /* Resources */, - 959AFCC02E1CB927006F9875 /* Sources */, 833F2882CD758C44D17ACD6A /* Derived */, + FD7043E7B0B739FCCC6D354B /* Sources */, + 301777750BDAD37E3EF02CA5 /* Tests */, ); name = Project; sourceTree = ""; @@ -165,6 +149,14 @@ path = InfoPlists; sourceTree = ""; }; + FD7043E7B0B739FCCC6D354B /* Sources */ = { + isa = PBXGroup; + children = ( + EFA3148B805294B3A9B81125 /* gitkeep.swift */, + ); + path = Sources; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -216,6 +208,8 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; + TargetAttributes = { + }; }; buildConfigurationList = 30FAB7D7FD2305E862A6285C /* Build configuration list for PBXProject "Stats" */; compatibilityVersion = "Xcode 14.0"; @@ -258,6 +252,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + EFDF35B300015A4D70E939B4 /* gitkeep.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -265,6 +260,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 0EE277B79FBEC34A0544D11A /* StatsTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -303,7 +299,10 @@ SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( + "$(inherited)", + DEBUG, + ); SWIFT_COMPILATION_MODE = singlefile; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -464,7 +463,10 @@ SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( + "$(inherited)", + DEBUG, + ); SWIFT_COMPILATION_MODE = singlefile; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0;