찹모찌의 기록일지
iOS에서 영상을 재생시키면서 생긴 문제(addPeriodicTimeObserver, NotificationCenter Observer) 본문
iOS에서 영상을 재생시키면서 생긴 문제(addPeriodicTimeObserver, NotificationCenter Observer)
찹모찌 2024. 3. 1. 23:42영상을 재생시킬 때 어떤 문제가 발생할 수 있을까?

위의 gif처럼 영상(AVPlayer)를 UICollectionView의 각 cell에 담아 영상 시청 기능을 구현했다. 그러나 프로젝트를 진행하면서 영상을 시청하다 뒤로 나가거나, 아니면 계속 스크롤하며 다음 cell의 영상을 재생했을 때 기존에 시청했던 영상이 재생되는 문제가 발생했다.
결국 ViewController의 deinit이 호출되지 않는다는 점을 확인하고, Memory graph에서 Observer가 해제되지 않고 계속 동작하는 것을 확인하고 문제를 해결했다.
이처럼 AVPlayerLayer를 커스텀해서 사용할 때, UISlider를 이용하여 재생바를 만들어 두거나 영상을 반복 재생시키기 위해 Notification Center를 이용하거나 했을 때 생기는 문제점을 정리했다.
1) addPeriodicTimeObserver

addPeriodicTimeObserver를 통해 player의 상태를 감지할 수 있는데, 이때 Observer를 제거해주지 않는다면?
사용자가 player가 있는 화면을 벗어난 뒤에도 Observer는 계속 player를 감지할 것이고 그렇다면 확실한 동작을 보장받지 못할 수 있다.
이런 문제가 발생하기 때문에 Apple에서는 addPeriodicTimeObserver는 Any 타입의 Observer를 반환하며 removeTimeObserver를 통해 이를 제거하도록 한다.

removeTimeObserver는 이전에 등록된 observer를 제거한다.
func removePeriodicTimeObserver() {
// If a time observer exists, remove it
if let token = timeObserverToken {
player.removeTimeObserver(token)
timeObserverToken = nil
}
}
이때 필자는… timeObserverToken을 제거하다가 또 다른 문제를 겪었다.

An instance of AVPlayer cannot remove a time observer that was added by a different instance of AVPlayer란 에러를 겪었는데, removeTimeObserver를 쓸 때는 꼭 같은 인스턴스, 즉 addPeriodicTimeObserver를 한 곳과 같은 데에서 remove를 해줘야 한다.
셀 재사용 시 기존 셀의 Token을 nil로 초기화 하지 않을 경우 이런 문제가 왜 발생할 수 있냐면, 콜렉션뷰와 같이 셀을 재사용하는 구간에서 timeObserverToken이 이전에 사용한 observer로 남아있을 수 있기 때문이다.
그래서 nil로 꼭 초기화 하는 동작이 필요하다.
2) NotificationCenter Observer

AVPlayer에 Player가 종료됐을때(endTime) 다시 처음으로 되돌아가 Play하라고 Observer를 걸어놨는데, 재사용을 생각안하고 remove를 안해줘 하나의 Cell에 있는 Player만 종료돼도 다른 Observer가 걸려있는 셀들에 전달되어 Play를 시켜버리는 문제가 발생하였다.
이런 문제를 겪고 UICollectionView를 사용할 때는 꼭 재사용을 생각해 Observer를 제거하는 동작이 필요하다는 것을 깨달았다.
'iOS' 카테고리의 다른 글
내 앨범이 너에게 닿기를: 서버 없이 앨범 전달받기 (0) | 2024.03.15 |
---|---|
설명 뷰가 늘어나면서 올라왔으면 좋겠습니다(애니메이션 구현기). (0) | 2024.03.09 |
숏폼 플랫폼 재생 화면 정보를 불러올 때는 어떻게 불러오는게 좋을까? (1) | 2024.03.08 |
Swift Concurrency와 UICollectionView Prefetch (0) | 2024.03.02 |
iOS에서 영상 재생하기 (0) | 2024.03.01 |