Skip to content

Commit cda0718

Browse files
authored
Merge pull request #34 from Nexters/feature/29-is-available-network
[feat][#29] check if network available
2 parents 887b2ef + 67c8ef6 commit cda0718

File tree

11 files changed

+136
-134
lines changed

11 files changed

+136
-134
lines changed

โ€ŽDontForget.xcodeproj/project.pbxprojโ€Ž

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
AD147F322B57FFB500561846 /* AppIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD147F312B57FFB500561846 /* AppIntent.swift */; };
4949
AD147F342B57FFB600561846 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AD147F332B57FFB600561846 /* Assets.xcassets */; };
5050
AD147F382B57FFB600561846 /* DontForgetWidgetExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = AD147F262B57FFB500561846 /* DontForgetWidgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
51+
AD1D31F92B9589A700ECCBFD /* NetworkMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD1D31F82B9589A700ECCBFD /* NetworkMonitor.swift */; };
5152
AD36D44B2B8DD37D00250705 /* DeletionRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD36D44A2B8DD37D00250705 /* DeletionRepository.swift */; };
5253
AD36D44D2B8DD39500250705 /* DeletionInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD36D44C2B8DD39500250705 /* DeletionInterface.swift */; };
5354
AD3B45852B68B634009529DE /* AnniversaryDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD3B45842B68B634009529DE /* AnniversaryDetailView.swift */; };
@@ -152,6 +153,7 @@
152153
AD147F312B57FFB500561846 /* AppIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppIntent.swift; sourceTree = "<group>"; };
153154
AD147F332B57FFB600561846 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
154155
AD147F352B57FFB600561846 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
156+
AD1D31F82B9589A700ECCBFD /* NetworkMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkMonitor.swift; sourceTree = "<group>"; };
155157
AD36D44A2B8DD37D00250705 /* DeletionRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeletionRepository.swift; sourceTree = "<group>"; };
156158
AD36D44C2B8DD39500250705 /* DeletionInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeletionInterface.swift; sourceTree = "<group>"; };
157159
AD3B45842B68B634009529DE /* AnniversaryDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnniversaryDetailView.swift; sourceTree = "<group>"; };
@@ -251,6 +253,7 @@
251253
children = (
252254
09642C3A2B649B260015220E /* EndPoint.swift */,
253255
09642C3C2B649B2D0015220E /* APIConstant.swift */,
256+
AD1D31F82B9589A700ECCBFD /* NetworkMonitor.swift */,
254257
);
255258
path = Network;
256259
sourceTree = "<group>";
@@ -756,6 +759,7 @@
756759
09642C462B649FD00015220E /* DTO.swift in Sources */,
757760
AD0F99332B7C523200E2A915 /* AlarmView.swift in Sources */,
758761
09642C582B67C8730015220E /* ViewModelType.swift in Sources */,
762+
AD1D31F92B9589A700ECCBFD /* NetworkMonitor.swift in Sources */,
759763
);
760764
runOnlyForDeploymentPostprocessing = 0;
761765
};
@@ -940,7 +944,7 @@
940944
"$(inherited)",
941945
"@executable_path/Frameworks",
942946
);
943-
MARKETING_VERSION = 1.0.2;
947+
MARKETING_VERSION = 1.1.0;
944948
"OTHER_LDFLAGS[arch=*]" = "-Wl,-ld_classic";
945949
PRODUCT_BUNDLE_IDENTIFIER = com.dazzling.DontForget;
946950
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -981,7 +985,7 @@
981985
"$(inherited)",
982986
"@executable_path/Frameworks",
983987
);
984-
MARKETING_VERSION = 1.0.2;
988+
MARKETING_VERSION = 1.1.0;
985989
PRODUCT_BUNDLE_IDENTIFIER = com.dazzling.DontForget;
986990
PRODUCT_NAME = "$(TARGET_NAME)";
987991
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1014,7 +1018,7 @@
10141018
"@executable_path/Frameworks",
10151019
"@executable_path/../../Frameworks",
10161020
);
1017-
MARKETING_VERSION = 1.0.2;
1021+
MARKETING_VERSION = 1.1.0;
10181022
PRODUCT_BUNDLE_IDENTIFIER = com.dazzling.DontForget.DontForgetWidget;
10191023
PRODUCT_NAME = "$(TARGET_NAME)";
10201024
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1049,7 +1053,7 @@
10491053
"@executable_path/Frameworks",
10501054
"@executable_path/../../Frameworks",
10511055
);
1052-
MARKETING_VERSION = 1.0.2;
1056+
MARKETING_VERSION = 1.1.0;
10531057
PRODUCT_BUNDLE_IDENTIFIER = com.dazzling.DontForget.DontForgetWidget;
10541058
PRODUCT_NAME = "$(TARGET_NAME)";
10551059
PROVISIONING_PROFILE_SPECIFIER = "";
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//
2+
// NetworkMonitor.swift
3+
// DontForget
4+
//
5+
// Created by ์ œ๋‚˜ on 3/4/24.
6+
//
7+
8+
import Foundation
9+
import Network
10+
11+
@Observable
12+
final class NetworkMonitor: ObservableObject {
13+
static let shared = NetworkMonitor()
14+
private let networkMonitor = NWPathMonitor()
15+
private let workerQueue = DispatchQueue(label: "Monitor")
16+
var isConnected = false
17+
18+
init() {
19+
networkMonitor.pathUpdateHandler = { path in
20+
self.isConnected = path.status == .satisfied
21+
}
22+
networkMonitor.start(queue: workerQueue)
23+
}
24+
}

โ€ŽDontForget/Sources/Domain/Model/CardType.swiftโ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import Foundation
99

10-
enum CardType: String {
10+
enum CardType: String, CaseIterable {
1111
case lunar = "LUNAR"
1212
case face = "FACE"
1313
case arm = "ARM"

โ€ŽDontForget/Sources/Presentations/Application/Common/Constants.swiftโ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ struct Constants {
2020
let calendar = Calendar.current
2121
let startOfCurrentDate = calendar.startOfDay(for: Date())
2222
let startOfTargetDate = calendar.startOfDay(for: from)
23-
return calendar.dateComponents([.day], from: startOfCurrentDate, to: startOfTargetDate).day!
23+
return calendar.dateComponents([.day], from: startOfCurrentDate, to: startOfTargetDate).day! * -1
2424
}
2525
}

โ€ŽDontForget/Sources/Presentations/Application/Creation/CreationView.swiftโ€Ž

Lines changed: 62 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,7 @@ struct CreationView: View {
4646
) {
4747
self.viewModel = viewModel
4848
self.type = type
49-
switch type {
50-
case .create:
51-
break
52-
case .edit:
49+
if let id = id {
5350
self.id = id
5451
}
5552
configure()
@@ -194,67 +191,20 @@ struct CreationView: View {
194191
.padding(.top, isKeyboardVisible && focusField == .memo ? keyboardHeight + 20 : 0)
195192
.animation(.default, value: keyboardHeight)
196193
}
197-
.onAppear {
198-
switch type {
199-
case .create:
200-
self.selectedAlarmIndexes = Set([AlarmPeriod.dDay.schedule])
201-
focusField = .eventName
202-
case .edit:
203-
viewModel.fetchAnniversaryDetail(id: id!)
204-
viewModel.$anniversaryDetail
205-
.receive(on: DispatchQueue.main)
206-
.sink { res in
207-
self.name = res?.title ?? ""
208-
self.memo = res?.content ?? ""
209-
self.selectedAlarmIndexes = Set(res?.alarmSchedule ?? [])
210-
self.baseType = res?.baseType == ConvertDate.solar.title ? 1 : 0
211-
if let date = res?.baseDate {
212-
self.baseDate = self.extractYearMonthDay(from: date)!
213-
}
214-
}
215-
.store(in: &cancellables)
216-
}
217-
NotificationCenter.default.addObserver(
218-
forName: UIResponder.keyboardWillShowNotification,
219-
object: nil,
220-
queue: .main
221-
) { noti in
222-
guard let keyboardFrame = noti.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return }
223-
keyboardHeight = keyboardFrame.height
224-
}
225-
NotificationCenter
226-
.default
227-
.addObserver(
228-
forName: UIResponder.keyboardWillHideNotification,
229-
object: nil,
230-
queue: .main
231-
) { _ in
232-
keyboardHeight = 0
233-
}
234-
}
235-
.onDisappear {
236-
NotificationCenter
237-
.default
238-
.removeObserver(
239-
self,
240-
name: UIResponder.keyboardWillShowNotification,
241-
object: nil
242-
)
243-
NotificationCenter
244-
.default
245-
.removeObserver(
246-
self,
247-
name: UIResponder.keyboardWillHideNotification,
248-
object: nil
249-
)
250-
}
194+
.onAppear(perform: actionsOnAppear)
195+
.onDisappear(perform: actionOnDisappear)
251196
.onReceive(viewModel.viewDismissalModePublisher) { shouldDismiss in
252197
if shouldDismiss {
253198
withAnimation {
254199
dismiss()
255200
}
256201
}
257202
}
203+
.onChange(of: showConfirmView) { _, showed in
204+
if showed {
205+
hideKeyboard()
206+
}
207+
}
258208
}
259209
.navigationBarHidden(true)
260210
}
@@ -274,16 +224,11 @@ extension CreationView {
274224
private func extractYearMonthDay(from dateString: String) -> [Int]? {
275225
let dateFormatter = DateFormatter()
276226
dateFormatter.dateFormat = "yyyy-MM-dd"
277-
guard let date = dateFormatter.date(from: dateString) else {
278-
print("=== DEBUG: Invalid date format")
279-
return nil
280-
}
281-
227+
let date = dateFormatter.date(from: dateString)!
282228
let calendar = Calendar.current
283229
let year = calendar.component(.year, from: date) % 100
284230
let month = calendar.component(.month, from: date)
285231
let day = calendar.component(.day, from: date)
286-
287232
return [year, month, day]
288233
}
289234

@@ -301,13 +246,58 @@ extension CreationView {
301246
}
302247

303248
private func randomCardType() -> String {
304-
let cardType = [
305-
CardType.lunar.rawValue,
306-
CardType.tail.rawValue,
307-
CardType.arm.rawValue,
308-
CardType.face.rawValue,
309-
CardType.forest.rawValue
310-
]
311-
return cardType.randomElement()!
249+
return CardType.allCases.randomElement()!.rawValue
250+
}
251+
252+
private func actionsOnAppear() {
253+
switch type {
254+
case .create:
255+
self.selectedAlarmIndexes = Set([AlarmPeriod.dDay.schedule])
256+
focusField = .eventName
257+
case .edit:
258+
viewModel.fetchAnniversaryDetail(id: id!)
259+
viewModel.$anniversaryDetail
260+
.receive(on: DispatchQueue.main)
261+
.sink { res in
262+
self.name = res?.title ?? ""
263+
self.memo = res?.content ?? ""
264+
self.selectedAlarmIndexes = Set(res?.alarmSchedule ?? [])
265+
self.baseType = res?.baseType == ConvertDate.solar.title ? 1 : 0
266+
if let date = res?.baseDate {
267+
self.baseDate = self.extractYearMonthDay(from: date)!
268+
}
269+
}
270+
.store(in: &cancellables)
271+
}
272+
NotificationCenter.default.addObserver(
273+
forName: UIResponder.keyboardWillShowNotification,
274+
object: nil,
275+
queue: .main
276+
) { noti in
277+
guard let keyboardFrame = noti.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return }
278+
keyboardHeight = keyboardFrame.height
279+
}
280+
NotificationCenter
281+
.default
282+
.addObserver(
283+
forName: UIResponder.keyboardWillHideNotification,
284+
object: nil,
285+
queue: .main
286+
) { _ in
287+
keyboardHeight = 0
288+
}
289+
}
290+
291+
private func actionOnDisappear() {
292+
NotificationCenter.default.removeObserver(
293+
self,
294+
name: UIResponder.keyboardWillShowNotification,
295+
object: nil
296+
)
297+
NotificationCenter.default.removeObserver(
298+
self,
299+
name: UIResponder.keyboardWillHideNotification,
300+
object: nil
301+
)
312302
}
313303
}

โ€ŽDontForget/Sources/Presentations/Application/Creation/CreationViewModel.swiftโ€Ž

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,6 @@ final class CreationViewModel: ViewModelType {
2222
@Published var anniversaryDetail: AnniversaryDetailDTO?
2323
@Published var title: String?
2424
@Published var date: String?
25-
@Published var content: String = ""
26-
@Published var calendarType: String = ""
27-
@Published var cardType: String = ""
28-
@Published var alarmSchedule: [String] = []
29-
@Published var getDate: [Int] = []
3025

3126
var viewDismissalModePublisher = PassthroughSubject<Bool, Never>()
3227
private var dismiss = false {
@@ -142,11 +137,7 @@ final class CreationViewModel: ViewModelType {
142137
}
143138
}
144139
.receive(on: DispatchQueue.main)
145-
.sink { completion in
146-
if case .failure = completion {
147-
#warning("handling error")
148-
}
149-
} receiveValue: { [weak self] response in
140+
.sink { _ in } receiveValue: { [weak self] response in
150141
if let response = response {
151142
self?.anniversaryDetail = response.anniversaryDetail
152143
self?.state = .success

โ€ŽDontForget/Sources/Presentations/Application/Creation/Section/CustomDatePicker.swiftโ€Ž

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,7 @@ struct CustomDatePicker: View {
8888
Spacer(minLength: fullView.size.height / 2 - 25)
8989
LazyVGrid(columns: [GridItem(.fixed(32))], spacing: 0) {
9090
ForEach(values, id: \.self) { value in
91-
let displayValue = value % 100
92-
Text("\(String(format: "%02d", displayValue))")
91+
Text("\(String(format: "%02d", value % 100))")
9392
.font(.pretendard(size: 24))
9493
.foregroundColor(selection.wrappedValue == value ? .blue : .gray)
9594
.frame(width: 60, height: 63)
@@ -108,8 +107,7 @@ struct CustomDatePicker: View {
108107
}
109108
.onPreferenceChange(CenterPreferenceKey.self) { centers in
110109
DispatchQueue.main.async {
111-
if !isProgrammaticScroll,
112-
let closest = centers.min(by: { abs($0.value) < abs($1.value) }),
110+
if !isProgrammaticScroll, let closest = centers.min(by: { abs($0.value) < abs($1.value) }),
113111
selection.wrappedValue != closest.key {
114112
withAnimation {
115113
scrollViewProxy.scrollTo(closest.key, anchor: .center)

โ€ŽDontForget/Sources/Presentations/Application/Detail/View/AnniversaryDetailView.swiftโ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ struct AnniversaryDetailView: View {
164164
coordinateSpace: .local
165165
)
166166
.onEnded({ value in
167-
if value.translation.width > 200 {
167+
if value.translation.width > 100 {
168168
withAnimation {
169169
dismiss()
170170
}

โ€ŽDontForget/Sources/Presentations/Application/Detail/ViewModel/AnniversaryDetailViewModel.swiftโ€Ž

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ final class DefaultAnniversaryDetailViewModel: ViewModelType {
1313
// MARK: - Properties
1414
let anniversaryId: Int
1515
private var cancellables = Set<AnyCancellable>()
16-
@Published var state: State
16+
@Published var state: State = .idle
1717
@Published var anniversaryDetail: AnniversaryDetailDTO?
1818
private let anniversaryDetailRepository: AnniversaryDetailRepository
1919
private let deletionRepository: DeletionRepository
@@ -44,7 +44,6 @@ final class DefaultAnniversaryDetailViewModel: ViewModelType {
4444
anniversaryDetailRepository: AnniversaryDetailRepository,
4545
deletionRepository: DeletionRepository
4646
) {
47-
self.state = .loading
4847
self.anniversaryId = anniversaryId
4948
self.anniversaryDetailRepository = anniversaryDetailRepository
5049
self.fetchAnniversaryDetailUseCase = DefaultFetchAnniversaryDetailUseCase(
@@ -82,19 +81,13 @@ final class DefaultAnniversaryDetailViewModel: ViewModelType {
8281
} catch {
8382
print("=== DEBUG: \(error)")
8483
promise(.failure(error))
85-
self.state = .failed("failed fetchAnniversaryDetail()")
8684
}
8785
}
8886
}
8987
.receive(on: DispatchQueue.main)
90-
.sink { completion in
91-
if case .failure = completion {
92-
#warning("handling error")
93-
}
94-
} receiveValue: { [weak self] response in
88+
.sink { _ in } receiveValue: { [weak self] response in
9589
if let response = response {
9690
self?.anniversaryDetail = response.anniversaryDetail
97-
self?.state = .success
9891
}
9992
}
10093
.store(in: &cancellables)
@@ -119,8 +112,7 @@ final class DefaultAnniversaryDetailViewModel: ViewModelType {
119112
.sink { completion in
120113
self.dismiss = true
121114
if case .failure = completion {
122-
#warning("handling error")
123-
print(completion)
115+
print("=== DEBUG: \(completion)")
124116
}
125117
} receiveValue: { _ in }
126118
.store(in: &cancellables)

0 commit comments

Comments
ย (0)