Я занимаюсь разработкой музыкального приложения, в котором пользователи могут просматривать выбранные дорожки и сохранять их в списке воспроизведения.У меня возникла проблема, когда при сохранении дорожки в список воспроизведения дважды, один раз за другим, элементы управления воспроизведением не работают должным образом, т. Е. Добавляется 2x дорожка1 в начале списка воспроизведения - при выборе 1-й дорожки1 - воспроизведение и пауза простохорошо, тогда, если я выберу 2-ю дорожку 1 (если 1-я дорожка 1 уже выбрана, или наоборот), она продолжит воспроизведение / паузу, как если бы это была 1-я дорожка 1.
Есть ли способ дублировать этот элемент вместо ссылки на тот же элемент?Вот некоторый код, который показывает, как я заполняю списки воспроизведения, мою структуру данных и т. Д.
Структура данных:
class Data: NSObject, NSCoding {
var title: String
var body: String
var colour: UIColor
var url: String
var isPlaying : Bool = false
init(title: String, body: String, colour: UIColor, url: String) {
self.title = title
self.body = body
self.colour = colour
self.url = url
}
class func createTrackArray() -> [Data] {
var array: [Data] = []
let track1 = Data(title: "Track 1 Title", body: "Track 1 Body", colour: .white, url: "track1url")
let track2 = Data(title: "Track 2 Title", body: "Track 2 Body", colour: .white, url: "track2url")
array.append(track1)
return array
}
}
Отображение музыки для просмотра:
//Global Variable
var musicDataArray: [Data] = []
class MusicVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
musicDataArray = Data.createTrackArray()
}
}
//MARK: - CollectionView Cell Configuration
extension MusicVC: UICollectionViewDelegate, UICollectionViewDataSource, CellDelegate {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return musicDataArray.count
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: .musicCell, for: indexPath) as! MusicCell
cell.cellData = musicDataArray[indexPath.item]
cell.song = musicDataArray[indexPath.item]
cell.cellDelegate = self
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
currentIndexPathItem = indexPath.item
guard let cellToPlay = musicCollectionView.cellForItem(at: IndexPath(item: currentIndexPathItem, section: 0)) as? MusicCell else {
print("Cell not here")
return
}
didSelectCell(for: cellToPlay)
prepareTrackForSavingToPlaylist(track: indexPath.item)
}
func didSelectCell(for cell: MusicCell) {
cell.play()
}
Эта функция сохраняет индекс (и связанный элемент массива ??) во временном массиве.Затем я отправляю его через segue другому контроллеру представления, в результате чего он сохраняется в списке воспроизведения.то есть playlistArray будет содержать только один элемент, который он передает следующему контроллеру представления.
func prepareTrackForSavingToPlaylist(track: Int) {
playlistArray.removeAll()
playlistArray.append(musicDataArray[track])
}
Next ViewController: затем добавляются пропущенные данные (которые являются информацией из этого временного массива из предыдущего контроллера представления)к любому списку воспроизведения, который они выбирают в виде коллекции
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let passedData = Data(title: dataFromMusicVC.title, body: dataFromMusicVC.body, colour: dataFromMusicVC.colour, url: dataFromMusicVC.url)
playlistArray[indexPath.item].append(passedData)
}
И, наконец, пользователь может выбрать список воспроизведения, и он отобразит все сохраненные дорожки в этом списке воспроизведения
extension UserPlaylistsVC: UICollectionViewDelegate, UICollectionViewDataSource, UserDelegate {
func didSelectCell(for cell: UserPlaylistsCell) {
cell.play()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return playlistArray[playlistIndex].count
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let createID = "UserCell"
let userCell = collectionView.dequeueReusableCell(withReuseIdentifier: createID, for: indexPath) as! UserPlaylistsCell
//playlistIndex is just an Int that is based on which cell is selected in a different view controller so that the right playlist is accessed.
userCell.song = playlistArray[playlistIndex][indexPath.item]
userCell.cellData = playlistArray[playlistIndex][indexPath.item]
userCell.userDelegate = self
userCell.delegate = self
return userCell
}
Этоячейка, которая используется для дорожек в списках воспроизведения:
protocol UserDelegate: class {
func didSelectCell (for cell: UserPlaylistsCell)
}
class UserPlaylistsCell: UICollectionViewCell {
@IBOutlet weak var titleLbl: UILabel!
@IBOutlet weak var bodyLbl: UILabel!
@IBOutlet weak var colourView: UIView!
var song : TypeData!
var audio = Audio()
weak var delegate: UserPlaylistDelegate?
weak var userDelegate: UserDelegate?
override func prepareForReuse() {
super.prepareForReuse()
}
override var isSelected: Bool {
didSet {
self.contentView.backgroundColor = isSelected ? UIColor.UMLightGrey : UIColor.white
}
}
override func awakeFromNib() {
super.awakeFromNib()
titleLbl.textColor = UIColor.UMDarkGrey
bodyLbl.textColor = UIColor.UMDarkGrey
colourView.layer.cornerRadius = colourView.layer.frame.size.width / 2
colourView.clipsToBounds = true
}
var cellData: TypeData! {
didSet {
titleLbl.text = cellData.title
bodyLbl.text = cellData.body
colourView.backgroundColor = cellData.colour
}
}
func play() {
if !(song?.isPlaying)! {
song?.isPlaying = true
//Checking whether the global variable is the same as the selected song url so that I don't have to fetch the asset again (fetching the asset plays the track from the beginning again)
if urlString == song.url {
player.play()
} else {
urlString = song.url
audio.fetchAsset()
audio.playAsset()
}
return
}
song?.isPlaying = false
player.pause()
print("Stop", (song?.title)!)
}
}
Есть ли у вас какие-либо идеи, почему, если одна и та же дорожка дважды сохраняется в строке в списке воспроизведения и выбрана дляplay - чтобы элементы управления не работали так, как если бы это была другая дорожка, т. е. желаемая функциональность заключается в том, что она будет рассматриваться как совершенно другая дорожка, при выборе которой она будет воспроизводиться с самого начала снова, при этом сохраняя возможность приостановки и воспроизведенияих индивидуально.
Если вам нужны дополнительные пояснения или дополнительный код, тогдапожалуйста, не стесняйтесь спрашивать.Я действительно ценю, что вы нашли время, чтобы разобраться с этой проблемой.
РЕДАКТИРОВАТЬ
Вот метод didSelectItemAt согласно запросу:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
currentItemIndex = indexPath.item
guard let cellToPlay = userPlaylistsCollectionView.cellForItem(at: IndexPath(item: currentItemIndex, section: 0)) as? UserPlaylistsCell else {
return
}
didSelectCell(for: cellToPlay)
}
РЕДАКТИРОВАТЬ
didDeselectMethod:
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
if let cellToStop = userPlaylistsCollectionView.dataSource?.collectionView(userPlaylistsCollectionView, cellForItemAt: indexPath) as? UserPlaylistsCell {
if (cellToStop.song.isPlaying) {
didSelectCell(for: cellToStop)
print(cellToStop.song.isPlaying)
}
}
}