-
Notifications
You must be signed in to change notification settings - Fork 10
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
부스트캠프 6기 iOS 코드 리뷰어 지원 #203
base: review
Are you sure you want to change the base?
Conversation
(boostcamp-2020#25 boostcamp-2020#26) ActivityScene TotalView 연결 및 Date PickerView 구현
(boostcamp-2020#97) feat: running split scene 구현
(boostcamp-2020#91) feat: Location accuracy에 따른 값 전송 유무 로직 추가
(boostcamp-2020#88) Motion Type에 따라 자동으로 러닝을 일시정지 및 재시작한다
…e <--> EditProfileScene)
(boostcamp-2020#191) fix: 다크모드 및 라이트모드 toggle시 annotation이 바뀌는 버그 수정
…/179 (boostcamp-2020#136, 161, 179) 및 코드 컨벤셔닝
fix: Calorie 누적 오류 Int -> Double
(boostcamp-2020#196)fix: pausedWorkout 사운드 문제
(boostcamp-2020#198) feat: split detail 데이터 바인딩
|
||
class SceneDelegate: UIResponder, UIWindowSceneDelegate { | ||
var window: UIWindow? | ||
var appCoordinator: AppCoordinator? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
var appCoordinator: AppCoordinator? | |
private var appCoordinator: AppCoordinator? |
사소한 부분이지만 접근제어를 가능한 닫아두는 것이 유지보수에 좋습니다.
예를들어 외부에서 appCoordinator에 접근해서 변경한다면 일관성 있는 동작을 보장하기 어려워집니다.
|
||
final class AppCoordinator: BasicCoordinator<Void> { | ||
override func start() { | ||
return showMainFlow() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return showMainFlow() | |
showMainFlow() |
여기서 return 을 해도 컴파일 에러는 발생하지 않지만
return 된 Void 값을 사용하지 않기 떄문에 return을 제거하는 것이 가독성에 좋아보입니다.
typealias CoordinationResult = ResultType | ||
|
||
let identifier = UUID() | ||
var navigationController: UINavigationController |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
var navigationController: UINavigationController | |
let navigationController: UINavigationController |
BasicCoordinator init 시에 navigationController를 할당하고 같은 객체를 계속 사용하게 되는데요.
더 이상 변경이 없음을 명확하게 알려주기 위해서 let 을 쓰는게 좋을 것 같아요.
init(navigationController: UINavigationController) { | ||
self.navigationController = navigationController | ||
navigationController.setNavigationBarHidden(true, animated: true) | ||
print("[Memory \(Date())] 🌈Coordinator🌈 \(Self.self) started") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
릴리즈된 앱에서 print 로그가 출력되는 것은 무의미하고 때로는 성능저하가 있을 수 있기 때문에 DEBUG 시에만 출력되도록 설정하는 것이 좋습니다. 아래와 같은 트릭을 사용하면 간편하게 개선할 수 있습니다.
public func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
#if DEBUG
Swift.print(items, separator: separator, terminator: terminator)
#endif
}
조금 더 심화된 학습을 해보고 싶다면 Logger를 직접 만들어보는 것도 좋습니다.
log Level에 따라서 메세지를 다르게 출력할 수 있습니다.
verbose, debug, info, warnings, error 단계로 나눠서 출력하고 error 시에는 리모트 서버 또는 디바이스 파일에 기록을 남기는 방법도 있습니다.
참고: https://github.com/emaloney/CleanroomLogger
runningEventSubject.send(.resume) | ||
} | ||
|
||
func setGoal(_ goalInfo: GoalInfo?) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
func setGoal(_ goalInfo: GoalInfo?) { | |
func setGoal(_ goalInfo: GoalInfo) { |
Optional이 아니어도 컴파일 에러는 없네요.
가능하면 init 시점에 GoalInfo를 주입하는 것으로 리팩토링 해봐도 좋을 것 같아요.
var runningInfoSubjects = [ | ||
RunningInfoTypeSubject(RunningInfo(type: .time)), | ||
RunningInfoTypeSubject(RunningInfo(type: .pace)), | ||
RunningInfoTypeSubject(RunningInfo(type: .averagePace)), | ||
RunningInfoTypeSubject(RunningInfo(type: .kilometer)), | ||
] | ||
var runningInfoTapAnimationSignal = PassthroughSubject<Int, Never>() | ||
var initialAnimationSignal = PassthroughSubject<Void, Never>() | ||
var resumeAnimationSignal = PassthroughSubject<Void, Never>() | ||
var showPausedRunningSignal = PassthroughSubject<Void, Never>() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
var runningInfoSubjects = [ | |
RunningInfoTypeSubject(RunningInfo(type: .time)), | |
RunningInfoTypeSubject(RunningInfo(type: .pace)), | |
RunningInfoTypeSubject(RunningInfo(type: .averagePace)), | |
RunningInfoTypeSubject(RunningInfo(type: .kilometer)), | |
] | |
var runningInfoTapAnimationSignal = PassthroughSubject<Int, Never>() | |
var initialAnimationSignal = PassthroughSubject<Void, Never>() | |
var resumeAnimationSignal = PassthroughSubject<Void, Never>() | |
var showPausedRunningSignal = PassthroughSubject<Void, Never>() | |
let runningInfoSubjects = [ | |
RunningInfoTypeSubject(RunningInfo(type: .time)), | |
RunningInfoTypeSubject(RunningInfo(type: .pace)), | |
RunningInfoTypeSubject(RunningInfo(type: .averagePace)), | |
RunningInfoTypeSubject(RunningInfo(type: .kilometer)), | |
] | |
let runningInfoTapAnimationSignal = PassthroughSubject<Int, Never>() | |
let initialAnimationSignal = PassthroughSubject<Void, Never>() | |
let resumeAnimationSignal = PassthroughSubject<Void, Never>() | |
let showPausedRunningSignal = PassthroughSubject<Void, Never>() |
프로토콜에서 var 로 되어있어서 그대로 유지하는 경우가 많은데요.
{ get } 으로만 프로퍼티 제약이 걸려있는 경우에 let 을 사용해도 충분한 상황이 있습니다.
navigationController.viewControllers = [runningPageVC] | ||
|
||
let uuid = runningCoordinator.identifier | ||
closeSubscription[uuid] = closablePublisher |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
현재는 closeSubscription에 직접 접근해서 변경하도록 되어있는데요.
BasicCoordinator
에서 private var closeSubscription
로 변경하고
아래의 함수와 비슷한 역할을 하는 함수가 있으면 더 명확할 것 같아요.
private func store<T>(coordinator: BasicCoordinator<T>) {
childCoordinators[coordinator.identifier] = coordinator
}
private lazy var pageControl = makePageControl() | ||
private lazy var backButton = makeBackButton() | ||
|
||
private var viewModel: RunningPageViewModelTypes? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private var viewModel: RunningPageViewModelTypes? | |
private let viewModel: RunningPageViewModelTypes |
init 시점에 viewModel이 주입되기 떄문에 optional이 아닌 타입으로 사용 가능합니다.
bindViewModel() | ||
|
||
view.layoutIfNeeded() | ||
distance = view.bounds.height - pageControl.center.y - buttonHeight / 2 - 30 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
viewDidLoad 이후에도 view.bounds 가 변경될 가능성이 있습니다.
viewDidLayoutSubviews 나 다른 lifecycle에서 계산해주는 것도 좋을 것 같아요.
|
||
import UIKit | ||
|
||
class ActivityDetailDataSource: NSObject, UITableViewDataSource { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UITableViewDataSource 구현을 따로 분리한 것도 좋은 시도 같아요 👍
ViewController 코드가 과도하게 증가하는 것을 막아줄 수 있겠네요.
No description provided.