【发布时间】:2021-06-21 18:33:45
【问题描述】:
我有一个按流派划分的电台列表,并将它们放置在一个数组中,如下所示:[[流派]、[流派]、[流派]]。我使用站[indexPath.section[indexPath.row] 进行索引,这将访问单个站。然后在 didSelectItemAt 中,我可以将此站传递给呈现的媒体视图控制器并为用户播放。但是,我想实现下一个按钮和上一个按钮,以便用户可以在媒体 VC 本身内切换站点,而无需返回到集合视图。我似乎无法找到一种方法将站点数组中站点的位置表示为 Int,然后我可以将其用作下一个/上一个按钮中的逻辑,正如我在下面尝试的那样。为简单起见,我尝试使用 flatMap 将数组展平,这样更好,因此我可以仅使用站 [indexPath.row] 进行索引,但这仍然不能解决我的问题。我尝试使用 .enumerated() 但我无法弄清楚如何成功使用它提供的索引,因为我需要将它返回的元组附加到数组中。有人对如何实现这一点有任何想法吗?我想这可能是不可能的..
import AVKit
import UIKit
private let reuseIdentifier = "Cell"
class MediaCollectionVC: UICollectionViewController {
var stations = [[Station]]()
let mediaVC = MediaPlayerVC()
override func viewDidLoad() {
super.viewDidLoad()
fetchRadioStation()
collectionView.register(MediaCollectionViewCell.self, forCellWithReuseIdentifier: MediaCollectionViewCell.identifier)
collectionView.register(MediaCollectionSectionReusableView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: MediaCollectionSectionReusableView.identifier)
}
override func numberOfSections(in collectionView: UICollectionView) -> Int { stations.count }
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return stations[section].count }
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
if kind == UICollectionView.elementKindSectionHeader {
let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: MediaCollectionSectionReusableView.identifier, for: indexPath) as! MediaCollectionSectionReusableView
switch indexPath.section {
case 0:
sectionHeader.label.text = "TV"
return sectionHeader
case 1:
sectionHeader.label.text = "News Radio"
return sectionHeader
case 2:
sectionHeader.label.text = "Entertainment Radio"
return sectionHeader
case 3:
sectionHeader.label.text = "Religious Radio"
return sectionHeader
default:
sectionHeader.label.text = "Section Header Issue"
return sectionHeader
}
} else {
print("section header issue")
return UICollectionReusableView()
}
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MediaCollectionViewCell.identifier, for: indexPath) as! MediaCollectionViewCell
let station = stations[indexPath.section][indexPath.row]
cell.titleLabel.text = station.name
cell.imageView.image = stationImages[station.name]
return cell
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// Its here where I'd like to get the position of the station and pass it to the mediaVC
let station = stations[indexPath.section][indexPath.row]
mediaVC.station = station
present(mediaVC, animated: true)
}
func parseJSON(data: Data) {
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode(StationData.self, from: data)
let newsData = decodedData.stations
DispatchQueue.main.async {
self.stations.append(newsData.filter { $0.category == "News" && $0.medium == "TV"})
self.stations.append(newsData.filter { $0.medium == "Radio" && $0.category == "News"})
self.stations.append(newsData.filter { $0.medium == "Radio" && $0.category == "Entertainment"})
self.stations.append(newsData.filter { $0.medium == "Radio" && $0.category == "Religious"})
self.collectionView.reloadData()
}
print("all stations loaded successfully")
} catch {
print("Error decoding: \(error)")
}
}
}
// MediaVC
import AVFoundation
import UIKit
class MediaPlayerVC: UIViewController {
public var position: Int = 0
public var stations = [[Station]]()
public var station: Station?
var player: AVPlayer?
var isPlaying: Bool = true
override func viewDidLoad() {
super.viewDidLoad()
updateUI()
configure()
}
func configure() {
guard let station = station else { return }
let urlString = station.streamURL
do {
try AVAudioSession.sharedInstance().setCategory(.playback)
try AVAudioSession.sharedInstance().setActive(true, options: .notifyOthersOnDeactivation)
guard let url = URL(string: urlString) else {
print("url issue")
return
}
player = AVPlayer(url: url)
guard let player = player else {
print("player issue")
return
}
player.volume = 0.5
player.play()
} catch {
print("error: \(error)")
}
nextButton.addTarget(self, action: #selector(nextButtonTapped(_:)), for: .touchUpInside)
backButton.addTarget(self, action: #selector(backButtonTapped(_:)), for: .touchUpInside)
}
// This is where I need to implement "position" somehow
@objc func nextButtonTapped(_ button: UIButton) {
if position < stations.count - 1 {
position = position + 1
player?.pause()
for subview in view.subviews {
subview.removeFromSuperview()
}
}
}
@objc func backButtonTapped(_ button: UIButton) {
if position > 0 {
position = position - 1
player?.pause()
for subview in view.subviews {
subview.removeFromSuperview()
}
}
}
}
【问题讨论】:
-
"这里是我想获取车站位置的地方" ???你似乎成功地得到了车站,对吧?而且您非常清楚它在数组中的位置;它位于
[indexPath.section][indexPath.row]。那么究竟是什么问题呢? -
@matt 如果我不想要下一个/上一个按钮,那么我可以关闭 mediaVC 并点击另一个电台,让 mediaVC 重新出现并播放该电台,这就是我认为的描述。但是,我想在 mediaVC 中包含一个下一个/上一个按钮,以避免不得不离开 mediaVC 来更换电台。为此,我必须将数组和当前(最初)播放站位置传递给 mediaVC,以便访问下一个/上一个按钮。当我这样做时,一旦我出于某种原因从不同的 indexPath.section 访问站点,索引就会中断。知道为什么吗?
-
为什么不使用
IndexPath? -
@Paulw11 再次感谢您解决它。我将 IndexPath 传递给 mediaVC,并且能够使用 position.section 和 position.row 进行索引。真的很感激!
标签: ios arrays swift uicollectionview uikit