// // Macro.swift // MusicPlayer // // Created by Mr.Zhou on 2024/3/25. // import UIKit import Foundation import AVFoundation import AppTrackingTransparency import AdSupport import MessageUI import MarqueeLabel import UserNotifications @_exported import JXSegmentedView @_exported import JXPagingView //给JXPagingListContainerView添加extension,表示遵从JXSegmentedViewListContainer的协议 extension JXPagingListContainerView: JXSegmentedViewListContainer {} //MARK: - 常用宏定义 ///屏幕宽 let screen_Width = UIScreen.main.bounds.width ///屏幕高 let screen_Height = UIScreen.main.bounds.height ///像素宽比值 let width = screen_Width / 375 ///像素高比值 let height = screen_Height / 667 ///状态栏高度 #if __IPHONE_13_0 let statusBarHeight:CGFloat = UIApplication.shared.windows.first?.windowScene?.statusBarManager?.statusBarFrame.size.height #else let statusBarHeight:CGFloat = UIApplication.shared.statusBarFrame.size.height #endif ///状态栏和导航栏的总高度 let navAndstatusBarHeight = statusBarHeight + 50*width ///判断是否是刘海屏 let iphoneX = ((statusBarHeight != 20) ? true : false) ///获取版本号 let LOCAL_RELEASE_VERSION = Bundle.main.infoDictionary!["CFBundleShortVersionString"] as! String ///获取程序名字 let App_Name = Bundle.main.infoDictionary!["CFBundleDisplayName"] as! String ///获取手机型号 let Phone_Model = UIDevice.current.model ///系统版本号 let System_Version = UIDevice.current.systemVersion ///获取当前系统语言 var Language_first_local:String { let first = Locale.preferredLanguages.first! let languageCode = Locale(identifier: first).languageCode if let code = languageCode { return code } else { return "en" } } ///当前应用版本号 var app_Version:String{ if let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String { return version }else { return "1.0.0" } } ///底部安全区域 let bottomPadding = UIApplication.shared.keyWindow?.safeAreaInsets.bottom ?? 0 ///全局占位图 let placeholderImage:UIImage = UIImage(named: "placeholder")! ///收藏歌曲占位图 let love_songBGImage:UIImage = UIImage(named: "Love Songs'bg")! ///收藏歌手占位图 let love_artistBGImage:UIImage = UIImage(named: "Love Artists'bg")! ///离线下载占位图 let offline_songBGImage:UIImage = UIImage(named: "Offline Songs'bg")! ///隐私政策网址 let privacyUrl:URL = .init(string: "https://musiclax.mystrikingly.com/privacy")! ///用户协议网址 let serviceUrl:URL = .init(string: "https://musiclax.mystrikingly.com/terms")! ///常用渐变色组合值 let gradientTextColors:[CGColor] = [UIColor(red: 0, green: 0.863, blue: 1, alpha: 1).cgColor, UIColor(red: 0, green: 1, blue: 0.561, alpha: 1).cgColor, UIColor(red: 0.776, green: 1, blue: 0.639, alpha: 1).cgColor] ///常用文本颜色-绿色 let greenTextColor:UIColor = .init(hex: "#80F988", alpha: 1.0) ///是否需要提醒用户更新 var isUpDateReminder:Bool = false{ willSet{ if newValue == true { //新值为更新提醒,发布通知 NotificationCenter.notificationKey.post(notificationName: .update_reminder) } } } ///UUID public let app_UUID = UIDevice.current.identifierForVendor?.uuidString ?? UUID().uuidString //MARK: - 全局变量与方法 //存储默认配置值 func coreDefaultValues() { if UserDefaults.standard.string(forKey: "OpenICEID") != nil { print("清理旧数据") UserDefaults.standard.removeObject(forKey: "OpenICEID") } if UserDefaults.standard.object(forKey: "OpenICEID") == nil { print("第一次启动,添加广告ID") if let array = coreAdModelforJson([.init(level: 3, identifier: "ca-app-pub-1371732277241593/2126815630", ad: "AdMob", type: .Insert), .init(level: 2, identifier: "ca-app-pub-1371732277241593/8500652294", ad: "AdMob", type: .Open), .init(level: 1, identifier: "ca-app-pub-1371732277241593/4561407280", ad: "AdMob", type: .Insert), .init(level: 0, identifier: "ca-app-pub-1371732277241593/1926543650", ad: "AdMob", type: .Open)]) { //存入默认开屏冷启动广告ID UserDefaults.standard.set(array, forKey: "OpenICEID") } } if UserDefaults.standard.string(forKey: "OpenHOSTID") != nil { UserDefaults.standard.removeObject(forKey: "OpenHOSTID") } if UserDefaults.standard.object(forKey: "OpenHOSTID") == nil { if let array = coreAdModelforJson([.init(level: 3, identifier: "ca-app-pub-1371732277241593/9262752398", ad: "AdMob", type: .Insert), .init(level: 2, identifier: "ca-app-pub-1371732277241593/6536516707", ad: "AdMob", type: .Open), .init(level: 1, identifier: "ca-app-pub-1371732277241593/9239018894", ad: "AdMob", type: .Insert), .init(level: 0, identifier: "ca-app-pub-1371732277241593/3299335073", ad: "AdMob", type: .Open)]) { //存入默认开屏热启动广告ID UserDefaults.standard.set(array, forKey: "OpenHOSTID") } } if UserDefaults.standard.string(forKey: "SearchINSERTID") != nil { UserDefaults.standard.removeObject(forKey: "SearchINSERTID") } if UserDefaults.standard.object(forKey: "SearchINSERTID") == nil { if let array = coreAdModelforJson([.init(level: 3, identifier: "ca-app-pub-1371732277241593/5323507386", ad: "AdMob", type: .Insert), .init(level: 2, identifier: "ca-app-pub-1371732277241593/6877962328", ad: "AdMob", type: .Insert), .init(level: 1, identifier: "ca-app-pub-1371732277241593/4251798981", ad: "AdMob", type: .Insert), .init(level: 0, identifier: "ca-app-pub-1371732277241593/8622500865", ad: "AdMob", type: .Insert)]) { //存入默认开屏热启动广告ID UserDefaults.standard.set(array, forKey: "SearchINSERTID") } } if UserDefaults.standard.string(forKey: "SearchNATIVEID") != nil { UserDefaults.standard.removeObject(forKey: "SearchNATIVEID") } if UserDefaults.standard.object(forKey: "SearchNATIVEID") == nil { if let array = coreAdModelforJson([.init(level: 3, identifier: "ca-app-pub-1371732277241593/5674216970", ad: "AdMob", type: .Native)]) { //存入默认开屏热启动广告ID UserDefaults.standard.set(array, forKey: "SearchNATIVEID") } } if UserDefaults.standard.string(forKey: "PlayerINSERTID") != nil { UserDefaults.standard.removeObject(forKey: "PlayerINSERTID") } if UserDefaults.standard.object(forKey: "PlayerINSERTID") == nil { if let array = coreAdModelforJson([.init(level: 3, identifier: "ca-app-pub-1371732277241593/9569874154", ad: "AdMob", type: .Insert), .init(level: 2, identifier: "ca-app-pub-1371732277241593/8256792481", ad: "AdMob", type: .Insert), .init(level: 1, identifier: "ca-app-pub-1371732277241593/8031261896", ad: "AdMob", type: .Insert), .init(level: 0, identifier: "ca-app-pub-1371732277241593/4182802216", ad: "AdMob", type: .Insert)]) { //存入默认开屏热启动广告ID UserDefaults.standard.set(array, forKey: "PlayerINSERTID") } } if UserDefaults.standard.string(forKey: "LibraryINSERTID") != nil { UserDefaults.standard.removeObject(forKey: "LibraryINSERTID") } if UserDefaults.standard.object(forKey: "LibraryINSERTID") == nil { if let array = coreAdModelforJson([.init(level: 3, identifier: "ca-app-pub-1371732277241593/4607022200", ad: "AdMob", type: .Insert), .init(level: 2, identifier: "ca-app-pub-1371732277241593/3104538158", ad: "AdMob", type: .Insert), .init(level: 1, identifier: "ca-app-pub-1371732277241593/8931897131", ad: "AdMob", type: .Insert), .init(level: 0, identifier: "ca-app-pub-1371732277241593/5298812459", ad: "AdMob", type: .Insert)]) { //存入默认开屏热启动广告ID UserDefaults.standard.set(array, forKey: "LibraryINSERTID") } } if UserDefaults.standard.string(forKey: "LibraryNATIVEID") != nil { UserDefaults.standard.removeObject(forKey: "LibraryNATIVEID") } if UserDefaults.standard.object(forKey: "LibraryNATIVEID") == nil { if let array = coreAdModelforJson([.init(level: 3, identifier: "ca-app-pub-1371732277241593/4683255855", ad: "AdMob", type: .Native)]) { //存入默认开屏热启动广告ID UserDefaults.standard.set(array, forKey: "LibraryNATIVEID") } } if UserDefaults.standard.object(forKey: "Max_OpenICEIDs") == nil { if let array = coreAdModelforJson([.init(level: 3, identifier: "1dd2cf325a0eb64d", ad: "AppLovin", type: .Insert)]) { //存入默认开屏热启动广告ID UserDefaults.standard.set(array, forKey: "Max_OpenICEIDs") } } if UserDefaults.standard.object(forKey: "Max_SearchINSERTIDs") == nil { if let array = coreAdModelforJson([.init(level: 3, identifier: "43414b9a63224bc6", ad: "AppLovin", type: .Insert)]) { //存入默认开屏热启动广告ID UserDefaults.standard.set(array, forKey: "Max_SearchINSERTIDs") } } if UserDefaults.standard.object(forKey: "Max_PlayerINSERTIDs") == nil { if let array = coreAdModelforJson([.init(level: 3, identifier: "e13ab66866fd6bf8", ad: "AppLovin", type: .Insert)]) { //存入默认开屏热启动广告ID UserDefaults.standard.set(array, forKey: "Max_PlayerINSERTIDs") } } if UserDefaults.standard.object(forKey: "Max_LibraryNATIVEIDs") == nil { if let array = coreAdModelforJson([.init(level: 3, identifier: "4f3858556dc405ee", ad: "AppLovin", type: .Insert)]) { //存入默认开屏热启动广告ID UserDefaults.standard.set(array, forKey: "Max_LibraryNATIVEIDs") } } if UserDefaults.standard.object(forKey: "platform") == nil { UserDefaults.standard.set(false, forKey: "platform") } //更多内容操作 if UserDefaults.standard.string(forKey: "ClientVersion") == nil { UserDefaults.standard.set("1.20240618.01.00", forKey: "ClientVersion") } if UserDefaults.standard.string(forKey: "PlayerVersion") == nil { UserDefaults.standard.set("6.18.1", forKey: "PlayerVersion") } if UserDefaults.standard.object(forKey: "NotificationBodyTexts") == nil { UserDefaults.standard.set(["✅ Enjoy your favorite offline music.Your new playlist is ready! Enjoy your favorite offline music.", "🕛 Now is the time to enjoy non-stop music!", "🚀 Boost your day with new offline music selections!", "🎵 Ready for a music adventure? Download latest tracks for offline fun!", "❤️ Your favorite songs are available for offline playback now.", "😍 New recommendations tailored for you. Add them to your library.", "👉 Touch the music journey, start now!", "🔥 Summer hits ready for download. Enjoy offline!", "🙌 Your music, your way. 💎💎💎", "💡 Discover today's music,enjoy the moment!" ], forKey: "NotificationBodyTexts") if UserDefaults.standard.object(forKey: "OpenAppDuration") == nil { UserDefaults.standard.set(10, forKey: "OpenAppDuration") } if UserDefaults.standard.object(forKey: "InterstitialDuration") == nil { UserDefaults.standard.set(40, forKey: "InterstitialDuration") } if UserDefaults.standard.object(forKey: "IntermediaryDuration") == nil { UserDefaults.standard.set(40, forKey: "IntermediaryDuration") } if UserDefaults.standard.object(forKey: "isShowDownload") == nil { UserDefaults.standard.set(true, forKey: "isShowDownload") } } } ///将广告模型组转为Data func coreAdModelforJson(_ array:[MPPositive_AdItemModel]) -> Data? { guard array.isEmpty != true else {return nil} do{ let jsonData = try JSONEncoder().encode(array) return jsonData }catch { //编译失败 print("用户默认广告配置设置失败,失败原因:\(error.localizedDescription)") return nil } } ///将data转为广告模型组 func jsonforCoreAdModel(_ data:Data) -> [MPPositive_AdItemModel]? { do{ let array:[MPPositive_AdItemModel] = try JSONDecoder().decode([MPPositive_AdItemModel].self, from: data) return array }catch{ //编译失败 print("用户默认广告配置设置失败,失败原因:\(error.localizedDescription)") return nil } } ///将Songs模型组转为Data func coreSongsforJson(_ array:[MPPositive_SongItemModel]) -> Data? { guard array.isEmpty != true else {return nil} do{ let jsonData = try JSONEncoder().encode(array) return jsonData }catch { //编译失败 print("歌曲模型组转为数据失败,失败原因:\(error.localizedDescription)") return nil } } ///将Data重新转化为Songs模型组 func jsonforCoreSongs(_ data:Data) ->[MPPositive_SongItemModel]? { do{ let array:[MPPositive_SongItemModel] = try JSONDecoder().decode([MPPositive_SongItemModel].self, from: data) return array }catch{ //编译失败 print("数据转化Songs失败,失败原因:\(error.localizedDescription)") return nil } } ///总事件闭包 typealias ActionBlock = () -> Void? ///A面全局模态弹出类型 var MPSideA_ModalType:MPSideA_PresentModal = .Timer ///B面全局模态弹出类型 var MPPositive_ModalType:MPPositive_PresentModal = .PlayerList ///调用next对单曲数据歌词ID与相关ID补全 func improveDataforLycirsAndRelated(_ song:MPPositive_SongItemModel, completion:@escaping(((String?,String?)) -> Void)) { //单曲补全需要再次调用next接口 MP_NetWorkManager.shared.requestNextLyricsAndRelated(song){ result in completion(result) } } ///调用player对资源路径和封面路径补全 func improveDataforResouceAndCover(_ song:MPPositive_SongItemModel, completion:@escaping((([String],[Int],[String])?, [String]?) -> Void), failure: ((Bool) -> Void)? = nil) { //单曲补全需要调用player接口 MP_NetWorkManager.shared.requestAndroidPlayer(song.videoId ?? "", playlistId: "", clickTrackingParams: song.clickTrackingParams ?? "") { resourceUrls, coverUrls in completion(resourceUrls,coverUrls) } failure: {statu in failure?(statu) } } ///转时分值 func setTimesToMinSeconds(_ time:TimeInterval) -> String { //设置分钟 let min = Int((time.isNaN ? 0:time) / 60) let second = Int((time.isNaN ? 0:time).truncatingRemainder(dividingBy: 60)) return "\(min < 10 ? "0\(min)":"\(min)"):\(second < 10 ? "0\(second)":"\(second)")" } ///转分值 func setTimesToMins(_ time:TimeInterval) -> String { //设置分钟 let min = Int((time.isNaN ? 0:time) / 60) return "\(min < 10 ? "0\(min)":"\(min)")" } ///获取麦克风权限 func authorize(observe:UIViewController) -> Bool{ let status = AVCaptureDevice.authorizationStatus(for: AVMediaType.audio) switch status { case .authorized: return true case .notDetermined: // 请求授权 AVCaptureDevice.requestAccess(for: AVMediaType.audio, completionHandler: {(status) in DispatchQueue.main.async(execute: {() -> Void in _ = authorize(observe: observe) }) }) default: () DispatchQueue.main.async(execute: { () -> Void in let alertController = UIAlertController(title: "Get Microphone Access",message: "“HiMelody” asks you to turn on your microphone to recognize the decibels around you and turns on white noise for you automatically. Please go to the “Settings” page to turn on the microphone permission",preferredStyle: .alert) let cancelAction = UIAlertAction(title:"Cancel", style: .cancel, handler:nil) let settingsAction = UIAlertAction(title:"Settings", style: .default, handler: { (action) -> Void in let url = URL(string: UIApplication.openSettingsURLString) if let url = url, UIApplication.shared.canOpenURL(url) { if #available(iOS 10, *) { UIApplication.shared.open(url, options: [:], completionHandler: { (success) in }) } else { UIApplication.shared.openURL(url) } } }) alertController.addAction(cancelAction) alertController.addAction(settingsAction) observe.present(alertController, animated: true) }) } return false } ///创建一个Label func createLabel(_ text:String? = nil, font:UIFont, textColor:UIColor, textAlignment:NSTextAlignment, lines:Int = 1) -> UILabel { let label = UILabel() label.text = text ?? "text" label.font = font label.textColor = textColor label.textAlignment = textAlignment label.numberOfLines = lines return label } ///创建一个支持跑马灯的label func createMarQueeLabel(_ text:String? = nil, font:UIFont, textColor:UIColor) -> MarqueeLabel { let label = MarqueeLabel(frame: .init(x: 0, y: 0, width: screen_Width, height: 30*width), duration: 10, fadeLength: 10) label.animationCurve = .linear label.text = text ?? "text" label.font = font label.textColor = textColor label.numberOfLines = 1 label.type = .continuous label.restartLabel() return label } ///根据播放器状态将按钮的图片进行切换 func switchPlayTypeBtnIcon(_ btn:UIButton) { switch MP_PlayerManager.shared.getPlayType() { case .normal://列表播放图案 btn.setBackgroundImage(UIImage(named: "Player_Normal'logo"), for: .normal) case .random://随机播放图案 btn.setBackgroundImage(UIImage(named: "Player_Shuffle'logo"), for: .normal) case .single://单曲循环图案 btn.setBackgroundImage(UIImage(named: "Player_Single'logo"), for: .normal) } } ///请求广告授权 func requestTrackingAuthorization(completion: @escaping (String?) -> Void) { if #available(iOS 14, *) { var attemptsLeft = 3 func requestAuth() { ATTrackingManager.requestTrackingAuthorization { status in switch status { case .authorized: let idfa = ASIdentifierManager.shared().advertisingIdentifier.uuidString print("Authorized: IDFA = \(idfa)") completion(idfa) case .denied, .restricted: print("Denied or Restricted") completion(nil) case .notDetermined: print("Not Determined") attemptsLeft -= 1 if attemptsLeft > 0 { requestAuth() // 继续请求直到达到最大尝试次数 } else { print("Reached maximum number of attempts") completion(nil) } @unknown default: print("Unknown status") completion(nil) } } } requestAuth() // 第一次请求 } else { if ASIdentifierManager.shared().isAdvertisingTrackingEnabled { let idfa = ASIdentifierManager.shared().advertisingIdentifier.uuidString print("Tracking enabled: IDFA = \(idfa)") completion(idfa) } else { print("Tracking not enabled") completion(nil) } } } ///截取\n\n后续的文本 func truncateTextAfterTwoNewlines(from text: String) -> String { // 定义正则表达式,匹配两个连续的换行符及其之后的内容 let pattern = "\n{2,}.*" let regex = try! NSRegularExpression(pattern: pattern, options: [.dotMatchesLineSeparators]) // 使用正则表达式进行替换,删除匹配到的部分 let truncatedText = regex.stringByReplacingMatches(in: text, options: [], range: NSRange(location: 0, length: text.utf16.count), withTemplate: "") return truncatedText } ///更新一个下载模型实体 func saveLoadVideoItem(_ song:MPPositive_SongItemModel?, completion:(() -> Void)?) { MP_DownloadManager.shared.loadQueue.async { guard let song = song?.copy() as? MPPositive_SongItemModel else {return} MP_CoreDataHandlerManager.shared.context.perform { //下载成功,生成一个下载数据 let item = try? MPPositive_DownloadItemModel.create() item?.coverImage = song.coverUrls?.last item?.reviewImage = song.reviewUrls?.last item?.title = song.title item?.longBylineText = song.longBylineText item?.lengthText = song.lengthText item?.shortBylineText = song.shortBylineText item?.lyrics = song.lyrics item?.lyricsID = song.lyricsID item?.videoId = song.videoId item?.relatedID = song.relatedID item?.addTime = Date() item?.artistID = song.artistID item?.albumID = song.albumID item?.playListID = song.playListID //同步生成一个独特的数据 MPPositive_RecentlyModel.fetch(predicate: .init(format: "videoId == %@", (song.videoId ?? ""))) { results in if results.isEmpty { let recent = try? MPPositive_RecentlyModel.create() recent?.coverImage = song.coverUrls?.last recent?.reviewImage = song.reviewUrls?.last recent?.title = song.title recent?.subtitle = "\(song.longBylineText ?? "")\(song.shortBylineText ?? "")" recent?.videoId = song.videoId recent?.lyricsID = song.lyricsID recent?.relatedID = song.relatedID recent?.addTime = Date() recent?.level = 3 recent?.artistID = song.artistID recent?.albumID = song.albumID recent?.playListID = song.playListID MPPositive_RecentlyModel.save() } } //保存下载数据 MPPositive_DownloadItemModel.save() completion?() //更新数据库 MPPositive_LoadCoreModel.shared.reloadLoadSongViewModel(nil) MPPositive_LoadCoreModel.shared.reloadRecents(nil) DispatchQueue.main.async { //执行埋点 MP_AnalyticsManager.shared.player_b_downloadsuccess_actionAction(item?.videoId ?? "", videoname: item?.title ?? "", artistname: item?.shortBylineText ?? "") print("完成了对\(song.title ?? "")的下载数据保存") } } } } ///发布通知 func scheduleDailyNotifications() { UNUserNotificationCenter.current().getNotificationSettings { settings in switch settings.authorizationStatus { case .authorized: DispatchQueue.main.async { guard let texts = UserDefaults.standard.object(forKey: "NotificationBodyTexts") as? [String], texts.isEmpty != true else {return} // 获取通知中心 let center = UNUserNotificationCenter.current() //创建通知内容,通知只具备body let firstContent = UNMutableNotificationContent() firstContent.title = "" firstContent.body = texts.randomElement() ?? "" firstContent.sound = UNNotificationSound.default //设置触发器-每日上午10点 var firstDateComponents = DateComponents() firstDateComponents.hour = 10 let firstTrigger = UNCalendarNotificationTrigger(dateMatching: firstDateComponents, repeats: true) //创建通知内容,通知只具备body let secondContent = UNMutableNotificationContent() secondContent.title = "" secondContent.body = texts.randomElement() ?? "" secondContent.sound = UNNotificationSound.default //设置触发器-每日下午2点 var secondDateComponents = DateComponents() secondDateComponents.hour = 14 let secondTrigger = UNCalendarNotificationTrigger(dateMatching: secondDateComponents, repeats: true) //创建通知请求 let firstRequest = UNNotificationRequest(identifier: "relax.offline.mp3.morningNotification", content: firstContent, trigger: firstTrigger) let secondRequest = UNNotificationRequest(identifier: "relax.offline.mp3.afternoonNotification", content: secondContent, trigger: secondTrigger) // 将通知请求添加到通知中心 center.add(firstRequest) { error in if let error = error { print("更新上午通知失败,失败原因: \(error)") } } center.add(secondRequest) { error in if let error = error { print("更新下午通知失败,失败原因: \(error)") } } } default: break } } } func printCallStack() { let callStack = Thread.callStackSymbols print("Call Stack: \(callStack)") } ///弹出一个更新通知弹窗 func postUpdateReminder(_ observe:UIViewController) { let alter = UIAlertController(title: "Update available".localizableString(), message: "A new version of our app is now available! We've made some exciting improvements and added new features to enhance your experience. To enjoy these updates and continue using our app seamlessly, please update to the latest version now.\nTap on 'Update' to get the latest features and enhancements.".localizableString(), preferredStyle: .alert) //取消 let not = UIAlertAction(title: "Not now".localizableString(), style: .cancel) { action in //用户取消更新事件 MP_AnalyticsManager.shared.update_reminder_cancelAction() print("用户取消更新") } alter.addAction(not) let updata = UIAlertAction(title: "Update".localizableString(), style: .destructive) { action in //用户确定更新事件 MP_AnalyticsManager.shared.update_reminder_sureAction() //跳转AppStore if let url = URL(string: "https://apps.apple.com/app/6502973957") { UIApplication.shared.open(url, options: [:], completionHandler: nil) } } alter.addAction(updata) MP_AnalyticsManager.shared.update_reminder_showAction() observe.present(alter, animated: true) } ///从离线第一首开始播放 func playOfflineSongs(_ videoId:String) { if MPPositive_LoadCoreModel.shared.loadViewModels.isEmpty == false { MP_HUD.text("You are in offline mode".localizableString(), delay: 2.0, completion: nil) //获取离线的歌曲 MP_AnalyticsManager.shared.song_clickAction("Offline Song") //优先清除数据 MP_PlayerManager.shared.loadPlayer = nil //弹出播放器 NotificationCenter.notificationKey.post(notificationName: .pup_player_vc) MP_AnalyticsManager.shared.player_b_impAction() //将当前下载音乐放入列表中 var array:[MPPositive_SongItemModel] = [] for (index, song) in MPPositive_LoadCoreModel.shared.loadViewModels.enumerated() { let item = MPPositive_SongItemModel() item.index = index item.coverUrls = [song.loadItem.coverImage ?? ""] item.reviewUrls = [song.loadItem.reviewImage ?? ""] item.title = song.loadItem.title item.longBylineText = song.loadItem.longBylineText item.lengthText = song.loadItem.lengthText item.shortBylineText = song.loadItem.shortBylineText item.lyricsID = song.loadItem.lyricsID item.lyrics = song.loadItem.lyrics item.videoId = song.loadItem.videoId item.relatedID = song.loadItem.relatedID array.append(item) } //检索videoId是否在loadModels中存在 if let currentVideo = MPPositive_LoadCoreModel.shared.loadViewModels.first(where: {$0.loadItem.videoId == videoId}) { let lodaViewModel = MPPositive_PlayerLoadViewModel(array, currentVideoId: currentVideo.loadItem.videoId ?? "") lodaViewModel.improveData(currentVideo.loadItem.videoId ?? "") //更改播放器播放类型 MP_PlayerManager.shared.setPlayType(.normal) MP_PlayerManager.shared.loadPlayer = lodaViewModel MP_AnalyticsManager.shared.player_b_listAction() }else if let currentVideo = MPPositive_LoadCoreModel.shared.loadViewModels.first { let lodaViewModel = MPPositive_PlayerLoadViewModel(array, currentVideoId: currentVideo.loadItem.videoId ?? "") lodaViewModel.improveData(currentVideo.loadItem.videoId ?? "") //更改播放器播放类型 MP_PlayerManager.shared.setPlayType(.normal) MP_PlayerManager.shared.loadPlayer = lodaViewModel MP_AnalyticsManager.shared.player_b_listAction() } }else { MP_HUD.text("Bad connection~".localizableString(), delay: 2.0, completion: nil) } }