| 알람 울리는중 |
|---|
UIView.animate를 사용해 반복 애니메이션을 적용했더니 앱이 실행 중일 때는 정상적으로 동작하는것 처럼 보였다. init에서 한 번만 시작했기 때문일거라 추정함init에서 startAnimations()를 호출하고 뷰가 처음 생성될 때만 애니메이션이 시작되기 때문이다.init(time: String, date: String, title: String) {
self.time = time
self.date = date
self.title = title
super.init(frame: .zero)
configureUI()
setupLayout()
bindData()
startAnimations()
}
앱이 백그라운드로 갔다가 다시 활성화될 때는 init이 다시 호출되지 않아서 애니메이션이 중단되더라도 다시 시작되지 않는다!
그래서 해결방안으로 해당화면이 띄워졌을 때 다시 애니메이션을 시작해주는 처리가 필요했다
viewWillAppear에 넣어보기viewWillAppear나 viewDidAppear에 애니메이션 시작 코드를 넣으면 되는 것 아닌가 생각했음.override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
alarmRingView.startAnimations()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
alarmRingView.startAnimations()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
alarmRingView.stopAnimations()
}
NotificationCenter를 이용하기layoutSubviews만 두어번 써본거 같았는데 구체적으로 어떤 역할인지 알게 되어 좋았다📍 init
init(frame:)
init(coder:)
📍 didMoveToSuperview
override func didMoveToSuperview()
📍 didMoveToWindow
override func didMoveToWindow()
window != nil → 화면에 보임window == nil → 화면에서 사라짐📍 layoutSubviews
override func layoutSubviews()
📍 흐름정리
init -> didMoveToSuperview -> didMoveToWindow (화면 등장) -> layoutSubviews (레이아웃 계산) -> (필요시 반복) -> didMoveToWindow (화면에서 사라짐)
+) 📍 draw(_:)
override func draw(_ rect: CGRect)
UIView 생명주기는 뷰가 생성되고 → 화면에 붙고 → 레이아웃이 잡히는 과정
결론적으로 홈으로 나갔다가 다시 들어왔을 때 애니메이션이 멈추는 문제를 해결하기 위해 NotificationCenter를 사용했다.
앱이 다시 활성화될 때 발생하는 알림을 받아서 그 시점에 애니메이션을 다시 시작해주는 방식이다.
UIApplication.didBecomeActiveNotification을 기준으로 어떤 행동을 할지 결정함
NotificationCenter.default.addObserver(
self,
selector: #selector(handleDidBecomeActive),
name: UIApplication.didBecomeActiveNotification,
object: nil
)
@objc private func handleDidBecomeActive() {
restartAnimations()
}
private func restartAnimations() {
stopAnimations()
startAnimations()
}
private func stopAnimations() {
layer.removeAllAnimations()
circleContainerView.layer.removeAllAnimations()
alarmImageView.layer.removeAllAnimations()
circleContainerView.transform = .identity
alarmImageView.transform = .identity
}
removeAllAnimations(): 현재 레이어에 걸려 있는 애니메이션을 모두 제거해서 중복 실행이나 꼬임을 방지
transform = .identity: 뷰를 원래 상태로 되돌린 뒤 다시 시작해야 해서
identity를 사용해서 변형이 전혀 없는 기본 상태로 만듦
NotificationCenter.default.removeObserver(self): 메모리 문제나 다른 의도치 않은 오류가 발생할 수 있으므로 deinit에서 반드시 해제해야 함
deinit {
NotificationCenter.default.removeObserver(self)
}
didBecomeActiveNotification이 발생