179 lines
7.1 KiB
Swift
179 lines
7.1 KiB
Swift
//
|
||
// MPPositive_PlayerLoadViewModel.swift
|
||
// MusicPlayer
|
||
//
|
||
// Created by Mr.Zhou on 2024/5/9.
|
||
//
|
||
|
||
import UIKit
|
||
///播放器管理ViewModel
|
||
class MPPositive_PlayerLoadViewModel: NSObject {
|
||
/// 单曲常规列表
|
||
var songVideos:[MPPositive_SongItemModel]!
|
||
///随机播放列表
|
||
var randomVideos:[MPPositive_SongItemModel]!
|
||
///当前播放音乐ViewModel
|
||
var currentVideo:MPPositive_SongViewModel!{
|
||
didSet{
|
||
DispatchQueue.main.async {
|
||
[weak self] in
|
||
guard let self = self else {return}
|
||
if currentVideo != nil {
|
||
print("当前播放音乐是:\(currentVideo?.song?.title ?? "")")
|
||
//启动监听器
|
||
startObservingCurrentVideoItem()
|
||
//当值变化时通知播放器页面,更新UI
|
||
NotificationCenter.notificationKey.post(notificationName: .positive_player_reload)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//监听器
|
||
private var itemObservation: NSKeyValueObservation?
|
||
// private var loadQueue:DispatchQueue!
|
||
///异步请求组
|
||
// private var group:DispatchGroup!
|
||
///单曲播放队列ViewModel
|
||
var listViewVideos:[MPPositive_SongViewModel]!
|
||
///palyer管理model初始化方法
|
||
/// - Parameters:
|
||
/// - songs: 全部歌曲列表
|
||
/// - firstVideoId: 需要播放的第一首歌
|
||
init(_ songs:[MPPositive_SongItemModel], currentVideoId: String) {
|
||
super.init()
|
||
self.songVideos = songs
|
||
//根据列表生成一份随机播放列表
|
||
self.randomVideos = self.songVideos.shuffled()
|
||
self.listViewVideos = []
|
||
|
||
}
|
||
//启动对于当前音乐的监听器
|
||
private func startObservingCurrentVideoItem() {
|
||
itemObservation?.invalidate() // 先移除旧的监听
|
||
//判断当前currentVideo是否已经加载完数据了
|
||
if currentVideo?.resourcePlayerItem != nil {
|
||
//数据已经加载完毕了
|
||
postNoticeAction()
|
||
}else {
|
||
//添加新的监听
|
||
itemObservation = currentVideo?.observe(\.resourcePlayerItem, options: [.new], changeHandler: { [weak self] video, change in
|
||
guard let self = self else {return}
|
||
if change.newValue != nil {
|
||
// 在这里处理 newItem 的值变化
|
||
postNoticeAction()
|
||
}else {
|
||
//获取到值是nil
|
||
print("无效更新")
|
||
}
|
||
})
|
||
}
|
||
}
|
||
//发起通知告诉播放器已经切换了播放音乐
|
||
private func postNoticeAction() {
|
||
DispatchQueue.main.async {
|
||
[weak self] in
|
||
guard let self = self else {return}
|
||
if currentVideo != nil {
|
||
MP_AnalyticsManager.shared.player_b_pvAction(currentVideo.song.videoId, videoname: currentVideo.title ?? "", artistname: currentVideo.song.shortBylineText ?? "")
|
||
//当值变化时通知播放器页面,更新UI
|
||
NotificationCenter.notificationKey.post(notificationName: .positive_player_reload, object: currentVideo)
|
||
}
|
||
}
|
||
}
|
||
|
||
///将选中Video的上1位,下两位项包括本身总计4项Video进行补全转为ViewModel,并播放这首音乐
|
||
func improveData(_ targetVideoId:String, isRandom:Bool = false) {
|
||
//对于选中Video的集合
|
||
var array:[MPPositive_SongItemModel] = []
|
||
if isRandom {
|
||
//获取targetVideoId的索引
|
||
guard let targetIndex = self.randomVideos.firstIndex(where: {$0.videoId == targetVideoId}) else {
|
||
return
|
||
}
|
||
array.append(self.randomVideos[targetIndex])
|
||
// //获取上一位
|
||
// let previousIndex = targetIndex-1
|
||
// if previousIndex >= 0 {
|
||
// array.append(self.randomVideos[previousIndex])
|
||
// }
|
||
let nextIndex = targetIndex+1
|
||
let lastIndex = targetIndex+2
|
||
if nextIndex < randomVideos.count {
|
||
array.append(self.randomVideos[nextIndex])
|
||
}
|
||
if lastIndex < randomVideos.count {
|
||
array.append(self.randomVideos[lastIndex])
|
||
}
|
||
}else {
|
||
//获取targetVideoId的索引
|
||
guard let targetIndex = self.songVideos.firstIndex(where: {$0.videoId == targetVideoId}) else {
|
||
return
|
||
}
|
||
array.append(self.songVideos[targetIndex])
|
||
// //获取上一位
|
||
// let previousIndex = targetIndex-1
|
||
// if previousIndex >= 0 {
|
||
// array.append(self.songVideos[previousIndex])
|
||
// }
|
||
let nextIndex = targetIndex+1
|
||
let lastIndex = targetIndex+2
|
||
if nextIndex < songVideos.count {
|
||
array.append(self.songVideos[nextIndex])
|
||
}
|
||
if lastIndex < songVideos.count {
|
||
array.append(self.songVideos[lastIndex])
|
||
}
|
||
}
|
||
//获取完成,优先检索ViewModel,看看是否已存在补完video
|
||
let videoIDs = Set(listViewVideos.map({$0.song.videoId}))
|
||
//比较videoID,去掉已经补完的内容
|
||
array = array.filter({!videoIDs.contains($0.videoId)})
|
||
//全部转化为MPPositive_SongViewModel
|
||
let viewModels = array.map({(MPPositive_SongViewModel($0))})
|
||
//添加新的ViewModel
|
||
self.listViewVideos.append(contentsOf: viewModels)
|
||
// //只保留最后5首
|
||
self.listViewVideos = self.listViewVideos.suffix(4)
|
||
//更新当前播放音乐
|
||
self.currentVideo = self.listViewVideos.first(where: {$0.song.videoId == targetVideoId})
|
||
}
|
||
///重新获取指定歌曲资源
|
||
func remakeImproveData(_ completion:@escaping (() -> Void)) {
|
||
currentVideo.configure()
|
||
completion()
|
||
}
|
||
|
||
///移除选中的song,并更新listViewVideos,移除相同index的值
|
||
func removeData(_ targetVideoId:String) {
|
||
let targetIndex = songVideos.firstIndex(where: {$0.videoId == targetVideoId}) ?? 0
|
||
//将选中的音乐移除,同时更新listView
|
||
songVideos = songVideos.filter({$0.videoId != targetVideoId})
|
||
randomVideos = randomVideos.filter({$0.videoId != targetVideoId})
|
||
listViewVideos = listViewVideos.filter({$0.song.videoId != targetVideoId})
|
||
if currentVideo != nil {
|
||
//判断是否当前音乐
|
||
if currentVideo.song.videoId == targetVideoId {
|
||
//判断targetIndex是否大于最大音乐值
|
||
if targetIndex < songVideos.count {
|
||
let videoId = songVideos[targetIndex].videoId ?? ""
|
||
improveData(videoId)
|
||
}else {
|
||
//移除的是原来最后一首音乐,播放新的最后一首音乐
|
||
let videoId = songVideos.last?.videoId ?? ""
|
||
improveData(videoId)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//销毁时
|
||
deinit {
|
||
itemObservation?.invalidate()
|
||
//释放所有数据
|
||
songVideos = nil
|
||
currentVideo = nil
|
||
randomVideos = nil
|
||
listViewVideos = nil
|
||
}
|
||
}
|