diff --git a/HMH_Tuist_iOS/HMH-Tuist-iOS.xcworkspace/xcshareddata/xcschemes/HMH-Tuist-iOS-Workspace.xcscheme b/HMH_Tuist_iOS/HMH-Tuist-iOS.xcworkspace/xcshareddata/xcschemes/HMH-Tuist-iOS-Workspace.xcscheme
index 6ed3f320..28e3f59c 100644
--- a/HMH_Tuist_iOS/HMH-Tuist-iOS.xcworkspace/xcshareddata/xcschemes/HMH-Tuist-iOS-Workspace.xcscheme
+++ b/HMH_Tuist_iOS/HMH-Tuist-iOS.xcworkspace/xcshareddata/xcschemes/HMH-Tuist-iOS-Workspace.xcscheme
@@ -62,20 +62,6 @@
ReferencedContainer = "container:Projects/Features/ChallengeFeature/ChallengeFeature.xcodeproj">
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
ProjectDescription.Path {
+ .relativeToRoot("./XCConfig/\(target.rawValue).xcconfig")
+ }
+
+ public static let configurations: [Configuration] = [
+ .build(.dev),
+ .build(.qa),
+ .build(.prod)
+ ]
+}
+
+public enum BuildTarget: String {
+ case dev = "DEV"
+ case qa = "QA"
+ case prod = "PROD"
+}
+
+public extension Configuration {
+ static func build(_ target: BuildTarget) -> Self {
+ switch target {
+ case .dev:
+ return .debug(
+ name: "Development",
+ xcconfig: XCConfig.path(for: .dev)
+ )
+ case .qa:
+ return .release(
+ name: "QA",
+ xcconfig: XCConfig.path(for: .qa)
+ )
+ case .prod:
+ return .release(
+ name: "PROD",
+ xcconfig: XCConfig.path(for: .prod)
+ )
+ }
+ }
+}
+
+//
+// Configurations.swift
+// MyPlugin
+//
+// Created by 류희재 on 7/13/24.
+//
+
+import Foundation
+import ProjectDescription
+
+/// 빌드할 환경에 대한 설정
+
+/// Target 분리 (The Modular Architecture 기반으로 분리했습니다)
+
+
/// DEV : 실제 프로덕트 BaseURL을 사용하는 debug scheme
/// TEST : 테스트 BaseURL을 사용하는 debug scheme
/// QA : 테스트 BaseURL을 사용하는 release scheme
@@ -23,38 +81,45 @@ import ProjectDescription
/// 2) TEST, QA -> 테스트 BaseURL
-public struct XCConfig {
- private struct Path {
- static var framework: ProjectDescription.Path { .relativeToRoot("Configurations/Targets/iOS-Framework.xcconfig") }
- static var demo: ProjectDescription.Path { .relativeToRoot("Configurations/Targets/iOS-Demo.xcconfig") }
- static var tests: ProjectDescription.Path { .relativeToRoot("Configurations/Targets/iOS-Tests.xcconfig") }
- static func project(_ config: String) -> ProjectDescription.Path { .relativeToRoot("Configurations/Base/Projects/Project-\(config).xcconfig") }
- }
-
- public static let framework: [Configuration] = [
- .debug(name: "Development", xcconfig: Path.framework),
- .debug(name: "Test", xcconfig: Path.framework),
- .release(name: "QA", xcconfig: Path.framework),
- .release(name: "PROD", xcconfig: Path.framework),
- ]
-
- public static let tests: [Configuration] = [
- .debug(name: "Development", xcconfig: Path.tests),
- .debug(name: "Test", xcconfig: Path.tests),
- .release(name: "QA", xcconfig: Path.tests),
- .release(name: "PROD", xcconfig: Path.tests),
- ]
- public static let demo: [Configuration] = [
- .debug(name: "Development", xcconfig: Path.demo),
- .debug(name: "Test", xcconfig: Path.demo),
- .release(name: "QA", xcconfig: Path.demo),
- .release(name: "PROD", xcconfig: Path.demo),
- ]
- public static let project: [Configuration] = [
- .debug(name: "Development", xcconfig: Path.project("Development")),
- .debug(name: "Test", xcconfig: Path.project("Test")),
- .release(name: "QA", xcconfig: Path.project("QA")),
- .release(name: "PROD", xcconfig: Path.project("PROD")),
- ]
-}
-
+//public struct XCConfig {
+// private struct Path {
+// static var framework: ProjectDescription.Path { .relativeToRoot("Configurations/Targets/iOS-Framework.xcconfig") }
+// static var demo: ProjectDescription.Path { .relativeToRoot("Configurations/Targets/iOS-Demo.xcconfig") }
+// static var tests: ProjectDescription.Path { .relativeToRoot("Configurations/Targets/iOS-Tests.xcconfig") }
+// static func project(_ config: String) -> ProjectDescription.Path { .relativeToRoot("Configurations/Base/Projects/Project-\(config).xcconfig") }
+// }
+//
+// public static let framework: [Configuration] = [
+// .debug(name: "Development", xcconfig: .relativeToRoot("XCConfig/DEV.xcconfig")),
+// .release(name: "PROD", xcconfig: .relativeToRoot("XCConfig/PROD.xcconfig"))
+//// .debug(name: "Development", xcconfig: Path.framework),
+//// .debug(name: "Test", xcconfig: Path.framework),
+//// .release(name: "QA", xcconfig: Path.framework),
+//// .release(name: "PROD", xcconfig: Path.framework),
+// ]
+//
+// public static let tests: [Configuration] = [
+// .debug(name: "Development", xcconfig: .relativeToRoot("XCConfig/DEV.xcconfig")),
+// .release(name: "PROD", xcconfig: .relativeToRoot("XCConfig/PROD.xcconfig"))
+//// .debug(name: "Development", xcconfig: Path.tests),
+////// .debug(name: "Test", xcconfig: Path.tests),
+////// .release(name: "QA", xcconfig: Path.tests),
+//// .release(name: "PROD", xcconfig: Path.tests),
+// ]
+// public static let demo: [Configuration] = [
+// .debug(name: "Development", xcconfig: .relativeToRoot("XCConfig/DEV.xcconfig")),
+// .release(name: "PROD", xcconfig: .relativeToRoot("XCConfig/PROD.xcconfig"))
+//// .debug(name: "Development", xcconfig: Path.demo),
+////// .debug(name: "Test", xcconfig: Path.demo),
+////// .release(name: "QA", xcconfig: Path.demo),
+//// .release(name: "PROD", xcconfig: Path.demo),
+// ]
+// public static let project: [Configuration] = [
+// .debug(name: "Development", xcconfig: .relativeToRoot("XCConfig/DEV.xcconfig")),
+// .release(name: "PROD", xcconfig: .relativeToRoot("XCConfig/PROD.xcconfig"))
+//// .debug(name: "Development", xcconfig: Path.project("Development")),
+////// .debug(name: "Test", xcconfig: Path.project("Test")),
+////// .release(name: "QA", xcconfig: Path.project("QA")),
+//// .release(name: "PROD", xcconfig: Path.project("PROD")),
+// ]
+//}
diff --git a/HMH_Tuist_iOS/Plugins/EnvPlugin/ProjectDescriptionHelpers/SettingDictionary+.swift b/HMH_Tuist_iOS/Plugins/EnvPlugin/ProjectDescriptionHelpers/SettingDictionary+.swift
index 3318a9e7..7dd53b79 100644
--- a/HMH_Tuist_iOS/Plugins/EnvPlugin/ProjectDescriptionHelpers/SettingDictionary+.swift
+++ b/HMH_Tuist_iOS/Plugins/EnvPlugin/ProjectDescriptionHelpers/SettingDictionary+.swift
@@ -18,6 +18,8 @@ public extension SettingsDictionary {
]
]
+ ///역할: Objective-C 카테고리 및 클래스를 정적으로 링크하도록 보장.
+ ///사용 사례: Objective-C 기반 라이브러리를 사용할 때 기본적으로 필요.
static let baseSettings: Self = [
"OTHER_LDFLAGS" : [
"$(inherited)",
@@ -25,48 +27,59 @@ public extension SettingsDictionary {
]
]
+ ///번들 ID를 설정합니다.
func setProductBundleIdentifier(_ value: String = "com.iOS$(BUNDLE_ID_SUFFIX)") -> SettingsDictionary {
merging(["PRODUCT_BUNDLE_IDENTIFIER": SettingValue(stringLiteral: value)])
}
+ ///앱 아이콘 이름을 설정합니다.
func setAssetcatalogCompilerAppIconName(_ value: String = "AppIcon$(BUNDLE_ID_SUFFIX)") -> SettingsDictionary {
merging(["ASSETCATALOG_COMPILER_APPICON_NAME": SettingValue(stringLiteral: value)])
}
+ ///활성화된 아키텍처만 빌드할지 설정 (ONLY_ACTIVE_ARCH).
func setBuildActiveArchitectureOnly(_ value: Bool) -> SettingsDictionary {
merging(["ONLY_ACTIVE_ARCH": SettingValue(stringLiteral: value ? "YES" : "NO")])
}
+ ///특정 SDK에서 제외할 아키텍처를 설정 (EXCLUDED_ARCHS).
func setExcludedArchitectures(sdk: String = "iphonesimulator*", _ value: String = "arm64") -> SettingsDictionary {
merging(["EXCLUDED_ARCHS[sdk=\(sdk)]": SettingValue(stringLiteral: value)])
}
+ ///Swift 활성 컴파일 조건을 설정 (SWIFT_ACTIVE_COMPILATION_CONDITIONS).
func setSwiftActiveComplationConditions(_ value: String) -> SettingsDictionary {
merging(["SWIFT_ACTIVE_COMPILATION_CONDITIONS": SettingValue(stringLiteral: value)])
}
+ ///사용자 경로를 항상 검색할지 설정 (ALWAYS_SEARCH_USER_PATHS).
func setAlwaysSearchUserPath(_ value: String = "NO") -> SettingsDictionary {
merging(["ALWAYS_SEARCH_USER_PATHS": SettingValue(stringLiteral: value)])
}
+ ///복사 과정에서 디버그 심볼 제거 여부를 설정 (COPY_PHASE_STRIP).
func setStripDebugSymbolsDuringCopy(_ value: String = "NO") -> SettingsDictionary {
merging(["COPY_PHASE_STRIP": SettingValue(stringLiteral: value)])
}
+ ///동적 라이브러리 기본 설치 경로 설정 (DYLIB_INSTALL_NAME_BASE).
func setDynamicLibraryInstallNameBase(_ value: String = "@rpath") -> SettingsDictionary {
merging(["DYLIB_INSTALL_NAME_BASE": SettingValue(stringLiteral: value)])
}
+ ///설치 대상 여부를 설정 (SKIP_INSTALL).
func setSkipInstall(_ value: Bool = false) -> SettingsDictionary {
merging(["SKIP_INSTALL": SettingValue(stringLiteral: value ? "YES" : "NO")])
}
+ ///코드 서명을 수동으로 설정합니다.
func setCodeSignManual() -> SettingsDictionary {
merging(["CODE_SIGN_STYLE": SettingValue(stringLiteral: "Manual")])
.merging(["DEVELOPMENT_TEAM": SettingValue(stringLiteral: "9K86FQHDLU")])
.merging(["CODE_SIGN_IDENTITY": SettingValue(stringLiteral: "$(CODE_SIGN_IDENTITY)")])
}
+ ///프로비저닝 프로파일 설정.
func setProvisioning() -> SettingsDictionary {
merging(["PROVISIONING_PROFILE_SPECIFIER": SettingValue(stringLiteral: "$(APP_PROVISIONING_PROFILE)")])
.merging(["PROVISIONING_PROFILE": SettingValue(stringLiteral: "$(APP_PROVISIONING_PROFILE)")])
diff --git a/HMH_Tuist_iOS/Projects/App/Derived/InfoPlists/HMH-iOS-Info.plist b/HMH_Tuist_iOS/Projects/App/Derived/InfoPlists/HMH-iOS-Info.plist
index a3d5de43..a58e1a02 100644
--- a/HMH_Tuist_iOS/Projects/App/Derived/InfoPlists/HMH-iOS-Info.plist
+++ b/HMH_Tuist_iOS/Projects/App/Derived/InfoPlists/HMH-iOS-Info.plist
@@ -2,75 +2,87 @@
- BASE_URL
- $(BASE_URL)
- BGTaskSchedulerPermittedIdentifiers
-
- com.HMH.dailyTask
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- 1.0
- CFBundleURLTypes
-
-
- CFBundleTypeRole
- Editor
- CFBundleURLSchemes
-
- kakao$(KAKAO_API_KEY)
-
-
-
- CFBundleVersion
- 1
- KAKAO_API_KEY
- $(KAKAO_API_KEY)
- LSApplicationQueriesSchemes
-
- kakaokompassauth
- kakaolink
-
- LSRequiresIPhoneOS
-
- NSAppTransportSecurity
-
- NSAllowsArbitraryLoads
-
-
- UIAppFonts
-
- Pretendard-Regular.otf
- Pretendard-SemiBold.otf
- Pretendard-Medium.otf
-
- UIApplicationSceneManifest
-
- UIApplicationSupportsMultipleScenes
-
- UISceneConfigurations
-
-
- UIRequiredDeviceCapabilities
-
- armv7
-
- UISupportedInterfaceOrientations
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
+ BASE_URL
+ $(BASE_URL)
+ BGTaskSchedulerPermittedIdentifiers
+
+ com.HMH.dailyTask
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleURLTypes
+
+
+ CFBundleTypeRole
+ Editor
+ CFBundleURLSchemes
+
+ kakao$(KAKAO_API_KEY)
+
+
+
+ CFBundleVersion
+ 1
+ KAKAO_API_KEY
+ $(KAKAO_API_KEY)
+ LSApplicationQueriesSchemes
+
+ kakaokompassauth
+ kakaolink
+
+ LSRequiresIPhoneOS
+
+ NSAppTransportSecurity
+
+ NSAllowsArbitraryLoads
+
+
+ UIAppFonts
+
+ Pretendard-Regular.otf
+ Pretendard-SemiBold.otf
+ Pretendard-Medium.otf
+
+ UIApplicationSceneManifest
+
+ UIApplicationSupportsMultipleScenes
+
+ UISceneConfigurations
+
+ UIWindowSceneSessionRoleApplication
+
+
+ UISceneConfigurationName
+ Default Configuration
+ UISceneDelegateClassName
+ $(PRODUCT_MODULE_NAME).SceneDelegate
+
+
+
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIRequiredDeviceCapabilities
+
+ armv7
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
diff --git a/HMH_Tuist_iOS/Projects/Core/Sources/Extension/Date+.swift b/HMH_Tuist_iOS/Projects/Core/Sources/Extension/Date+.swift
index eac0649e..d0486e5b 100644
--- a/HMH_Tuist_iOS/Projects/Core/Sources/Extension/Date+.swift
+++ b/HMH_Tuist_iOS/Projects/Core/Sources/Extension/Date+.swift
@@ -21,4 +21,20 @@ public extension String {
formatter.dateFormat = format
return formatter.date(from: self)
}
+
+
+ func challengeHeaderFormattd() -> String? {
+ let inputDateFormatter = DateFormatter()
+ inputDateFormatter.dateFormat = "yyyy-MM-dd"
+ guard let date = inputDateFormatter.date(from: self) else {
+ return nil
+ }
+
+ let outputDateFormatter = DateFormatter()
+ outputDateFormatter.dateFormat = "M월 d일"
+ let formattedDateString = outputDateFormatter.string(from: date)
+
+ return formattedDateString
+ }
+
}
diff --git a/HMH_Tuist_iOS/Projects/Features/HomeFeature/Derived/InfoPlists/HomeFeatureInterface-Info.plist b/HMH_Tuist_iOS/Projects/Data/Derived/InfoPlists/DataTests-Info.plist
similarity index 96%
rename from HMH_Tuist_iOS/Projects/Features/HomeFeature/Derived/InfoPlists/HomeFeatureInterface-Info.plist
rename to HMH_Tuist_iOS/Projects/Data/Derived/InfoPlists/DataTests-Info.plist
index 323e5ecf..6c40a6cd 100644
--- a/HMH_Tuist_iOS/Projects/Features/HomeFeature/Derived/InfoPlists/HomeFeatureInterface-Info.plist
+++ b/HMH_Tuist_iOS/Projects/Data/Derived/InfoPlists/DataTests-Info.plist
@@ -13,7 +13,7 @@
CFBundleName
$(PRODUCT_NAME)
CFBundlePackageType
- FMWK
+ BNDL
CFBundleShortVersionString
1.0
CFBundleVersion
diff --git a/HMH_Tuist_iOS/Projects/Data/Project.swift b/HMH_Tuist_iOS/Projects/Data/Project.swift
index b842c871..e59430ca 100644
--- a/HMH_Tuist_iOS/Projects/Data/Project.swift
+++ b/HMH_Tuist_iOS/Projects/Data/Project.swift
@@ -11,7 +11,7 @@ import DependencyPlugin
let project = Project.makeModule(
name: "Data",
- targets: [.staticFramework, .demo],
+ targets: [.staticFramework, .demo, .unitTest],
internalDependencies: [
.domain,
.Modules.networks
diff --git a/HMH_Tuist_iOS/Projects/Data/Sources/Mapper/Challenge/ChallengeSuccessInfoMapper.swift b/HMH_Tuist_iOS/Projects/Data/Sources/Mapper/Challenge/ChallengeSuccessInfoMapper.swift
new file mode 100644
index 00000000..4fc8636b
--- /dev/null
+++ b/HMH_Tuist_iOS/Projects/Data/Sources/Mapper/Challenge/ChallengeSuccessInfoMapper.swift
@@ -0,0 +1,24 @@
+//
+// DailyChallengeTransform.swift
+// Data
+//
+// Created by 류희재 on 10/29/24.
+// Copyright © 2024 HMH-iOS. All rights reserved.
+//
+
+import Foundation
+
+import Domain
+import Networks
+
+extension FinishedDailyChallenge {
+ func toEntity() -> ChallengeSuccessInfo {
+ return .init(challengeDate: challengeDate, isSuccess: isSuccess)
+ }
+}
+
+extension ChallengeSuccessInfo {
+ func toDTO() -> FinishedDailyChallenge {
+ return .init(challengeDate: challengeDate, isSuccess: isSuccess)
+ }
+}
diff --git a/HMH_Tuist_iOS/Projects/Data/Sources/Mapper/Challenge/DailyChallengeInfoMapper.swift b/HMH_Tuist_iOS/Projects/Data/Sources/Mapper/Challenge/DailyChallengeInfoMapper.swift
index abd3b747..385207e9 100644
--- a/HMH_Tuist_iOS/Projects/Data/Sources/Mapper/Challenge/DailyChallengeInfoMapper.swift
+++ b/HMH_Tuist_iOS/Projects/Data/Sources/Mapper/Challenge/DailyChallengeInfoMapper.swift
@@ -1,18 +1,20 @@
//
-// DailyChallengeTransform.swift
+// HomeChallengeDetailMapper.swift
// Data
//
-// Created by 류희재 on 10/29/24.
+// Created by 류희재 on 11/5/24.
// Copyright © 2024 HMH-iOS. All rights reserved.
//
-import Foundation
-
import Domain
import Networks
-extension FinishedDailyChallenge {
- func toEntity() -> DailyChallengeInfo {
- return .init(challengeDate: challengeDate, isSuccess: isSuccess)
+extension DailyChallengeResult {
+ public func toEntity() -> DailyChallengeInfo {
+ .init(
+ status: status,
+ goalTime: goalTime,
+ apps: apps.map { $0.toEntity() }
+ )
}
}
diff --git a/HMH_Tuist_iOS/Projects/Data/Sources/Mapper/ErrorMapper.swift b/HMH_Tuist_iOS/Projects/Data/Sources/Mapper/ErrorMapper.swift
index bc1a4b2b..10f71bd0 100644
--- a/HMH_Tuist_iOS/Projects/Data/Sources/Mapper/ErrorMapper.swift
+++ b/HMH_Tuist_iOS/Projects/Data/Sources/Mapper/ErrorMapper.swift
@@ -15,11 +15,20 @@ import Networks
extension Publisher where Failure == HMHNetworkError {
func mapToDomainError(to errorType: T.Type) -> AnyPublisher