2023. 3. 29. 17:24ㆍiOS/이슈
유튜브, 인스타, 트위터 등 앱들을 사용할 때는 몰랐는데 생각보다 셀에서 영상이 재생되는 예제를 찾기 힘들었다. 상태 관리가 힘들어서 그런 것 같다.
그러던 중 아래와 같은 요구 사항이 추가되었다
피드 리스트에서 스크롤 시 중앙에 있는 비디오만 재생해주세요
구현 아이디어 1
[참고1] 테이블 뷰의 center 좌표를 구하고 헤당 좌표에 있는 셀의 비디오를 재생
재생 상태 관리는 이전에 재생한 cell을 변수로 저장
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
let point = self.convert(tableView.center, to: tableView)
guard let indexPath = tableView.indexPathForRow(at: point) else { return }
guard let capturedCell = tableView.cellForRow(at: indexPath) as? FeedCell else { return }
if savedCell?.feed.id != capturedCell.feed.id {
savedCell?.pause()
savedCell = capturedCell
savedCell?.play()
}
}
1. decelerate를 고려하지 않아 불필요한 호출이 생김
2. pause()가 되지 않는 예외 케이스가 생김
모든 케이스를 다 처리하지 못하는 상황 발생
GSPlayer의 feed example을 참고 함 해당 예제는 셀 하나가 화면 전체 크기인 유튜브 숏츠 형식이라 딱 알맞지는 않았다.
구현 아이디어 2
[참고2] visibleCell이 아니면 pause(), decelerate에 대한 분기를 나눠 play() 처리
play() 전 모든 visibleCell pause() 처리
실행 로직은 현재 셀의 절반 이상이 visible 영역에 놓이면 실행한다.
func checkPlay() {
let visibleCells = tableView.visibleCells.compactMap { $0 as? FeedCell }
guard visibleCells.count > 0 else { return }
visibleCells.forEach { $0.pause() }
let visibleFrame = CGRect(x: 0, y: tableView.contentOffset.y, width: tableView.bounds.width, height: tableView.bounds.height)
// 절반 이상 보일 경우에 재생
let visibleCell = visibleCells
.filter { visibleFrame.intersection($0.frame).height >= $0.frame.height / 2 }
.first
visibleCell?.play()
}
아이디어 2 보완
요구사항 1: 화면이 처음 로드 될 시 첫번째 비디오 피드가 화면에 보일 경우 재생
요구사항 2: 비디오 피드가 리스트의 마지막일 경우 스크롤 중앙에 오지 않아도 재생
요구사항 3: 리스트 화면에서 벗어날 경우 모든 비디오 pause()
checkPlay() 대신 centerCellStrategy() 메소드를 만듦
private func centerCellPlayStrategy() {
let visibleVideoCells = fetchVisibleVideoCells()
guard visibleVideoCells.count > 0 else { return }
pauseAllVideos()
// edge case) 요구사항 2 마지막 비디오 피드 재생
// 컨텐츠 오프셋이 끝에 가까운 경우를 체크
if tableView.contentOffset.y > tableView.contentSize.height - 100 {
visibleVideoCells.last?.play()
return
}
let center = CGPoint(x: tableView.center.x, y: tableView.center.y)
let point = self.convert(center, to: tableView)
guard
let indexPath = tableView.indexPathForRow(at: point),
let capturedCell = tableView.cellForRow(at: indexPath) as? VideoFeedCell
else {
isEnoughShownToPlay(visibleVideoCells.last!)
return
}
isEnoughShownToPlay(capturedCell)
}
// 요구사항 1: 피드리스트의 ViewWillAppear() 트리거에서
visibleVideoCells.first?.play() 실행
// 요구사항 3: 피드리스트의 VIewWillDisAppear() 트리거에서
visibleVIdeoCells.forEach { $0.pause() } 실행
포스팅할 항목 - 비디오 피드 구현 중 이슈들
Time observer & deinit
재생 전 깜빡거림
썸네일 자체, 썸네일 제대로 안 나옴, 썸네일 추출
의도치 않은 영상 재생
회전
참고 1 중앙 셀 값 얻기
참고 2 GSPlayer Shorts Play Logic
참고 3 ScrollView Delgate들
참고 4 동영상 피드 리스트 예제
'iOS > 이슈' 카테고리의 다른 글
Memory Leak (0) | 2023.10.31 |
---|---|
Nested ScrollView - 프로 프로필 피드 탭 구현 (0) | 2023.03.29 |
AVFoundation - 비디오의 인코딩(압축) 및 업로드(3) - 업로드 개선 (0) | 2023.03.21 |
AVFoundation - 비디오의 인코딩(압축) 및 업로드(2) - AssetReader / Writer 이용 (0) | 2023.03.20 |
AVFoundation - 비디오의 인코딩(압축) 및 업로드(1) - Export Session 이용 (0) | 2023.03.18 |