Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat][#29] check if network available #34

Merged
merged 5 commits into from
Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions DontForget.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
AD147F322B57FFB500561846 /* AppIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD147F312B57FFB500561846 /* AppIntent.swift */; };
AD147F342B57FFB600561846 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AD147F332B57FFB600561846 /* Assets.xcassets */; };
AD147F382B57FFB600561846 /* DontForgetWidgetExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = AD147F262B57FFB500561846 /* DontForgetWidgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
AD1D31F92B9589A700ECCBFD /* NetworkMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD1D31F82B9589A700ECCBFD /* NetworkMonitor.swift */; };
AD36D44B2B8DD37D00250705 /* DeletionRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD36D44A2B8DD37D00250705 /* DeletionRepository.swift */; };
AD36D44D2B8DD39500250705 /* DeletionInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD36D44C2B8DD39500250705 /* DeletionInterface.swift */; };
AD3B45852B68B634009529DE /* AnniversaryDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD3B45842B68B634009529DE /* AnniversaryDetailView.swift */; };
Expand Down Expand Up @@ -152,6 +153,7 @@
AD147F312B57FFB500561846 /* AppIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppIntent.swift; sourceTree = "<group>"; };
AD147F332B57FFB600561846 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
AD147F352B57FFB600561846 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
AD1D31F82B9589A700ECCBFD /* NetworkMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkMonitor.swift; sourceTree = "<group>"; };
AD36D44A2B8DD37D00250705 /* DeletionRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeletionRepository.swift; sourceTree = "<group>"; };
AD36D44C2B8DD39500250705 /* DeletionInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeletionInterface.swift; sourceTree = "<group>"; };
AD3B45842B68B634009529DE /* AnniversaryDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnniversaryDetailView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -251,6 +253,7 @@
children = (
09642C3A2B649B260015220E /* EndPoint.swift */,
09642C3C2B649B2D0015220E /* APIConstant.swift */,
AD1D31F82B9589A700ECCBFD /* NetworkMonitor.swift */,
);
path = Network;
sourceTree = "<group>";
Expand Down Expand Up @@ -756,6 +759,7 @@
09642C462B649FD00015220E /* DTO.swift in Sources */,
AD0F99332B7C523200E2A915 /* AlarmView.swift in Sources */,
09642C582B67C8730015220E /* ViewModelType.swift in Sources */,
AD1D31F92B9589A700ECCBFD /* NetworkMonitor.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
24 changes: 24 additions & 0 deletions DontForget/Sources/Data/Network/NetworkMonitor.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// NetworkMonitor.swift
// DontForget
//
// Created by 제나 on 3/4/24.
//

import Foundation
import Network

@Observable
Copy link
Collaborator Author

@dayo2n dayo2n Mar 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

중복이므로 삭제
16.0 지원을 고려중이라 매크로말고 ObservableObject를 따르도록 하겠습니다용

final class NetworkMonitor: ObservableObject {
static let shared = NetworkMonitor()
private let networkMonitor = NWPathMonitor()
private let workerQueue = DispatchQueue(label: "Monitor")
var isConnected = false

init() {
networkMonitor.pathUpdateHandler = { path in
self.isConnected = path.status == .satisfied
}
networkMonitor.start(queue: workerQueue)
}
}
2 changes: 1 addition & 1 deletion DontForget/Sources/Domain/Model/CardType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import Foundation

enum CardType: String {
enum CardType: String, CaseIterable {
case lunar = "LUNAR"
case face = "FACE"
case arm = "ARM"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,7 @@ struct CreationView: View {
) {
self.viewModel = viewModel
self.type = type
switch type {
case .create:
break
case .edit:
if let id = id {
self.id = id
}
configure()
Expand Down Expand Up @@ -194,60 +191,8 @@ struct CreationView: View {
.padding(.top, isKeyboardVisible && focusField == .memo ? keyboardHeight + 20 : 0)
.animation(.default, value: keyboardHeight)
}
.onAppear {
switch type {
case .create:
self.selectedAlarmIndexes = Set([AlarmPeriod.dDay.schedule])
focusField = .eventName
case .edit:
viewModel.fetchAnniversaryDetail(id: id!)
viewModel.$anniversaryDetail
.receive(on: DispatchQueue.main)
.sink { res in
self.name = res?.title ?? ""
self.memo = res?.content ?? ""
self.selectedAlarmIndexes = Set(res?.alarmSchedule ?? [])
self.baseType = res?.baseType == ConvertDate.solar.title ? 1 : 0
if let date = res?.baseDate {
self.baseDate = self.extractYearMonthDay(from: date)!
}
}
.store(in: &cancellables)
}
NotificationCenter.default.addObserver(
forName: UIResponder.keyboardWillShowNotification,
object: nil,
queue: .main
) { noti in
guard let keyboardFrame = noti.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return }
keyboardHeight = keyboardFrame.height
}
NotificationCenter
.default
.addObserver(
forName: UIResponder.keyboardWillHideNotification,
object: nil,
queue: .main
) { _ in
keyboardHeight = 0
}
}
.onDisappear {
NotificationCenter
.default
.removeObserver(
self,
name: UIResponder.keyboardWillShowNotification,
object: nil
)
NotificationCenter
.default
.removeObserver(
self,
name: UIResponder.keyboardWillHideNotification,
object: nil
)
}
.onAppear(perform: actionsOnAppear)
.onDisappear(perform: actionOnDisappear)
.onReceive(viewModel.viewDismissalModePublisher) { shouldDismiss in
if shouldDismiss {
withAnimation {
Expand All @@ -274,16 +219,11 @@ extension CreationView {
private func extractYearMonthDay(from dateString: String) -> [Int]? {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
guard let date = dateFormatter.date(from: dateString) else {
print("=== DEBUG: Invalid date format")
return nil
}

let date = dateFormatter.date(from: dateString)!
let calendar = Calendar.current
let year = calendar.component(.year, from: date) % 100
let month = calendar.component(.month, from: date)
let day = calendar.component(.day, from: date)

return [year, month, day]
}

Expand All @@ -301,13 +241,58 @@ extension CreationView {
}

private func randomCardType() -> String {
let cardType = [
CardType.lunar.rawValue,
CardType.tail.rawValue,
CardType.arm.rawValue,
CardType.face.rawValue,
CardType.forest.rawValue
]
return cardType.randomElement()!
return CardType.allCases.randomElement()!.rawValue
}

private func actionsOnAppear() {
switch type {
case .create:
self.selectedAlarmIndexes = Set([AlarmPeriod.dDay.schedule])
focusField = .eventName
case .edit:
viewModel.fetchAnniversaryDetail(id: id!)
viewModel.$anniversaryDetail
.receive(on: DispatchQueue.main)
.sink { res in
self.name = res?.title ?? ""
self.memo = res?.content ?? ""
self.selectedAlarmIndexes = Set(res?.alarmSchedule ?? [])
self.baseType = res?.baseType == ConvertDate.solar.title ? 1 : 0
if let date = res?.baseDate {
self.baseDate = self.extractYearMonthDay(from: date)!
}
}
.store(in: &cancellables)
}
NotificationCenter.default.addObserver(
forName: UIResponder.keyboardWillShowNotification,
object: nil,
queue: .main
) { noti in
guard let keyboardFrame = noti.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return }
keyboardHeight = keyboardFrame.height
}
NotificationCenter
.default
.addObserver(
forName: UIResponder.keyboardWillHideNotification,
object: nil,
queue: .main
) { _ in
keyboardHeight = 0
}
}

private func actionOnDisappear() {
NotificationCenter.default.removeObserver(
self,
name: UIResponder.keyboardWillShowNotification,
object: nil
)
NotificationCenter.default.removeObserver(
self,
name: UIResponder.keyboardWillHideNotification,
object: nil
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,6 @@ final class CreationViewModel: ViewModelType {
@Published var anniversaryDetail: AnniversaryDetailDTO?
@Published var title: String?
@Published var date: String?
@Published var content: String = ""
@Published var calendarType: String = ""
@Published var cardType: String = ""
@Published var alarmSchedule: [String] = []
@Published var getDate: [Int] = []

var viewDismissalModePublisher = PassthroughSubject<Bool, Never>()
private var dismiss = false {
Expand Down Expand Up @@ -142,11 +137,7 @@ final class CreationViewModel: ViewModelType {
}
}
.receive(on: DispatchQueue.main)
.sink { completion in
if case .failure = completion {
#warning("handling error")
}
} receiveValue: { [weak self] response in
.sink { _ in } receiveValue: { [weak self] response in
if let response = response {
self?.anniversaryDetail = response.anniversaryDetail
self?.state = .success
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,7 @@ struct CustomDatePicker: View {
Spacer(minLength: fullView.size.height / 2 - 25)
LazyVGrid(columns: [GridItem(.fixed(32))], spacing: 0) {
ForEach(values, id: \.self) { value in
let displayValue = value % 100
Text("\(String(format: "%02d", displayValue))")
Text("\(String(format: "%02d", value % 100))")
.font(.pretendard(size: 24))
.foregroundColor(selection.wrappedValue == value ? .blue : .gray)
.frame(width: 60, height: 63)
Expand All @@ -108,8 +107,7 @@ struct CustomDatePicker: View {
}
.onPreferenceChange(CenterPreferenceKey.self) { centers in
DispatchQueue.main.async {
if !isProgrammaticScroll,
let closest = centers.min(by: { abs($0.value) < abs($1.value) }),
if !isProgrammaticScroll, let closest = centers.min(by: { abs($0.value) < abs($1.value) }),
selection.wrappedValue != closest.key {
withAnimation {
scrollViewProxy.scrollTo(closest.key, anchor: .center)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ struct AnniversaryDetailView: View {
coordinateSpace: .local
)
.onEnded({ value in
if value.translation.width > 200 {
if value.translation.width > 100 {
withAnimation {
dismiss()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ final class DefaultAnniversaryDetailViewModel: ViewModelType {
// MARK: - Properties
let anniversaryId: Int
private var cancellables = Set<AnyCancellable>()
@Published var state: State
@Published var state: State = .idle
@Published var anniversaryDetail: AnniversaryDetailDTO?
private let anniversaryDetailRepository: AnniversaryDetailRepository
private let deletionRepository: DeletionRepository
Expand Down Expand Up @@ -44,7 +44,6 @@ final class DefaultAnniversaryDetailViewModel: ViewModelType {
anniversaryDetailRepository: AnniversaryDetailRepository,
deletionRepository: DeletionRepository
) {
self.state = .loading
self.anniversaryId = anniversaryId
self.anniversaryDetailRepository = anniversaryDetailRepository
self.fetchAnniversaryDetailUseCase = DefaultFetchAnniversaryDetailUseCase(
Expand Down Expand Up @@ -82,19 +81,13 @@ final class DefaultAnniversaryDetailViewModel: ViewModelType {
} catch {
print("=== DEBUG: \(error)")
promise(.failure(error))
self.state = .failed("failed fetchAnniversaryDetail()")
}
}
}
.receive(on: DispatchQueue.main)
.sink { completion in
if case .failure = completion {
#warning("handling error")
}
} receiveValue: { [weak self] response in
.sink { _ in } receiveValue: { [weak self] response in
if let response = response {
self?.anniversaryDetail = response.anniversaryDetail
self?.state = .success
}
}
.store(in: &cancellables)
Expand All @@ -119,8 +112,7 @@ final class DefaultAnniversaryDetailViewModel: ViewModelType {
.sink { completion in
self.dismiss = true
if case .failure = completion {
#warning("handling error")
print(completion)
print("=== DEBUG: \(completion)")
}
} receiveValue: { _ in }
.store(in: &cancellables)
Expand Down
Loading