对网络波动情况的初级调试

This commit is contained in:
Mr.zhou 2024-05-22 14:25:58 +08:00
parent c8cf604c59
commit 26a46c83a3
11 changed files with 294 additions and 153 deletions

View File

@ -40,6 +40,7 @@
CBB5F1F92BFC35D000CBF73A /* MPPositive_CollectionSongModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBB5F1F82BFC35D000CBF73A /* MPPositive_CollectionSongModel.swift */; };
CBB5F1FB2BFC3DB600CBF73A /* MPPositive_CollectionListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBB5F1FA2BFC3DB600CBF73A /* MPPositive_CollectionListModel.swift */; };
CBB5F1FD2BFC40E400CBF73A /* MPPositive_CollectionArtistModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBB5F1FC2BFC40E400CBF73A /* MPPositive_CollectionArtistModel.swift */; };
CBB5F1FF2BFCB40000CBF73A /* MPPositive_Debouncer.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBB5F1FE2BFCB40000CBF73A /* MPPositive_Debouncer.swift */; };
CBB75B0B2BEF0BC400B3FF9A /* MPPositive_DownloadItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBB75B0A2BEF0BC400B3FF9A /* MPPositive_DownloadItemModel.swift */; };
CBB9F9DD2BEDCFEE008338DE /* MPPositive_JsonLyrics.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBB9F9DC2BEDCFEE008338DE /* MPPositive_JsonLyrics.swift */; };
CBB9F9DF2BEDDCC5008338DE /* MP_PlayerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBB9F9DE2BEDDCC5008338DE /* MP_PlayerManager.swift */; };
@ -229,6 +230,7 @@
CBB5F1F82BFC35D000CBF73A /* MPPositive_CollectionSongModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_CollectionSongModel.swift; sourceTree = "<group>"; };
CBB5F1FA2BFC3DB600CBF73A /* MPPositive_CollectionListModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_CollectionListModel.swift; sourceTree = "<group>"; };
CBB5F1FC2BFC40E400CBF73A /* MPPositive_CollectionArtistModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_CollectionArtistModel.swift; sourceTree = "<group>"; };
CBB5F1FE2BFCB40000CBF73A /* MPPositive_Debouncer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_Debouncer.swift; sourceTree = "<group>"; };
CBB75B0A2BEF0BC400B3FF9A /* MPPositive_DownloadItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_DownloadItemModel.swift; sourceTree = "<group>"; };
CBB9F9DC2BEDCFEE008338DE /* MPPositive_JsonLyrics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_JsonLyrics.swift; sourceTree = "<group>"; };
CBB9F9DE2BEDDCC5008338DE /* MP_PlayerManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MP_PlayerManager.swift; sourceTree = "<group>"; };
@ -964,6 +966,7 @@
CBCB32192BD7578500802900 /* MP_LocationManager.swift */,
CBBFA9172BBA83BA00057FD5 /* MP_CoreDataHandlerManager.swift */,
CBE2C4C62BC783F700F283A7 /* MP_HUD.swift */,
CBB5F1FE2BFCB40000CBF73A /* MPPositive_Debouncer.swift */,
CBC687482BC2882B0023ECA6 /* MPTableManager.swift */,
CBD958D12BB6600500666B0D /* MP_PlayerSlider.swift */,
CB102F532BFAFA7200E967D8 /* MP_CircularProgressView.swift */,
@ -1172,6 +1175,7 @@
CB102F522BFAE73800E967D8 /* MPPositive_JsonRecommend.swift in Sources */,
CBCB4FEF2BD11402009760B3 /* MPSideA_NavigationController.swift in Sources */,
CBF456DD2BF1E72F00ABF761 /* MPPositive_SearchResultListViewModel.swift in Sources */,
CBB5F1FF2BFCB40000CBF73A /* MPPositive_Debouncer.swift in Sources */,
CBEB01832BF5D88400D45006 /* MPPositive_ArtistShowCollectionViewCell.swift in Sources */,
CBD5E80C2BF33D0200A3EBED /* MPPositive_SearchResultTypeShowView.swift in Sources */,
CBCB35212BD7ACE900802900 /* MPPositive_JsonBrowse.swift in Sources */,

View File

@ -49,6 +49,18 @@
ReferencedContainer = "container:MusicPlayer.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<EnvironmentVariables>
<EnvironmentVariable
key = "IDERedirectionPolicy"
value = "oslogToStdio"
isEnabled = "YES">
</EnvironmentVariable>
<EnvironmentVariable
key = "OS_ACTIVITY_MODE"
value = "disable"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"

View File

@ -22,6 +22,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
}
}
setAudioSupport()
MP_NetWorkManager.shared.requestStatusToYouTube()
IQKeyboardManager.shared.enable = true
IQKeyboardManager.shared.shouldResignOnTouchOutside = true
window = UIWindow(frame: UIScreen.main.bounds)

View File

@ -83,6 +83,10 @@ extension NotificationCenter{
case player_type_switch
///
case player_delete_list
///-
case net_switch_notReachable
///-
case net_switch_reachable
}
}
}

View File

@ -0,0 +1,33 @@
//
// MPPositive_Debouncer.swift
// MusicPlayer
//
// Created by Mr.Zhou on 2024/5/21.
//
import UIKit
class MPPositive_Debouncer: NSObject {
static let shared = MPPositive_Debouncer()
//
private var timer: Timer?
//
private var delay: TimeInterval
private override init() {
delay = 0.4
super.init()
}
deinit {
timer?.invalidate()
timer = nil
}
func call(_ action:@escaping (() -> Void)) {
//
timer?.invalidate()
//
timer = Timer.scheduledTimer(withTimeInterval: delay, repeats: false) { _ in
action()
}
}
}

View File

@ -37,6 +37,30 @@ class MP_NetWorkManager: NSObject {
private let search = "/search"
///YouTuBe
private let youTubeKeys:[String] = ["MUSIC_VIDEO_TYPE_ATV","MUSIC_VIDEO_TYPE_OMV","MUSIC_PAGE_TYPE_ALBUM","MUSIC_PAGE_TYPE_ARTIST","MUSIC_PAGE_TYPE_PLAYLIST","MUSIC_PAGE_TYPE_TRACK_LYRICS","MUSIC_PAGE_TYPE_TRACK_RELATED"]
///
enum NetWorkStatus: String {
case notReachable = "网络不可用"
case unknown = "网络未知"
case reachable = "网络可用"
}
private var netWorkStatu:NetWorkStatus = .reachable{
willSet{
DispatchQueue.main.async {
[weak self] in
guard let self = self else {return}
//
if netWorkStatu == .reachable, newValue == .notReachable {
print("网络不可用")
NotificationCenter.notificationKey.post(notificationName: .net_switch_notReachable)
}
//
if netWorkStatu == .notReachable, newValue == .reachable {
print("网络可用")
NotificationCenter.notificationKey.post(notificationName: .net_switch_reachable)
}
}
}
}
//MARK: -
//访
private var visitorData:String?
@ -133,24 +157,23 @@ class MP_NetWorkManager: NSObject {
monitor.start(queue: queue)
}
///
private func requestStatusToYouTube(_ isAilable:@escaping(Bool) -> Void) {
func requestStatusToYouTube() {
//
let reachabilityManager = NetworkReachabilityManager(host: "https://music.youtube.com/")
//ping
reachabilityManager?.startListening(onUpdatePerforming: { status in
reachabilityManager?.startListening(onQueue: .main, onUpdatePerforming: { [weak self] status in
guard let self = self else {return}
switch status {
case .unknown://
isAilable(false)
print("网络情况未知")
netWorkStatu = .unknown
case .notReachable://
isAilable(false)
print("网络不可用")
netWorkStatu = .notReachable
case .reachable(.ethernetOrWiFi), .reachable(.cellular)://
//
isAilable(true)
netWorkStatu = .reachable
}
})
}
}
//MARK: - API
extension MP_NetWorkManager {
@ -189,11 +212,8 @@ extension MP_NetWorkManager {
]
]
]
requestStatusToYouTube { isAvailable in
if isAvailable == true {
self.requestPostHomeBrowse(url, parameters: parameters)
}
}
guard netWorkStatu != .notReachable else {return}
requestPostHomeBrowse(url, parameters: parameters)
}
}
@ -255,14 +275,11 @@ extension MP_NetWorkManager {
]
]
]
requestStatusToYouTube { isAvailable in
if isAvailable == true {
self.requestPostAlbumOrList(url, parameters: parameters) { results in
guard netWorkStatu != .notReachable else {return}
requestPostAlbumOrList(url, parameters: parameters) { results in
comletion(results)
}
}
}
}
///
private func requestPostAlbumOrList(_ url:URL, parameters:Parameters, comletion:@escaping (MPPositive_ListAlbumListViewModel) -> Void) {
//postRootBrowses
@ -315,14 +332,11 @@ extension MP_NetWorkManager {
]
]
]
requestStatusToYouTube { isAvailable in
if isAvailable == true {
self.requestPostArtist(url, parameters: parameters) { result in
guard netWorkStatu != .notReachable else {return}
requestPostArtist(url, parameters: parameters) { result in
comletion(result)
}
}
}
}
//
private func requestPostArtist(_ url:URL, parameters:Parameters, comletion:@escaping (MPPositive_ArtistViewModel) -> Void) {
//postRootBrowses
@ -374,14 +388,11 @@ extension MP_NetWorkManager {
]
]
]
requestStatusToYouTube { isAvailable in
if isAvailable == true {
self.requestPostArtistMore(url, parameters: parameters) { result in
guard netWorkStatu != .notReachable else {return}
requestPostArtistMore(url, parameters: parameters) { result in
comletion(result)
}
}
}
}
///
private func requestPostArtistMore(_ url:URL, parameters:Parameters, comletion:@escaping (([MPPositive_BrowseItemViewModel], String?, String?)) -> Void) {
//postRootBrowses
@ -430,14 +441,11 @@ extension MP_NetWorkManager {
]
]
]
requestStatusToYouTube { isAvailable in
if isAvailable == true {
self.requestPostArtistMoreContinuation(url, parameters: parameters) { result in
guard netWorkStatu != .notReachable else {return}
requestPostArtistMoreContinuation(url, parameters: parameters) { result in
comletion(result)
}
}
}
}
///
private func requestPostArtistMoreContinuation(_ url:URL, parameters:Parameters, comletion:@escaping (([MPPositive_BrowseItemViewModel], String?, String?)) -> Void) {
//postRootBrowses
@ -487,16 +495,12 @@ extension MP_NetWorkManager {
]
]
]
requestStatusToYouTube { isAvailable in
if isAvailable == true {
//next
self.requestPostNextList(url, parameters: parameters) { listSongs in
guard netWorkStatu != .notReachable else {return}
requestPostNextList(url, parameters: parameters) { listSongs in
//
completion(listSongs)
}
}
}
}
//next
private func requestPostNextList(_ url:URL, parameters:Parameters, completion:@escaping (([MPPositive_SongItemModel]) -> Void)) {
//post
@ -542,15 +546,11 @@ extension MP_NetWorkManager {
]
]
]
requestStatusToYouTube { isAvailable in
if isAvailable == true {
//next/
self.requestPostNextLyricsAndRelated(url, parameters: parameters) { result in
guard netWorkStatu != .notReachable else {return}
requestPostNextLyricsAndRelated(url, parameters: parameters) { result in
completion(result)
}
}
}
}
//Next/
private func requestPostNextLyricsAndRelated(_ url:URL, parameters:Parameters, completion:@escaping(((String?,String?)) -> Void)) {
//post
@ -596,14 +596,11 @@ extension MP_NetWorkManager {
]
]
]
requestStatusToYouTube { isAvailable in
if isAvailable == true {
self.requestPostPlayer(url, parameters: parameters){ resourceUlrs, coverUrls in
guard netWorkStatu != .notReachable else {return}
requestPostPlayer(url, parameters: parameters){ resourceUlrs, coverUrls in
completion(resourceUlrs, coverUrls)
}
}
}
}
///
private func requestPostPlayer(_ url:URL, parameters:Parameters, completion:@escaping((([String],[String]), [String]?) -> Void)) {
//post
@ -651,14 +648,11 @@ extension MP_NetWorkManager {
]
]
]
requestStatusToYouTube { isAvailable in
if isAvailable == true {
self.requestPostLyric(url, parameters: parameters) { lyrics in
guard netWorkStatu != .notReachable else {return}
requestPostLyric(url, parameters: parameters) { lyrics in
completion(lyrics)
}
}
}
}
//
private func requestPostLyric(_ url:URL, parameters:Parameters, completion:@escaping((String) -> Void)) {
//post
@ -701,14 +695,11 @@ extension MP_NetWorkManager {
]
]
]
requestStatusToYouTube { isAvailable in
if isAvailable == true {
self.requestPostRecommend(url, parameters: parameters) { results in
guard netWorkStatu != .notReachable else {return}
requestPostRecommend(url, parameters: parameters) { results in
completion(results)
}
}
}
}
///
private func requestPostRecommend(_ url:URL, parameters:Parameters, completion: @escaping ([MPPositive_RecommendListViewModel]) -> Void) {
//post
@ -757,14 +748,11 @@ extension MP_NetWorkManager {
]
]
]
requestStatusToYouTube { isAvailable in
if isAvailable == true {
self.requestPostSearchSuggestions(url, parameters: parameters) { result in
guard netWorkStatu != .notReachable else {return}
requestPostSearchSuggestions(url, parameters: parameters) { result in
completion(result)
}
}
}
}
//
private func requestPostSearchSuggestions(_ url:URL, parameters:Parameters, completion:@escaping(([[MPPositive_SearchSuggestionItemModel]]) -> Void)) {
//post
@ -811,14 +799,11 @@ extension MP_NetWorkManager {
]
]
]
requestStatusToYouTube { isAvailable in
if isAvailable == true {
self.requestPostSearchPreviewResults(url, parameters: parameters) { result in
guard netWorkStatu != .notReachable else {return}
requestPostSearchPreviewResults(url, parameters: parameters) { result in
completion(result)
}
}
}
}
//
private func requestPostSearchPreviewResults(_ url:URL, parameters:Parameters, completion:@escaping (([MPPositive_SearchResultListViewModel]) -> Void)) {
//post
@ -871,14 +856,11 @@ extension MP_NetWorkManager {
]
]
]
requestStatusToYouTube { isAvailable in
if isAvailable == true {
self.requestPostSearchTypeResults(url, parameters: parameters) { result in
guard netWorkStatu != .notReachable else {return}
requestPostSearchTypeResults(url, parameters: parameters) { result in
completion(result)
}
}
}
}
//
private func requestPostSearchTypeResults(_ url:URL, parameters:Parameters, completion:@escaping (([MPPositive_SearchResultItemViewModel], String?, String?))->Void) {
//post
@ -931,14 +913,11 @@ extension MP_NetWorkManager {
]
]
]
requestStatusToYouTube { isAvailable in
if isAvailable == true {
self.requestPostSearchTypeContinuation(url, parameters: parameters) { result in
guard netWorkStatu != .notReachable else {return}
requestPostSearchTypeContinuation(url, parameters: parameters) { result in
completion(result)
}
}
}
}
//
private func requestPostSearchTypeContinuation(_ url:URL, parameters:Parameters, completion:@escaping (([MPPositive_SearchResultItemViewModel], String?, String?))->Void) {
//post

View File

@ -103,7 +103,10 @@ class MP_PlayerManager:NSObject{
super.init()
//
NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishPlaying(_ :)), name: .AVPlayerItemDidPlayToEndTime, object: player.currentItem)
//
NotificationCenter.notificationKey.add(observer: self, selector: #selector(userSwitchCurrentVideoAction(_ :)), notificationName: .positive_player_reload)
//
NotificationCenter.notificationKey.add(observer: self, selector: #selector(netWorkReachableAction(_ :)), notificationName: .net_switch_reachable)
}
deinit {
NotificationCenter.default.removeObserver(self)
@ -160,7 +163,23 @@ class MP_PlayerManager:NSObject{
loadPlayer.currentVideo?.resourcePlayerItem?.addObserver(self, forKeyPath: "status", options: [.old,.new], context: nil)
//
loadPlayer.currentVideo?.resourcePlayerItem.addObserver(self, forKeyPath: "loadedTimeRanges", options: [.old,.new], context: nil)
//
loadPlayer.currentVideo?.resourcePlayerItem.addObserver(self, forKeyPath: "playbackLikelyToKeepUp", options: [.old,.new], context: nil)
//
loadPlayer.listViewVideos.forEach({$0.preloadAsset($0.resourceAsset)})
}
///
@objc private func netWorkReachableAction(_ sender:Notification) {
//
if loadPlayer.currentVideo != nil {
//
let currentTime = loadPlayer.currentVideo!.resourcePlayerItem.currentTime()
//
player.play()
playState = .Playing
}
}
//KVO
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
guard let keyPath = keyPath else {
@ -174,14 +193,6 @@ class MP_PlayerManager:NSObject{
if playState != .Playing {
//statuVlaueplayerItem
print("当前音乐-\(loadPlayer.currentVideo?.title ?? "") 已经准备好播放")
//
print("开始播放音乐-\(loadPlayer.currentVideo?.title ?? "")")
player.play()
playState = .Playing
//
if startActionBlock != nil {
startActionBlock!()
}
}
}else {
print("当前音乐-\(loadPlayer.currentVideo?.title ?? "") 未做好准备播放,失败原因是\(loadPlayer.currentVideo?.resourcePlayerItem.error?.localizedDescription ?? "")")
@ -211,7 +222,22 @@ class MP_PlayerManager:NSObject{
}
case "playbackLikelyToKeepUp"://
break
if let playbackLikelyToKeepUp = change?[.newKey] as? Bool, playbackLikelyToKeepUp == true {
if playState != .Playing {
//
print("播放音乐-\(loadPlayer.currentVideo?.title ?? "")")
player.play()
playState = .Playing
//
if startActionBlock != nil {
startActionBlock!()
}
}
}else {
//
player.pause()
playState = .Null
}
default:
break
}
@ -324,7 +350,7 @@ class MP_PlayerManager:NSObject{
switch playType {
case .random://
for (index, item) in loadPlayer.randomVideos.enumerated() {
if item.videoId == loadPlayer.currentVideo.song.videoId {
if item.videoId == loadPlayer.currentVideo?.song.videoId {
//
nextIndex = index - 1
}
@ -333,15 +359,15 @@ class MP_PlayerManager:NSObject{
if nextIndex < 0 {
//
let last = loadPlayer.randomVideos.last
loadPlayer.improveData(last?.videoId ?? "")
loadPlayer.improveData(last?.videoId ?? "", isRandom: true)
}else {
//
let song = loadPlayer.randomVideos[nextIndex]
loadPlayer.improveData(song.videoId ?? "")
loadPlayer.improveData(song.videoId ?? "", isRandom: true)
}
default://
for (index, item) in loadPlayer.songVideos.enumerated() {
if item.videoId == loadPlayer.currentVideo.song.videoId {
if item.videoId == loadPlayer.currentVideo?.song.videoId {
//
nextIndex = index - 1
}
@ -366,7 +392,7 @@ class MP_PlayerManager:NSObject{
switch playType {
case .random:
for (index, item) in loadPlayer.randomVideos.enumerated() {
if item.videoId == loadPlayer.currentVideo.song.videoId {
if item.videoId == loadPlayer.currentVideo?.song.videoId {
//
nextIndex = index + 1
}
@ -375,15 +401,15 @@ class MP_PlayerManager:NSObject{
if nextIndex > (loadPlayer.randomVideos.count-1) {
//
let first = loadPlayer.randomVideos.first
loadPlayer.improveData(first?.videoId ?? "")
loadPlayer.improveData(first?.videoId ?? "", isRandom: true)
}else {
//,ID
let song = loadPlayer.randomVideos[nextIndex]
loadPlayer.improveData(song.videoId ?? "")
loadPlayer.improveData(song.videoId ?? "", isRandom: true)
}
default:
for (index, item) in loadPlayer.songVideos.enumerated() {
if item.videoId == loadPlayer.currentVideo.song.videoId {
if item.videoId == loadPlayer.currentVideo?.song.videoId {
//
nextIndex = index + 1
}
@ -411,7 +437,10 @@ class MP_PlayerManager:NSObject{
//KVO
video.resourcePlayerItem.removeObserver(self, forKeyPath: "status")
video.resourcePlayerItem.removeObserver(self, forKeyPath: "loadedTimeRanges")
// video.resourcePlayerItem.removeObserver(self, forKeyPath: "playbackLikelyToKeepUp")
video.resourcePlayerItem.removeObserver(self, forKeyPath: "playbackLikelyToKeepUp")
}
if cacheValueBlock != nil {
cacheValueBlock!(0, 1)
}
if loadPlayer.currentVideo != nil {
//

View File

@ -33,13 +33,19 @@ class MPPositive_SongViewModel: NSObject {
var song:MPPositive_SongItemModel!
///
var isPloading:Bool = false
//
private var isCancelled = false
init(_ song:MPPositive_SongItemModel) {
super.init()
self.song = song
configure()
}
deinit {
//
resourcePlayerItem = nil
resourceAsset = nil
isCancelled = true
print("\(title ?? "")被释放了")
}
//
private func configure() {
@ -76,9 +82,9 @@ class MPPositive_SongViewModel: NSObject {
}
reloadCollectionAndDownLoad()
//
if isPloading == false {
preloadAsset(resourceAsset)
}
// if isPloading == false {
// preloadAsset(resourceAsset)
// }
}
//
func reloadCollectionAndDownLoad() {
@ -91,12 +97,19 @@ class MPPositive_SongViewModel: NSObject {
//
func preloadAsset(_ asset:AVURLAsset) {
guard isPloading == false else {
return
}
self.isPloading = true
//
if #available(iOS 16, *) {
//ios16
Task{
do{
let playable = try await asset.load(.isPlayable)
guard !isCancelled else {
return
}
if playable == true {
print("\(self.title ?? "")预加载成功")
self.isPloading = true
@ -105,8 +118,9 @@ class MPPositive_SongViewModel: NSObject {
switch asset.status(of: .isPlayable) {
case .failed(let erro):
print("\(title ?? "")预加载失败,失败原因:\(erro.localizedDescription)")
self.isPloading = false
default:
break
self.isPloading = false
}
}
}catch{
@ -118,7 +132,7 @@ class MPPositive_SongViewModel: NSObject {
let keys = ["playable"]
asset.loadValuesAsynchronously(forKeys: keys) {
[weak self] in
guard let self = self else {return}
guard let self = self, !isCancelled else {return}
for key in keys {
var error: NSError? = nil
let status = asset.statusOfValue(forKey: key, error: &error)
@ -131,8 +145,10 @@ class MPPositive_SongViewModel: NSObject {
}
case .failed:
print("\(title ?? "")预加载失败,失败原因:\(error?.localizedDescription ?? "")")
self.isPloading = false
case .cancelled:
print("\(title ?? "")预加载被取消了")
self.isPloading = false
default:
break
}

View File

@ -26,9 +26,8 @@ class MPPositive_PlayerLoadViewModel: NSObject {
}
}
}
///ID
var currentVideoId:String!
///ViewModel
///ViewModel
var listViewVideos:[MPPositive_SongViewModel]!
///
var group:DispatchGroup?
@ -42,17 +41,32 @@ class MPPositive_PlayerLoadViewModel: NSObject {
//
self.randomVideos = self.songVideos.shuffled()
self.listViewVideos = []
self.currentVideoId = currentVideoId
}
///Video23VideoViewModel,
func improveData(_ targetVideoId:String) {
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
if nextIndex < randomVideos.count {
array.append(self.randomVideos[nextIndex])
}
}else {
//targetVideoId
guard let targetIndex = self.songVideos.firstIndex(where: {$0.videoId == targetVideoId}) else {
return
}
//Video
var array:[MPPositive_SongItemModel] = []
array.append(self.songVideos[targetIndex])
//
let previousIndex = targetIndex-1
@ -63,6 +77,7 @@ class MPPositive_PlayerLoadViewModel: NSObject {
if nextIndex < songVideos.count {
array.append(self.songVideos[nextIndex])
}
}
//ViewModelvideo
let videoIDs = Set(listViewVideos.map({$0.song.videoId}))
//videoID,
@ -89,11 +104,12 @@ class MPPositive_PlayerLoadViewModel: NSObject {
}
}
group?.notify(queue: .main, execute: {
//
self.listViewVideos = self.listViewVideos.sorted(by: {$0.index < $1.index})
//
self.currentVideo = self.listViewVideos.first(where: {$0.song.videoId == targetVideoId})
self.group = nil
[weak self] in
//
self?.currentVideo = self?.listViewVideos.first(where: {$0.song.videoId == targetVideoId})
//
self?.listViewVideos = self?.listViewVideos.suffix(3)
self?.group = nil
})
}
///

View File

@ -468,6 +468,9 @@ class MPPositive_PlayerViewController: MPPositive_BaseViewController, UIViewCont
}
////
@objc private func typeClick(_ sender:UIButton) {
MPPositive_Debouncer.shared.call {
[weak self] in
guard let self = self else {return}
//
var value = MP_PlayerManager.shared.getPlayType().rawValue
value += 1
@ -476,18 +479,27 @@ class MPPositive_PlayerViewController: MPPositive_BaseViewController, UIViewCont
}
MP_PlayerManager.shared.setPlayType(.init(rawValue: value)!)
}
}
//
@objc private func nextClick(_ sender:UIButton) {
MPPositive_Debouncer.shared.call {
[weak self] in
guard let self = self else {return}
coverView.sliderView.value = 0
playBtn.isUserInteractionEnabled = false
MP_PlayerManager.shared.nextEvent()
}
}
//
@objc private func previousClick(_ sender:UIButton) {
MPPositive_Debouncer.shared.call {
[weak self] in
guard let self = self else {return}
coverView.sliderView.value = 0
playBtn.isUserInteractionEnabled = false
MP_PlayerManager.shared.previousEvent()
}
}
}

View File

@ -60,16 +60,37 @@ class MPPositive_PlayerCoverView: UIView {
lazy var durationLabel:UILabel = createLabel("00:00" ,font: .systemFont(ofSize: 12*width, weight: .medium), textColor: .init(hex: "#FFFFFF", alpha: 0.85), textAlignment: .left)
///Label
lazy var maxTimesLabel:UILabel = createLabel("00:00" ,font: .systemFont(ofSize: 12*width, weight: .medium), textColor: .init(hex: "#FFFFFF", alpha: 0.6), textAlignment: .right)
///View
private lazy var maskNotReachableView:UIView = {
let maskView = UIView()
maskView.backgroundColor = .init(hex: "#000000", alpha: 0.7)
maskView.layer.masksToBounds = true
maskView.layer.cornerRadius = 16*width
//label
let noticeLabel:UILabel = createLabel("The network connection is disconnected and the player will stop loading music. Please restore the network as soon as possible!", font: .systemFont(ofSize: 18, weight: .medium), textColor: .white, textAlignment: .center, lines: 0)
maskView.addSubview(noticeLabel)
noticeLabel.snp.makeConstraints { make in
make.center.equalToSuperview()
make.width.equalToSuperview().multipliedBy(0.7)
}
return maskView
}()
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .clear
configure()
//
NotificationCenter.notificationKey.add(observer: self, selector: #selector(netWorkNotReachableAction(_:)), notificationName: .net_switch_notReachable)
NotificationCenter.notificationKey.add(observer: self, selector: #selector(netWorkReachableAction(_:)), notificationName: .net_switch_reachable)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
//
private func configure() {
//
@ -80,6 +101,11 @@ class MPPositive_PlayerCoverView: UIView {
make.centerX.equalToSuperview()
make.top.equalToSuperview().offset(12*width)
}
addSubview(maskNotReachableView)
maskNotReachableView.snp.makeConstraints { make in
make.left.right.top.bottom.equalTo(coverImageView)
}
maskNotReachableView.isHidden = true
//
addSubview(titleLabel)
titleLabel.snp.makeConstraints { make in
@ -128,6 +154,15 @@ class MPPositive_PlayerCoverView: UIView {
make.top.equalTo(sliderView.snp.bottom).offset(5*width)
}
}
//
@objc private func netWorkNotReachableAction(_ sender:Notification) {
maskNotReachableView.isHidden = false
}
//
@objc private func netWorkReachableAction(_ sender:Notification) {
maskNotReachableView.isHidden = true
}
//
@objc private func seekProgressClick(_ sender: UISlider, forEvent event: UIEvent) {
//touchEvent