PQStuckPointMusicController.swift 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  1. //
  2. // PQStuckPointMusicController.swift
  3. // PQSpeed
  4. //
  5. // Created by SanW on 2021/4/28.
  6. // Copyright © 2021 BytesFlow. All rights reserved.
  7. //
  8. import AVFoundation
  9. import UIKit
  10. import BFCommonKit
  11. class PQStuckPointMusicController: PQBaseViewController {
  12. // 选中的总时长
  13. var selectedTotalDuration: Float64 = 0
  14. // 选择的总数
  15. var selectedDataCount: Int = 0
  16. // 选择的图片总数
  17. var selectedImageDataCount: Int = 0
  18. // 选中的素材数据
  19. var selectedPhotoData: [PQEditVisionTrackMaterialsModel]?
  20. // 选中的音乐数据
  21. var selectedMusicData: PQVoiceModel?
  22. /// 缓存数据
  23. /// ["tagId":
  24. /// [
  25. /// "tagInfo":([PQStuckPointMusicTagsModel], ([UICollectionViewLayoutAttributes], CGFloat)),
  26. /// "pageList":[PQVoiceModel],
  27. /// "currentTag": PQStuckPointMusicTagsModel
  28. /// ]
  29. /// ]
  30. var cacheMusicData: [String: [String: Any]] = Dictionary<String, [String: Any]>.init()
  31. // 热搜数据
  32. var hotList: [Any] = Array<Any>.init()
  33. // 左边距离
  34. let leftMargin: CGFloat = 16
  35. // 搜索拦高度
  36. let searchTFH: CGFloat = 37
  37. // 当前页码
  38. var pageNum: Int = 0
  39. // 当前标签信息-如果是热门则为空
  40. var tagData: PQStuckPointMusicTagsModel?
  41. // 当前播放的音乐
  42. var currentPlayData: PQVoiceModel?
  43. // 当前播放的视频
  44. var playerItem: AVPlayerItem?
  45. lazy var avPlayer: AVPlayer = {
  46. let avPlayer = AVPlayer()
  47. PQNotification.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: avPlayer.currentItem, queue: .main) { [weak self] notify in
  48. BFLog(message: "AVPlayerItemDidPlayToEndTime = \(notify)")
  49. avPlayer.seek(to: CMTime(value: CMTimeValue((self?.currentPlayData?.startTime ?? 0) * 1000), timescale: CMTimeScale(playerTimescale)))
  50. // avPlayer.play()
  51. self?.playStuckPointMusic(itemData: nil)
  52. }
  53. PQNotification.addObserver(forName: .AVPlayerItemNewErrorLogEntry, object: avPlayer.currentItem, queue: .main) { notify in
  54. BFLog(message: "AVPlayerItemNewErrorLogEntry = \(notify)")
  55. }
  56. PQNotification.addObserver(forName: .AVPlayerItemFailedToPlayToEndTime, object: avPlayer.currentItem, queue: .main) { notify in
  57. BFLog(message: "AVPlayerItemFailedToPlayToEndTime = \(notify)")
  58. }
  59. PQNotification.addObserver(forName: .AVPlayerItemPlaybackStalled, object: avPlayer.currentItem, queue: .main) { notify in
  60. BFLog(message: "AVPlayerItemPlaybackStalled = \(notify)")
  61. }
  62. avPlayer.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: CMTimeScale(playerTimescale)), queue: .main) { [weak self] cmTime in
  63. BFLog(message: "addPeriodicTimeObserver = \(cmTime)")
  64. }
  65. return avPlayer
  66. }()
  67. // 输入框清空按钮
  68. lazy var clearBtn: UIButton = {
  69. let clearBtn = UIButton(type: .custom)
  70. clearBtn.setImage(UIImage().BF_Image(named: "icon_search_delete"), for: .normal)
  71. clearBtn.frame = CGRect(x: 0, y: 0, width: 28, height: 32)
  72. clearBtn.tag = 1
  73. clearBtn.addTarget(self, action: #selector(btnClick(sender:)), for: .touchUpInside)
  74. clearBtn.isHidden = true
  75. return clearBtn
  76. }()
  77. // 搜索框
  78. lazy var searchTF: UITextField = {
  79. let searchTF = UITextField(frame: CGRect(x: leftMargin, y: cDevice_iPhoneNavBarAndStatusBarHei, width: cScreenWidth - leftMargin * 2, height: searchTFH))
  80. searchTF.font = UIFont.systemFont(ofSize: 17)
  81. searchTF.backgroundColor = PQBFConfig.shared.otherTintColor
  82. searchTF.attributedPlaceholder = NSAttributedString(string: "搜索歌曲名称/歌手", attributes: [.foregroundColor: UIColor.hexColor(hexadecimal: "#BDBDBD"), .font: UIFont.systemFont(ofSize: 14)])
  83. searchTF.textColor = PQBFConfig.shared.styleTitleColor
  84. searchTF.addCorner(corner: searchTFH / 2)
  85. searchTF.leftViewMode = .always
  86. let leftView = UIView(frame: CGRect(x: 0, y: 0, width: 35, height: 32))
  87. let imageView = UIImageView(image: UIImage().BF_Image(named: "icon_search_s"))
  88. imageView.frame = CGRect(x: 15, y: 8, width: 16, height: 16)
  89. leftView.addSubview(imageView)
  90. searchTF.leftView = leftView
  91. searchTF.delegate = self
  92. searchTF.rightViewMode = .always
  93. let rightView = UIView(frame: CGRect(x: 0, y: 0, width: 40, height: 32))
  94. rightView.addSubview(clearBtn)
  95. searchTF.rightView = rightView
  96. searchTF.delegate = self
  97. searchTF.returnKeyType = .search
  98. searchTF.addTarget(self, action: #selector(editingChanged), for: .editingChanged)
  99. return searchTF
  100. }()
  101. /// 一级分类视图
  102. lazy var topCategoryController: PQStuckPointMusicContentController = {
  103. let topCategoryController = PQStuckPointMusicContentController()
  104. addChild(topCategoryController)
  105. view.insertSubview(topCategoryController.view, belowSubview: searchController.view)
  106. topCategoryController.updateViewFrame(newFrame: CGRect(x: 0, y: searchTF.frame.maxY + cDefaultMargin * 2, width: cDefaultMargin * 12, height: view.frame.height - (searchTF.frame.maxY + cDefaultMargin * 2)))
  107. // 一级分类点击
  108. topCategoryController.didSelectedHandle = { [weak self] _, _, _, itemData in
  109. if itemData is PQStuckPointMusicTagsModel {
  110. self?.musicPageController.updateCurrentPlayMusic(isPlaying: false, isClearCurrentMusic: true)
  111. self?.searchController.updateCurrentPlayMusic(isPlaying: false, isClearCurrentMusic: true)
  112. self?.tagData = itemData as? PQStuckPointMusicTagsModel
  113. self?.dealWithCategorySelectedData(itemData: itemData as? PQStuckPointMusicTagsModel)
  114. // 更新当前标签
  115. self?.updateMusicCacheData(tagId: (itemData as? PQStuckPointMusicTagsModel)?.tagId ?? 0, tagInfo: nil, pageList: nil, currentTag: self?.tagData)
  116. }
  117. self?.playStuckPointMusic(itemData: nil, isClearCurrentMusic: true)
  118. }
  119. return topCategoryController
  120. }()
  121. /// 音乐列表视图
  122. lazy var musicPageController: PQStuckPointMusicContentController = {
  123. let musicPageController = PQStuckPointMusicContentController()
  124. musicPageController.cellHight = cDefaultMargin * 8
  125. addChild(musicPageController)
  126. view.insertSubview(musicPageController.view, belowSubview: searchController.view)
  127. musicPageController.updateViewFrame(newFrame: CGRect(x: topCategoryController.view.frame.maxX, y: topCategoryController.view.frame.minY, width: view.frame.width - topCategoryController.view.frame.maxX, height: topCategoryController.view.frame.height))
  128. musicPageController.contentType = .page
  129. musicPageController.didSelectedHandle = { [weak self] isTagsClick, _, _, itemData in
  130. if isTagsClick { // 二级分类点击
  131. self?.tagData = (itemData as? PQStuckPointMusicTagsModel)
  132. let tagId: Int64 = (itemData as? PQStuckPointMusicTagsModel)?.tagId ?? 0
  133. let parentTagId: Int64 = (itemData as? PQStuckPointMusicTagsModel)?.parentTagId ?? 0
  134. // 请求列表数据
  135. self?.requestPageListData(tagId: tagId, parentTagId: parentTagId)
  136. } else {
  137. self?.playStuckPointMusic(itemData: itemData as? PQVoiceModel)
  138. }
  139. }
  140. musicPageController.refreshHandle = { [weak self] isRefresh, _ in
  141. let tagId: Int64 = self?.tagData?.tagId ?? 0
  142. let parentTagId: Int64 = self?.tagData?.parentTagId ?? 0
  143. // self?.musicPageController.tagsInfo = (tags, tagAttributes) as? ([PQStuckPointMusicTagsModel], ([UICollectionViewLayoutAttributes], CGFloat))
  144. // 请求列表数据
  145. self?.requestPageListData(isRefresh: isRefresh, tagId: tagId, parentTagId: parentTagId)
  146. // 请求二级标签数据
  147. // self?.loadRequestSubTagsList()
  148. self?.playStuckPointMusic(itemData: nil, isClearCurrentMusic: true)
  149. }
  150. musicPageController.btnClickHandle = { [weak self] _, bgmData in
  151. // 使用音乐
  152. self?.userstuckPointMusic(musicData: bgmData as? PQVoiceModel)
  153. }
  154. return musicPageController
  155. }()
  156. /// 搜索控制器
  157. lazy var searchController: PQStuckPointMusicSearchController = {
  158. let searchController = PQStuckPointMusicSearchController()
  159. searchController.selectedDataCount = selectedDataCount
  160. searchController.selectedImageDataCount = selectedImageDataCount
  161. searchController.selectedTotalDuration = selectedTotalDuration
  162. searchController.cellHight = cDefaultMargin * 8
  163. addChild(searchController)
  164. view.addSubview(searchController.view)
  165. searchController.updateViewFrame(newFrame: CGRect(x: 0, y: cDevice_iPhoneNavBarAndStatusBarHei + cDefaultMargin * 2, width: view.frame.width, height: view.frame.height - (cDevice_iPhoneNavBarAndStatusBarHei + cDefaultMargin * 2)))
  166. searchController.didSelectedHandle = { [weak self] isTagsClick, _, _, itemData in
  167. if !isTagsClick {
  168. self?.view.endEditing(true)
  169. if !(itemData is PQEmptyModel) {
  170. self?.playStuckPointMusic(itemData: itemData as? PQVoiceModel)
  171. }
  172. }
  173. }
  174. searchController.btnClickHandle = { [weak self] _, bgmData in
  175. // 使用音乐
  176. self?.userstuckPointMusic(musicData: bgmData as? PQVoiceModel)
  177. }
  178. searchController.scroDidScroHandle = { [weak self] in
  179. self?.view.endEditing(true)
  180. }
  181. searchController.view.isHidden = true
  182. searchController.contentType = .serach
  183. return searchController
  184. }()
  185. lazy var emptyRemindView: PQEmptyRemindView = {
  186. let emptyRemindView = PQEmptyRemindView(frame: CGRect(x: 0, y: searchTF.frame.maxY + cDefaultMargin * 2, width: view.frame.width, height: view.frame.height - (searchTF.frame.maxY + cDefaultMargin * 2)))
  187. emptyRemindView.remindLab.font = UIFont.systemFont(ofSize: 20)
  188. emptyRemindView.remindLab.textColor = UIColor.hexColor(hexadecimal: "#575757")
  189. emptyRemindView.isHidden = true
  190. let emptyData = PQEmptyModel()
  191. emptyData.title = "暂无音乐"
  192. emptyRemindView.emptyData = emptyData
  193. emptyRemindView.fullRefreshBloc = { [weak self] _, _ in
  194. /// 请求标签数据
  195. self?.loadRequestTagsList()
  196. }
  197. view.addSubview(emptyRemindView)
  198. return emptyRemindView
  199. }()
  200. /// 已选择音乐view
  201. lazy var selectedMusciView: PQStuckPointMusicContentCell = {
  202. let selectedMusciView = PQStuckPointMusicContentCell(frame: CGRect(x: 0, y: view.frame.height - cDefaultMargin * 6, width: cScreenWidth, height: cDefaultMargin * 6))
  203. selectedMusciView.confirmContentView.backgroundColor = UIColor.hexColor(hexadecimal: "#333333")
  204. selectedMusciView.playImageView.isHidden = true
  205. selectedMusciView.confirmBtn.setTitle(" 继续使用 ", for: .normal)
  206. selectedMusciView.backgroundColor = UIColor.hexColor(hexadecimal: "#333333")
  207. view.addSubview(selectedMusciView)
  208. return selectedMusciView
  209. }()
  210. override func viewDidLoad() {
  211. super.viewDidLoad()
  212. // 拦截侧滑返回
  213. disablePopGesture().popGestureHandle = { [weak self] in
  214. self?.backBtnClick()
  215. }
  216. leftButton(image: UIImage.init(named: "icon_detail_back"), tintColor: PQBFConfig.shared.styleTitleColor)
  217. setTitle(title: "选择音乐主题", color: PQBFConfig.shared.styleTitleColor)
  218. view.addSubview(searchTF)
  219. addKeyboardObserver()
  220. /// 请求标签数据
  221. loadRequestTagsList()
  222. PQNotification.addObserver(self, selector: #selector(enterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
  223. if selectedMusicData != nil {
  224. let editerVC: PQStuckPointEditerController = PQStuckPointEditerController()
  225. editerVC.stuckPointMusicData = selectedMusicData
  226. editerVC.selectedDataCount = selectedDataCount
  227. editerVC.selectedImageDataCount = selectedImageDataCount
  228. editerVC.selectedTotalDuration = selectedTotalDuration
  229. editerVC.selectedPhotoData = selectedPhotoData
  230. editerVC.isReCreate = true
  231. navigationController?.pushViewController(editerVC, animated: true)
  232. }
  233. // 卡点视频音乐选择曝光上报
  234. PQEventTrackViewModel.baseReportUpload(businessType: .bt_windowView, objectType: .ot_view_selectSyncedUpMusic, pageSource: .sp_stuck_selectSynceedUpMusic, extParams: nil, remindmsg: "卡点视频数据上报-(曝光上报:卡点视频音乐选择页)")
  235. }
  236. override func viewWillDisappear(_ animated: Bool) {
  237. super.viewWillDisappear(animated)
  238. playStuckPointMusic(itemData: nil)
  239. }
  240. /// 按钮点击事件
  241. /// - Parameter sender: <#sender description#>
  242. /// - Returns: <#description#>
  243. @objc func btnClick(sender: UIButton) {
  244. switch sender.tag {
  245. case 1: // 清除
  246. searchTF.text = nil
  247. // emptyRemindView.isHidden = true
  248. clearBtn.isHidden = true
  249. default:
  250. break
  251. }
  252. }
  253. /// 请求标签数据
  254. /// - Returns: <#description#>
  255. func loadRequestTagsList() {
  256. PQLoadingHUB.shared.showHUB()
  257. PQStuckPointViewModel.stuckPointMusicCategoryList { [weak self] tags, _, _ in
  258. PQLoadingHUB.shared.dismissHUB()
  259. if tags.count > 0 {
  260. self?.tagData = tags.first
  261. }
  262. self?.emptyRemindView.isHidden = tags.count > 0
  263. if tags.count > 0 {
  264. self?.topCategoryController.configMusicListData(isRefresh: true, musicListData: tags)
  265. // 请求列表数据
  266. self?.requestPageListData(isHotPage: true, tagId: tags.first?.tagId ?? 0, parentTagId: 0)
  267. }
  268. }
  269. }
  270. /// 请求二级标签数据
  271. /// - Returns: <#description#>
  272. func loadRequestSubTagsList() {
  273. PQLoadingHUB.shared.showHUB()
  274. PQStuckPointViewModel.stuckPointMusicCategoryList(parentTagId: tagData?.tagId ?? 0) { [weak self] tags, _, tagAttributes in
  275. PQLoadingHUB.shared.dismissHUB()
  276. if tagAttributes != nil {
  277. let tagId: Int64 = tags.count > 0 ? (tags.first?.tagId ?? 0) : (self?.tagData?.tagId ?? 0)
  278. let parentTagId: Int64 = tags.count > 0 ? (self?.tagData?.tagId ?? 0) : 0
  279. self?.musicPageController.tagsInfo = (tags, tagAttributes) as? ([PQStuckPointMusicTagsModel], ([UICollectionViewLayoutAttributes], CGFloat))
  280. if tags.count > 0 {
  281. self?.tagData = tags.first
  282. }
  283. // 添加缓存
  284. self?.updateMusicCacheData(tagId: parentTagId > 0 ? parentTagId : tagId, isClearOld: false, tagInfo: self?.musicPageController.tagsInfo, pageList: nil, currentTag: self?.tagData)
  285. // 请求列表数据
  286. self?.requestPageListData(tagId: tagId, parentTagId: parentTagId)
  287. } else {
  288. // 重置数据
  289. self?.resetPageData(isResetData: false)
  290. }
  291. }
  292. }
  293. /// 处理cell点击回调
  294. /// - Parameter itemData: <#itemData description#>
  295. /// - Returns: <#description#>
  296. func dealWithCategorySelectedData(itemData: PQStuckPointMusicTagsModel?) {
  297. tagData = itemData
  298. // 重置数据
  299. resetPageData(isResetData: true)
  300. let cacheData = getMusicCacheData(itemData: itemData)
  301. if cacheData != nil, (cacheData?.0 != nil && (cacheData?.0?.0.count ?? 0) > 0) || (cacheData?.1 != nil && (cacheData?.1?.count ?? 0) > 0) {
  302. musicPageController.tagsInfo = cacheData?.0
  303. musicPageController.configMusicListData(isRefresh: true, musicListData: cacheData?.1 ?? [])
  304. pageNum = ((cacheData?.1?.count ?? 0) / 20) + 1
  305. tagData = cacheData?.2
  306. } else {
  307. pageNum = 1
  308. // 请求二级标签数据
  309. loadRequestSubTagsList()
  310. }
  311. }
  312. /// 请求列表数据
  313. /// - Parameters:
  314. /// - tagId: <#tagId description#>
  315. /// - parentTagId: <#parentTagId description#>
  316. /// - tagsInfo: <#tagsInfo description#>
  317. /// - Returns: <#description#>
  318. func requestPageListData(isRefresh: Bool = true, isHotPage: Bool = false, tagId: Int64, parentTagId: Int64) {
  319. PQLoadingHUB.shared.showHUB()
  320. if isRefresh {
  321. pageNum = 1
  322. }
  323. PQStuckPointViewModel.stuckPointMusicPageList(tagId: tagId, parentTagId: parentTagId, pageNum: pageNum, videoCount: selectedDataCount - selectedImageDataCount, imageCount: selectedImageDataCount, totalDuration: selectedTotalDuration) { [weak self] musicInfo, _ in
  324. PQLoadingHUB.shared.dismissHUB()
  325. if musicInfo.count > 0 {
  326. self?.pageNum = (self?.pageNum ?? 0) + 1
  327. }
  328. self?.musicPageController.configMusicListData(isRefresh: isRefresh, musicListData: musicInfo)
  329. // 添加缓存
  330. self?.updateMusicCacheData(tagId: parentTagId > 0 ? parentTagId : tagId, isClearOld: isRefresh, tagInfo: nil, pageList: musicInfo, currentTag: nil)
  331. if musicInfo.count > 0, isHotPage, isRefresh {
  332. self?.hotList = musicInfo
  333. self?.searchController.hotList = self?.hotList ?? []
  334. }
  335. }
  336. }
  337. /// 重置页面数据
  338. /// - Parameter isResetData: <#isResetData description#>
  339. /// - Returns: <#description#>
  340. func resetPageData(isResetData: Bool) {
  341. musicPageController.tagsInfo = nil
  342. musicPageController.configMusicListData(isResetData: isResetData, isRefresh: true, musicListData: [])
  343. pageNum = 1
  344. }
  345. /// 播放音乐
  346. /// - Parameter itemData: <#itemData description#>
  347. func playStuckPointMusic(itemData: PQVoiceModel?, isClearCurrentMusic: Bool = false) {
  348. if itemData != nil, currentPlayData != itemData {
  349. if !isValidURL(url: itemData?.musicPath ?? "") {
  350. cShowHUB(superView: nil, msg: "本歌曲暂无伴奏版本哦~")
  351. return
  352. }
  353. avPlayer.pause()
  354. playerItem?.removeObserver(self, forKeyPath: "status")
  355. playerItem?.removeObserver(self, forKeyPath: "error")
  356. playerItem = AVPlayerItem(url: URL(string: itemData?.musicPath ?? "")!)
  357. if (itemData?.endTime ?? 0) > 0, (itemData?.endTime ?? 0) > (itemData?.startTime ?? 0) {
  358. playerItem?.forwardPlaybackEndTime = CMTime(value: CMTimeValue((itemData?.endTime ?? 0) * playerTimescale), timescale: CMTimeScale(playerTimescale))
  359. }
  360. avPlayer.replaceCurrentItem(with: playerItem)
  361. playerItem?.addObserver(self, forKeyPath: "status", options: .new, context: nil)
  362. playerItem?.addObserver(self, forKeyPath: "error", options: .new, context: nil)
  363. avPlayer.seek(to: CMTime(value: CMTimeValue((itemData?.startTime ?? 0) * playerTimescale), timescale: CMTimeScale(playerTimescale)))
  364. avPlayer.play()
  365. // let player = TXVodPlayer()
  366. // let config = TXVodPlayConfig()
  367. // config.cacheFolderPath = videoCacheDirectory
  368. // config.maxCacheItems = 0
  369. // player.config = config
  370. //// player.vodDelegate = self
  371. // player.setRenderMode(.RENDER_MODE_FILL_EDGE)
  372. // player.startPlay("https://clipres.yishihui.com/longvideo/material/voice/prod/20210512/MUSIC_QQ_000T1Ws32MWrUj")
  373. currentPlayData = itemData
  374. } else if itemData != nil, avPlayer.rate == 0.0 {
  375. avPlayer.play()
  376. } else {
  377. avPlayer.pause()
  378. musicPageController.updateCurrentPlayMusic(isPlaying: false, isClearCurrentMusic: isClearCurrentMusic)
  379. searchController.updateCurrentPlayMusic(isPlaying: false, isClearCurrentMusic: isClearCurrentMusic)
  380. }
  381. if isClearCurrentMusic {
  382. avPlayer.pause()
  383. currentPlayData = nil
  384. }
  385. }
  386. /// 使用卡点音乐
  387. /// - Parameter musicData: <#musicData description#>
  388. /// - Returns: <#description#>
  389. func userstuckPointMusic(musicData: PQVoiceModel?) {
  390. if musicData != nil {
  391. let editerVC: PQStuckPointEditerController = PQStuckPointEditerController()
  392. editerVC.selectedDataCount = selectedDataCount
  393. editerVC.selectedImageDataCount = selectedImageDataCount
  394. editerVC.selectedTotalDuration = selectedTotalDuration
  395. editerVC.stuckPointMusicData = musicData
  396. editerVC.selectedPhotoData = selectedPhotoData
  397. navigationController?.pushViewController(editerVC, animated: true)
  398. }
  399. }
  400. /// 返回按钮操作
  401. override func backBtnClick() {
  402. if searchController.view.isHidden {
  403. navigationController?.popViewController(animated: true)
  404. // 点击上报:选择音乐分类
  405. PQEventTrackViewModel.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_click_back, pageSource: .sp_stuck_selectSynceedUpMusic, extParams: nil, remindmsg: "卡点视频数据上报-(点击上报:返回按钮)")
  406. } else {
  407. hiddenSearchController()
  408. // 点击上报:返回按钮
  409. PQEventTrackViewModel.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_click_back, pageSource: .sp_stuck_searchSyncedUpMusic, extParams: nil, remindmsg: "卡点视频数据上报-(点击上报:返回按钮)")
  410. }
  411. }
  412. /// 进入后台暂停播放
  413. @objc func enterBackground() {
  414. playStuckPointMusic(itemData: nil)
  415. }
  416. deinit {
  417. PQNotification.removeObserver(self)
  418. avPlayer.currentItem?.removeObserver(self, forKeyPath: "status")
  419. avPlayer.currentItem?.removeObserver(self, forKeyPath: "error")
  420. avPlayer.pause()
  421. avPlayer.replaceCurrentItem(with: nil)
  422. playerItem = nil
  423. }
  424. }
  425. // MARK: - 音乐搜索相关
  426. /// 音乐搜索相关
  427. extension PQStuckPointMusicController: UITextFieldDelegate {
  428. /// 点击输入框
  429. @objc func editingChanged() {
  430. if searchTF.text != nil, (searchTF.text?.count ?? 0) > 0, searchTF.markedTextRange == nil {
  431. if searchTF.text?.isSpace ?? false {
  432. return
  433. }
  434. // loadSearchData()
  435. clearBtn.isHidden = false
  436. }
  437. }
  438. /// 搜索
  439. @objc func loadSearchData() {
  440. if searchTF.text != nil, (searchTF.text?.count ?? 0) > 0, searchTF.text?.isSpace ?? false {
  441. cShowHUB(superView: nil, msg: "搜索内容不能为空")
  442. return
  443. }
  444. if searchTF.text != nil, (searchTF.text?.count ?? 0) > 0 {
  445. BFLog(message: "背景音乐--开始搜索背景音乐-1")
  446. searchController.loadSearchData(keyword: searchTF.text)
  447. }
  448. }
  449. /// 添加键盘监听
  450. /// - Returns: <#description#>
  451. func addKeyboardObserver() {
  452. // 监听键盘的显示和隐藏
  453. PQNotification.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
  454. PQNotification.addObserver(self, selector: #selector(keyboardWillHidden), name: UIResponder.keyboardWillHideNotification, object: nil)
  455. }
  456. /// 键盘显示
  457. /// - Parameter notification: <#notification description#>
  458. @objc func keyboardWillShow(notification: Notification) {
  459. let duration: TimeInterval = TimeInterval("\(notification.userInfo?["UIKeyboardAnimationDurationUserInfoKey"] ?? "1")") ?? 1
  460. UIView.animate(withDuration: duration) { [weak self] in
  461. self?.navTitleLabel?.alpha = 0
  462. self?.searchTF.frame = CGRect(x: cDefaultMargin * 5, y: (cDevice_iPhoneNavBarHei - (self?.searchTFH ?? 37.0)) / 2 + cDevice_iPhoneStatusBarHei, width: cScreenWidth - cDefaultMargin * 7, height: self?.searchTFH ?? 37.0)
  463. } completion: { _ in
  464. }
  465. searchController.view.isHidden = false
  466. hotList.forEach { item in
  467. if item is PQVoiceModel {
  468. (item as? PQVoiceModel)?.isSelected = false
  469. (item as? PQVoiceModel)?.isPlaying = false
  470. }
  471. }
  472. musicPageController.collectionView.reloadData()
  473. searchController.hotList = hotList
  474. playStuckPointMusic(itemData: nil)
  475. // 曝光上报:音乐素材搜索页
  476. PQEventTrackViewModel.baseReportUpload(businessType: .bt_windowView, objectType: .ot_view_searchSyncedUpMusic, pageSource: .sp_stuck_searchSyncedUpMusic, extParams: nil, remindmsg: "卡点视频数据上报-(曝光上报:音乐素材搜索页)")
  477. }
  478. /// 键盘将要隐藏
  479. @objc func keyboardWillHidden() {}
  480. /// 隐藏搜索界面
  481. /// - Returns: <#description#>
  482. func hiddenSearchController() {
  483. view.endEditing(true)
  484. UIView.animate(withDuration: 0.3) { [weak self] in
  485. self?.navTitleLabel?.alpha = 1
  486. self?.searchTF.frame = CGRect(x: self?.leftMargin ?? 0, y: cDevice_iPhoneNavBarAndStatusBarHei, width: cScreenWidth - (self?.leftMargin ?? 0) * 2, height: self?.searchTFH ?? 0)
  487. } completion: { _ in
  488. }
  489. clearBtn.isHidden = true
  490. searchController.view.isHidden = true
  491. // searchTF.text = nil
  492. // searchController.clearData()
  493. // currentPlayData?.isSelected = false
  494. // currentPlayData?.isPlaying = false
  495. playStuckPointMusic(itemData: nil)
  496. }
  497. override func touchesBegan(_: Set<UITouch>, with _: UIEvent?) {
  498. view.endEditing(true)
  499. }
  500. func textFieldShouldReturn(_ textField: UITextField) -> Bool {
  501. loadSearchData()
  502. view.endEditing(true)
  503. if textField.text == nil || (textField.text?.count ?? 0) <= 0 {
  504. cShowHUB(superView: nil, msg: "请先输入搜索内容")
  505. }
  506. return true
  507. }
  508. }
  509. // MARK: - 缓存相关
  510. /// 缓存相关
  511. extension PQStuckPointMusicController {
  512. /// 获取缓存数据
  513. /// - Parameter itemData: <#itemData description#>
  514. /// - Returns: <#description#>
  515. func getMusicCacheData(itemData: PQStuckPointMusicTagsModel?) -> (([PQStuckPointMusicTagsModel], ([UICollectionViewLayoutAttributes], CGFloat))?, [PQVoiceModel]?, PQStuckPointMusicTagsModel?)? {
  516. if itemData != nil, cacheMusicData.keys.contains("\(itemData?.tagId ?? 0)") {
  517. let tempData = cacheMusicData["\(itemData?.tagId ?? 0)"]
  518. return (tempData?["tagInfo"] as? ([PQStuckPointMusicTagsModel], ([UICollectionViewLayoutAttributes], CGFloat)), tempData?["pageList"] as? [PQVoiceModel], tempData?["currentTag"] as? PQStuckPointMusicTagsModel)
  519. } else {
  520. return nil
  521. }
  522. }
  523. /// 更新缓存
  524. /// - Parameters:
  525. /// - tagId: 一级分类id
  526. /// - isClearOld: 是否清空老数据
  527. /// - tagInfo: 二级标签信息
  528. /// - pageList: 音乐数据
  529. /// - currentTag: 当前页当前标签
  530. /// - Returns: <#description#>
  531. func updateMusicCacheData(tagId: Int64, isClearOld: Bool = false, tagInfo: ([PQStuckPointMusicTagsModel], ([UICollectionViewLayoutAttributes], CGFloat))?, pageList: [PQVoiceModel]?, currentTag: PQStuckPointMusicTagsModel?) {
  532. if (tagInfo != nil && (tagInfo?.0.count ?? 0) > 0) || (pageList != nil && (pageList?.count ?? 0) > 0) || currentTag != nil {
  533. if cacheMusicData.keys.contains("\(tagId)") {
  534. var tempDic = cacheMusicData["\(tagId)"]
  535. if tagInfo != nil, (tagInfo?.0.count ?? 0) > 0 {
  536. tempDic?["tagInfo"] = tagInfo!
  537. }
  538. if pageList != nil, (pageList?.count ?? 0) > 0 {
  539. var oldPageList: [PQVoiceModel] = (tempDic?["pageList"] as? [PQVoiceModel]) ?? Array<PQVoiceModel>.init()
  540. if isClearOld {
  541. oldPageList.removeAll()
  542. }
  543. if oldPageList.count > 0 {
  544. tempDic?["pageList"] = oldPageList + pageList!
  545. } else {
  546. tempDic?["pageList"] = pageList!
  547. }
  548. }
  549. if currentTag != nil {
  550. tempDic?["currentTag"] = currentTag!
  551. }
  552. cacheMusicData["\(tagId)"] = tempDic ?? Dictionary<String, Any>.init()
  553. } else {
  554. var tempDic: [String: Any] = Dictionary<String, Any>.init()
  555. if tagInfo != nil, (tagInfo?.0.count ?? 0) > 0 {
  556. tempDic["tagInfo"] = tagInfo!
  557. }
  558. if pageList != nil, (pageList?.count ?? 0) > 0 {
  559. tempDic["pageList"] = pageList!
  560. }
  561. if currentTag != nil {
  562. tempDic["currentTag"] = currentTag!
  563. }
  564. cacheMusicData["\(tagId)"] = tempDic
  565. }
  566. }
  567. }
  568. }
  569. extension PQStuckPointMusicController {
  570. override func observeValue(forKeyPath keyPath: String?, of object: Any?, change _: [NSKeyValueChangeKey: Any]?, context _: UnsafeMutableRawPointer?) {
  571. if object is AVPlayerItem, keyPath == "status" {
  572. BFLog(message: "AVPlayerItem - status = \((object as! AVPlayerItem).status.rawValue)")
  573. switch (object as! AVPlayerItem).status {
  574. case .unknown:
  575. break
  576. case .readyToPlay:
  577. break
  578. case .failed:
  579. break
  580. default:
  581. break
  582. }
  583. } else if object is AVPlayerItem, keyPath == "error" {
  584. BFLog(message: "AVPlayerItem - error = \(String(describing: (object as! AVPlayerItem).error))")
  585. }
  586. }
  587. }