Skip to content

Commit 306f3e5

Browse files
committed
코어데이터에 String으로 저장하던 Timestamp 값을 Date로 변경
- 위젯에서 필요한 날짜 범위만큼 값을 가져오기위해 Timestamp 값을 date로 변경함. - string으로 테스트 하던 부분 모두 수정
1 parent f0b7e20 commit 306f3e5

File tree

11 files changed

+203
-46
lines changed

11 files changed

+203
-46
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Scheme
3+
LastUpgradeVersion = "1500"
4+
version = "1.7">
5+
<BuildAction
6+
parallelizeBuildables = "YES"
7+
buildImplicitDependencies = "YES">
8+
<BuildActionEntries>
9+
<BuildActionEntry
10+
buildForTesting = "YES"
11+
buildForRunning = "YES"
12+
buildForProfiling = "YES"
13+
buildForArchiving = "YES"
14+
buildForAnalyzing = "YES">
15+
<BuildableReference
16+
BuildableIdentifier = "primary"
17+
BlueprintIdentifier = "7B11F8232B4549DF00346A41"
18+
BuildableName = "PlantingMind.app"
19+
BlueprintName = "PlantingMind"
20+
ReferencedContainer = "container:PlantingMind.xcodeproj">
21+
</BuildableReference>
22+
</BuildActionEntry>
23+
</BuildActionEntries>
24+
</BuildAction>
25+
<TestAction
26+
buildConfiguration = "Debug"
27+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
28+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29+
shouldUseLaunchSchemeArgsEnv = "YES"
30+
shouldAutocreateTestPlan = "YES">
31+
</TestAction>
32+
<LaunchAction
33+
buildConfiguration = "Debug"
34+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
35+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
36+
launchStyle = "0"
37+
useCustomWorkingDirectory = "NO"
38+
ignoresPersistentStateOnLaunch = "NO"
39+
debugDocumentVersioning = "YES"
40+
debugServiceExtension = "internal"
41+
allowLocationSimulation = "YES">
42+
<BuildableProductRunnable
43+
runnableDebuggingMode = "0">
44+
<BuildableReference
45+
BuildableIdentifier = "primary"
46+
BlueprintIdentifier = "7B11F8232B4549DF00346A41"
47+
BuildableName = "PlantingMind.app"
48+
BlueprintName = "PlantingMind"
49+
ReferencedContainer = "container:PlantingMind.xcodeproj">
50+
</BuildableReference>
51+
</BuildableProductRunnable>
52+
</LaunchAction>
53+
<ProfileAction
54+
buildConfiguration = "Release"
55+
shouldUseLaunchSchemeArgsEnv = "YES"
56+
savedToolIdentifier = ""
57+
useCustomWorkingDirectory = "NO"
58+
debugDocumentVersioning = "YES">
59+
<BuildableProductRunnable
60+
runnableDebuggingMode = "0">
61+
<BuildableReference
62+
BuildableIdentifier = "primary"
63+
BlueprintIdentifier = "7B11F8232B4549DF00346A41"
64+
BuildableName = "PlantingMind.app"
65+
BlueprintName = "PlantingMind"
66+
ReferencedContainer = "container:PlantingMind.xcodeproj">
67+
</BuildableReference>
68+
</BuildableProductRunnable>
69+
</ProfileAction>
70+
<AnalyzeAction
71+
buildConfiguration = "Debug">
72+
</AnalyzeAction>
73+
<ArchiveAction
74+
buildConfiguration = "Release"
75+
revealArchiveInOrganizer = "YES">
76+
</ArchiveAction>
77+
</Scheme>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Scheme
3+
LastUpgradeVersion = "1500"
4+
version = "1.7">
5+
<BuildAction
6+
parallelizeBuildables = "YES"
7+
buildImplicitDependencies = "YES">
8+
</BuildAction>
9+
<TestAction
10+
buildConfiguration = "Debug"
11+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
12+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
13+
shouldUseLaunchSchemeArgsEnv = "YES"
14+
shouldAutocreateTestPlan = "YES">
15+
<Testables>
16+
<TestableReference
17+
skipped = "NO"
18+
parallelizable = "YES">
19+
<BuildableReference
20+
BuildableIdentifier = "primary"
21+
BlueprintIdentifier = "7B11F8332B4549E000346A41"
22+
BuildableName = "PlantingMindTests.xctest"
23+
BlueprintName = "PlantingMindTests"
24+
ReferencedContainer = "container:PlantingMind.xcodeproj">
25+
</BuildableReference>
26+
</TestableReference>
27+
</Testables>
28+
</TestAction>
29+
<LaunchAction
30+
buildConfiguration = "Debug"
31+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
32+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
33+
launchStyle = "0"
34+
useCustomWorkingDirectory = "NO"
35+
ignoresPersistentStateOnLaunch = "NO"
36+
debugDocumentVersioning = "YES"
37+
debugServiceExtension = "internal"
38+
allowLocationSimulation = "YES">
39+
</LaunchAction>
40+
<ProfileAction
41+
buildConfiguration = "Release"
42+
shouldUseLaunchSchemeArgsEnv = "YES"
43+
savedToolIdentifier = ""
44+
useCustomWorkingDirectory = "NO"
45+
debugDocumentVersioning = "YES">
46+
</ProfileAction>
47+
<AnalyzeAction
48+
buildConfiguration = "Debug">
49+
</AnalyzeAction>
50+
<ArchiveAction
51+
buildConfiguration = "Release"
52+
revealArchiveInOrganizer = "YES">
53+
</ArchiveAction>
54+
</Scheme>

PlantingMind/PlantingMind/Calender/CalendarViewModel.swift

+5-12
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class CalendarViewModel: ObservableObject {
4848

4949
func addingMonth(value: Int) {
5050
guard let newMonth = calendar.date(byAdding: .month, value: value, to: selectedDate),
51-
let startMonth = startMonth else { return }
51+
let startMonth = startMonth else { return }
5252

5353
// newMonth가 2024년 1월 이전이라면 return
5454
guard newMonth >= startMonth else { return }
@@ -64,17 +64,11 @@ class CalendarViewModel: ObservableObject {
6464
}
6565

6666
private func fetch(date: Date) {
67-
var dateFormatter: DateFormatter {
68-
let formatter = DateFormatter()
69-
formatter.dateFormat = "yyyy-MM"
70-
71-
return formatter
72-
}
73-
74-
let timestamp = dateFormatter.string(from: date)
67+
guard let startOfMonth = date.startOfMonth,
68+
let endOfMonth = date.endOfMonth else { return }
7569

7670
let fetchRequest = NSFetchRequest<MoodRecord>(entityName: "MoodRecord")
77-
let predicate = NSPredicate(format: "%K CONTAINS[cd] %@", #keyPath(MoodRecord.timestamp), timestamp)
71+
let predicate = NSPredicate(format: "%K >= %@ && %K <= %@", #keyPath(MoodRecord.timestamp), startOfMonth as NSDate, #keyPath(MoodRecord.timestamp), endOfMonth as NSDate)
7872
fetchRequest.predicate = predicate
7973

8074
do {
@@ -90,9 +84,8 @@ class CalendarViewModel: ObservableObject {
9084
guard let date = Calendar.current.date(from: DateComponents(year: day.year,
9185
month: day.month,
9286
day: day.day)) else { return nil }
93-
let timestamp = date.timeStampString()
9487

95-
return self.moods.filter { $0.timestamp == timestamp }.first
88+
return self.moods.filter { $0.timestamp == date }.first
9689
}
9790

9891
private func daysCount(for month: Date) -> Int {

PlantingMind/PlantingMind/CoreData/MoodRecord+CoreDataProperties.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ extension MoodRecord {
1616
return NSFetchRequest<MoodRecord>(entityName: "MoodRecord")
1717
}
1818

19-
@NSManaged public var timestamp: String
19+
@NSManaged public var timestamp: Date
2020
@NSManaged public var mood: String
2121
@NSManaged public var reason: String?
2222

PlantingMind/PlantingMind/CoreData/MoodRecords.xcdatamodeld/MoodRecords.xcdatamodel/contents

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
<entity name="MoodRecord" representedClassName="MoodRecord" syncable="YES">
44
<attribute name="mood" attributeType="String" defaultValueString="normal"/>
55
<attribute name="reason" optional="YES" attributeType="String" minValueString="0" maxValueString="100"/>
6-
<attribute name="timestamp" attributeType="String" defaultValueString="2020-01-01"/>
6+
<attribute name="timestamp" attributeType="Date" defaultDateTimeInterval="725731200" usesScalarValueType="NO"/>
77
</entity>
88
</model>

PlantingMind/PlantingMind/DateExtension.swift

+10-4
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,16 @@
88
import Foundation
99

1010
extension Date {
11-
func timeStampString() -> String {
12-
let dateFormatter = DateFormatter()
13-
dateFormatter.dateFormat = "yyyy-MM-dd"
11+
var startOfMonth: Date? {
12+
Calendar.current.date(from: Calendar.current.dateComponents([.year, .month], from: self))
13+
}
14+
15+
var endOfMonth: Date? {
16+
guard let nextMonth = Calendar.current.date(byAdding: .month, value: 1, to: self),
17+
let startOfNextMonth = Calendar.current.date(from: Calendar.current.dateComponents([.year, .month], from: nextMonth)) else {
18+
return nil
19+
}
1420

15-
return dateFormatter.string(from: self)
21+
return Calendar.current.date(byAdding: .second, value: -1, to: startOfNextMonth)
1622
}
1723
}

PlantingMind/PlantingMind/MoodRecord/MoodRecordViewModel.swift

+2-3
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,9 @@ class MoodRecordViewModel: ObservableObject {
2727

2828
func save() {
2929
guard let date = self.date else { return }
30-
let timestamp = date.timeStampString()
3130

3231
let fetchRequest = NSFetchRequest<MoodRecord>(entityName: "MoodRecord")
33-
let predicate = NSPredicate(format: "timestamp == %@", timestamp)
32+
let predicate = NSPredicate(format: "timestamp == %@", date as NSDate)
3433
fetchRequest.predicate = predicate
3534

3635
do {
@@ -42,7 +41,7 @@ class MoodRecordViewModel: ObservableObject {
4241
record.reason = self.reason
4342
} else {
4443
let record = MoodRecord(context: context)
45-
record.timestamp = timestamp
44+
record.timestamp = date
4645
record.mood = self.mood.rawValue
4746
record.reason = self.reason
4847
}

PlantingMind/PlantingMindTests/CalendarViewModelTests.swift

+33-17
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@ final class CalendarViewModelTests: XCTestCase {
1313
var context: NSManagedObjectContext!
1414
var viewModel: CalendarViewModel!
1515

16-
override func setUp() {
17-
super.setUp()
16+
override func setUpWithError() throws {
17+
try super.setUpWithError()
1818

19-
let date = Calendar.current.date(from: DateComponents(year: 2024,
20-
month: 1,
21-
day: 1))
19+
let date = try XCTUnwrap(Calendar.current.date(from: DateComponents(year: 2024,
20+
month: 1,
21+
day: 1)))
2222

2323
context = CoreDataStack(.inMemory).persistentContainer.viewContext
24-
viewModel = CalendarViewModel(today: date!, context: context)
25-
setupCoreData()
24+
viewModel = CalendarViewModel(today: date, context: context)
25+
try setupCoreData()
2626
}
2727

2828
override func tearDown() {
@@ -61,9 +61,9 @@ final class CalendarViewModelTests: XCTestCase {
6161
day: 1))
6262

6363
viewModel = CalendarViewModel(today: date!, context: context)
64-
viewModel.selectedDate = Calendar.current.date(from: DateComponents(year: 2024,
65-
month: 1,
66-
day: 1))!
64+
viewModel.selectedDate = try XCTUnwrap(Calendar.current.date(from: DateComponents(year: 2024,
65+
month: 1,
66+
day: 1)))
6767
viewModel.addingMonth(value: 1)
6868

6969
let nilCount = viewModel.days.filter { $0 == nil }.count
@@ -83,7 +83,7 @@ final class CalendarViewModelTests: XCTestCase {
8383
viewModel.fetch()
8484

8585
let expectedRecordsCount = 3
86-
XCTAssertTrue(viewModel.moods.count == expectedRecordsCount)
86+
XCTAssertEqual(viewModel.moods.count, expectedRecordsCount)
8787
}
8888

8989
func test_원하는_날짜의_mood_받기() throws {
@@ -100,9 +100,9 @@ final class CalendarViewModelTests: XCTestCase {
100100

101101
// 저장된 정보 없을 경우 Nil
102102
let result2 = viewModel.mood(of: CalendarModel(year: 2024,
103-
month: 1,
104-
day: 2,
105-
isToday: false))
103+
month: 1,
104+
day: 2,
105+
isToday: false))
106106

107107
XCTAssertNil(result2)
108108
}
@@ -119,12 +119,28 @@ final class CalendarViewModelTests: XCTestCase {
119119
XCTAssertEqual(self.viewModel.moods.count, expectedDataCount)
120120
notiExpectation.fulfill()
121121
})
122-
122+
123123
wait(for: [notiExpectation], timeout: 1.5)
124124
}
125125

126-
private func setupCoreData() {
127-
let timestapms = ["2024-02-24", "2024-01-01", "2024-01-06", "2024-01-24"]
126+
private func setupCoreData() throws {
127+
let date1 = try XCTUnwrap(Calendar.current.date(from: DateComponents(year: 2024,
128+
month: 2,
129+
day: 24)))
130+
131+
let date2 = try XCTUnwrap(Calendar.current.date(from: DateComponents(year: 2024,
132+
month: 1,
133+
day: 1)))
134+
135+
let date3 = try XCTUnwrap(Calendar.current.date(from: DateComponents(year: 2024,
136+
month: 1,
137+
day: 6)))
138+
139+
let date4 = try XCTUnwrap(Calendar.current.date(from: DateComponents(year: 2024,
140+
month: 1,
141+
day: 24)))
142+
143+
let timestapms = [date1, date2, date3, date4]
128144
let moods: [Mood] = [.nice, .normal, .notBad, .bad]
129145
let reasons: [String?] = ["happy birthday", nil, "developing...", "eww"]
130146

PlantingMind/PlantingMindTests/DayCellViewModelTest.swift

+3-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ final class DayCellViewModelTest: XCTestCase {
2222
func test_DayCellModel_record_non_nil() throws {
2323
let coreDataStack = CoreDataStack(.inMemory)
2424
let moodRecord = MoodRecord(context: coreDataStack.persistentContainer.viewContext)
25-
moodRecord.timestamp = "2024-02-24"
25+
moodRecord.timestamp = try XCTUnwrap(Calendar.current.date(from: DateComponents(year: 2024,
26+
month: 2,
27+
day: 24)))
2628
moodRecord.mood = Mood.nice.rawValue
2729

2830
let model = DayCellViewModel(today: Date(), calendarModel: CalendarModel(year: 2024, month: 2, day: 24, isToday: false),

PlantingMind/PlantingMindTests/FetchNotificationSpy.swift

+11-3
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,16 @@ final class FetchNotificationSpy {
3030
func sendNoticiation() {
3131
self.saveCoreData()
3232

33-
let timestamp = "2024-01"
33+
let startOfMonth = Calendar.current.date(from: DateComponents(year: 2024,
34+
month: 1,
35+
day: 1))!
36+
37+
let endOfMonth = Calendar.current.date(from: DateComponents(year: 2024,
38+
month: 1,
39+
day: 31))!
3440

3541
let fetchRequest = NSFetchRequest<MoodRecord>(entityName: "MoodRecord")
36-
let predicate = NSPredicate(format: "%K CONTAINS[cd] %@", #keyPath(MoodRecord.timestamp), timestamp)
42+
let predicate = NSPredicate(format: "%K >= %@ && %K <= %@", #keyPath(MoodRecord.timestamp), startOfMonth as NSDate, #keyPath(MoodRecord.timestamp), endOfMonth as NSDate)
3743
fetchRequest.predicate = predicate
3844

3945
do {
@@ -49,7 +55,9 @@ final class FetchNotificationSpy {
4955

5056
private func saveCoreData() {
5157
let moodRecord = MoodRecord(context: context)
52-
moodRecord.timestamp = "2024-01-07"
58+
moodRecord.timestamp = Calendar.current.date(from: DateComponents(year: 2024,
59+
month: 1,
60+
day: 7))!
5361
moodRecord.mood = Mood.good.rawValue
5462
moodRecord.reason = "i wanna sleep"
5563

PlantingMind/PlantingMindTests/MoodRecordViewModelTests.swift

+6-4
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ final class MoodRecordViewModelTests: XCTestCase {
7272
viewModel.reason = expectedReason
7373
viewModel.save()
7474

75-
let record = self.fetch()
75+
let record = try self.fetch()
7676

7777
XCTAssertNotNil(record)
7878
XCTAssertEqual(record?.mood, expectedMood.rawValue)
@@ -90,11 +90,13 @@ final class MoodRecordViewModelTests: XCTestCase {
9090
XCTAssertTrue(mock.bindNoticiationIsCalled)
9191
}
9292

93-
private func fetch() -> MoodRecord? {
94-
let timestamp = "2024-02-24"
93+
private func fetch() throws -> MoodRecord? {
94+
let timestamp = try XCTUnwrap(Calendar.current.date(from: DateComponents(year: 2024,
95+
month: 2,
96+
day: 24)))
9597

9698
let fetchRequest = NSFetchRequest<MoodRecord>(entityName: "MoodRecord")
97-
let predicate = NSPredicate(format: "timestamp == %@", timestamp)
99+
let predicate = NSPredicate(format: "timestamp == %@", timestamp as NSDate)
98100
fetchRequest.predicate = predicate
99101

100102
do {

0 commit comments

Comments
 (0)