Conversation
📝 Walkthrough워크스루사용자 진행 상태 플래그를 UserDefaults에 추가하여 영속성 지원을 확장하고, 저장소 계층에서 이 플래그를 관리하며, 코디네이터 뷰에서 조건부 초기 화면 표시 로직을 도입하고 라우팅 구조를 정리했습니다. 변경사항
예상 코드 리뷰 노력🎯 3 (보통) | ⏱️ ~25분 관련 가능성 있는 PR
제안 리뷰어
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
Cherrish-iOS/Cherrish-iOS/Data/Repository/DemoRepository.swift (1)
60-70: 미사용 변수 경고 가능성
response변수가 선언되었지만 사용되지 않습니다. 의도적으로 응답을 무시하는 경우_ =패턴을 사용하거나, 향후hasProgressChallenge를 true로 설정해야 한다면 해당 로직을 추가하는 것이 좋습니다.♻️ 미사용 변수 처리
func createChallenge(missionIds: Int, routineNames: [String]) async throws { let userID: Int = userDefaultService.load(key: .userID) ?? 1 - let response = try await networkService.request( + _ = try await networkService.request( DemoAPI.createChallenge(userID: userID, requestDTO: .init( homecareRoutineId: missionIds, routineNames: routineNames ) ) ) }
🤖 Fix all issues with AI agents
In `@Cherrish-iOS/Cherrish-iOS/Data/Repository/DemoRepository.swift`:
- Around line 42-47: The catch block in DemoRepository.swift force-casts the
thrown error with `error as! CherrishError`, which can crash for
non-CherrishError errors; change this to a safe cast (e.g., `if let chErr =
error as? CherrishError` or `guard let chErr = error as? CherrishError else {
throw error }`) and only call `userDefaultService.save(false, key:
.hasProgressChallenge)` when `chErr == .conflict`, otherwise rethrow the
original error; update the catch in the function containing this logic to
perform the safe cast and conditional save before rethrowing.
In
`@Cherrish-iOS/Cherrish-iOS/Presentation/Feature/ChallengeView/Coordinator/ChallengeCoordinatorView.swift`:
- Line 13: Change ChallengeCoordinatorView to accept UserDefaultService via
constructor injection instead of instantiating DefaultUserDefaultService inline:
add an init(userDefaultService: UserDefaultService =
DefaultUserDefaultService()) that assigns to the existing userDefaultService
property, remove the direct DefaultUserDefaultService() initialization, and keep
the property typed as UserDefaultService so tests can inject a mock and callers
can rely on the default.
| } catch { | ||
| if error as! CherrishError == CherrishError.conflict { | ||
| let _ = userDefaultService.save(false, key: .hasProgressChallenge) | ||
| } | ||
| throw error | ||
| } |
There was a problem hiding this comment.
Force cast 사용으로 인한 런타임 크래시 위험
error as! CherrishError는 error가 CherrishError 타입이 아닐 경우 앱이 크래시됩니다. 네트워크 에러, 디코딩 에러 등 다른 타입의 에러가 발생할 수 있으므로 안전한 캐스팅을 사용해야 합니다.
🐛 안전한 캐스팅으로 수정
} catch {
- if error as! CherrishError == CherrishError.conflict {
+ if let cherrishError = error as? CherrishError, cherrishError == .conflict {
let _ = userDefaultService.save(false, key: .hasProgressChallenge)
}
throw error
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| } catch { | |
| if error as! CherrishError == CherrishError.conflict { | |
| let _ = userDefaultService.save(false, key: .hasProgressChallenge) | |
| } | |
| throw error | |
| } | |
| } catch { | |
| if let cherrishError = error as? CherrishError, cherrishError == .conflict { | |
| let _ = userDefaultService.save(false, key: .hasProgressChallenge) | |
| } | |
| throw error | |
| } |
🧰 Tools
🪛 SwiftLint (0.57.0)
[Error] 43-43: Force casts should be avoided
(force_cast)
🤖 Prompt for AI Agents
In `@Cherrish-iOS/Cherrish-iOS/Data/Repository/DemoRepository.swift` around lines
42 - 47, The catch block in DemoRepository.swift force-casts the thrown error
with `error as! CherrishError`, which can crash for non-CherrishError errors;
change this to a safe cast (e.g., `if let chErr = error as? CherrishError` or
`guard let chErr = error as? CherrishError else { throw error }`) and only call
`userDefaultService.save(false, key: .hasProgressChallenge)` when `chErr ==
.conflict`, otherwise rethrow the original error; update the catch in the
function containing this logic to perform the safe cast and conditional save
before rethrowing.
| struct ChallengeCoordinatorView: View { | ||
| @EnvironmentObject private var challengeCoordinator: ChallengeCoordinator | ||
| @EnvironmentObject private var tabBarCoordinator: TabBarCoordinator | ||
| private let userDefaultService: UserDefaultService = DefaultUserDefaultService() |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
🧩 Analysis chain
🏁 Script executed:
rg -n "UserDefaultService" --type swift -C2Repository: TEAM-Cherrish/Cherrish-iOS
Length of output: 10776
🏁 Script executed:
cat -n Cherrish-iOS/Cherrish-iOS/Presentation/Feature/ChallengeView/Coordinator/ChallengeCoordinatorView.swiftRepository: TEAM-Cherrish/Cherrish-iOS
Length of output: 2055
🏁 Script executed:
cat -n Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Onboarding/SplashView.swift | head -20Repository: TEAM-Cherrish/Cherrish-iOS
Length of output: 669
의존성 주입 패턴 일관성 개선 필요
DefaultUserDefaultService()를 직접 인스턴스화하고 있습니다. 리포지토리들(HomeRepository, DemoRepository, ChallengeRepository 등)은 생성자 주입을 통해 UserDefaultService를 받고 있으며, SplashView처럼 같은 계층의 View 컴포넌트도 명시적 init() 메서드에서 기본 매개변수로 주입하는 패턴을 사용하고 있습니다.
다음과 같이 개선하면 테스트 시 mock 서비스 주입이 가능해지고 일관성이 향상됩니다:
init(userDefaultService: UserDefaultService = DefaultUserDefaultService()) {
self.userDefaultService = userDefaultService
}
🤖 Prompt for AI Agents
In
`@Cherrish-iOS/Cherrish-iOS/Presentation/Feature/ChallengeView/Coordinator/ChallengeCoordinatorView.swift`
at line 13, Change ChallengeCoordinatorView to accept UserDefaultService via
constructor injection instead of instantiating DefaultUserDefaultService inline:
add an init(userDefaultService: UserDefaultService =
DefaultUserDefaultService()) that assigns to the existing userDefaultService
property, remove the direct DefaultUserDefaultService() initialization, and keep
the property typed as UserDefaultService so tests can inject a mock and callers
can rely on the default.
🔗 연결된 이슈
📄 작업 내용