Swift - CollectionView 的 didSelectItemAt:无法打开 indexPath.section 以访问正确的项目

问题描述

我有一个包含媒体站列表的 json 文件。我根据它们的“类别”和“中等”属性将它们分为四个不同的部分。我遇到的问题是在 didSelectRowAt 方法中访问这些项目并将它们传递给媒体播放器 VC,以便它们可以在允许使用前进和后退按钮在电台之间切换的界面中播放。我能够轻松地将站数组传递给媒体播放器 VC,但我无法获得有意义的 indexPath 或某种类型的 Int 以能够索引到我的站数组并在位置上加或减 1 以更改站。我不知道如何继续。需要注意的一点是,stations 数组中只有 1 个电视台,并且它是第一个项目,如果这有所不同的话。为了便于阅读,我在下面包含了我的代码并省略了一些 UI 代码

import AVKit
import BlackLabsColor
import SDWebImage
import UIKit

private let reuseIdentifier = "Cell"

class MediaCollectionVC2: UICollectionViewController {

var stations = [Station]()
var myVC = MediaPlayerVC()

override func viewDidLoad() {
    super.viewDidLoad()

    fetchRadioStation()
    collectionView.register(MediaCollectionViewCell.self,forCellWithReuseIdentifier: MediaCollectionViewCell.identifier)
    collectionView.register(MediaCollectionSectionReusableView.self,forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,withReuseIdentifier: MediaCollectionSectionReusableView.identifier)
    collectionView.backgroundColor = .gray
    self.title = "Live Media"
}

override func numberOfSections(in collectionView: UICollectionView) -> Int { return 4 }

override func collectionView(_ collectionView: UICollectionView,numberOfItemsInSection section: Int) -> Int {

    switch section {
    case 0:
        var numOfItems = 0
        for station in stations {
            if station.medium == "TV" {
                numOfItems += 1
            }
        }
        return numOfItems
    case 1:
        var numOfItems = 0
        for station in stations {
            if station.category == "News" && station.medium == "Radio" {
                numOfItems += 1
            }
        }
        return numOfItems
    case 2:
        var numOfItems = 0
        for station in stations {
            if station.category == "Entertainment" && station.medium == "Radio" {
                numOfItems += 1
            }
        }
        return numOfItems
    case 3:
        var numOfItems = 0
        for station in stations {
            if station.category == "ReligIoUs" && station.medium == "Radio" {
                numOfItems += 1
            }
        }
        return numOfItems
    default:
        print("number of items in section problem")
    }
    return 10
    
}

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

    switch indexPath.section {
    case 0:
        let tvstations = stations.filter { $0.medium == "TV" }
        let tvstation = tvstations[indexPath.row]
        
        cell.imageView.image = UIImage(named: tvstation.name)
        cell.titleLabel.text = tvstation.name
        return cell

    case 1:
        let newsRadioStations = stations.filter { $0.category == "News" && $0.medium == "Radio" }
        let newsRadioStation = newsRadioStations[indexPath.row]
        cell.imageView.image = UIImage(named: "\(newsRadioStation.name).jpg")
        cell.titleLabel.text = newsRadioStation.name
        return cell

    case 2:
        let entertainmenTradioStations = stations.filter { $0.category == "Entertainment" && $0.medium == "Radio" }
        let entertainmenTradioStation = entertainmenTradioStations[indexPath.row]
        cell.imageView.image = UIImage(named: "\(entertainmenTradioStations.name).jpg")
        cell.titleLabel.text = entertainmenTradioStation.name
        return cell

    case 3:
        let religIoUsRadioStations = stations.filter { $0.category == "ReligIoUs" && $0.medium == "Radio" }
        let religIoUsRadioStation = religIoUsRadioStations[indexPath.row]
        cell.titleLabel.text = religIoUsRadioStation.name
        return cell
    default:
        cell.imageView.image = UIImage(named: "tv")
        cell.titleLabel.text = "PROBLEMO"
        return cell
    }
}

// ISSUES HERE
override func collectionView(_ collectionView: UICollectionView,didSelectItemAt indexPath: IndexPath) {
    
    switch indexPath.section {
    case 0:
        let tvstations = stations.filter { $0.medium == "TV" }
        let tvstation = tvstations[indexPath.row]
        playVideo(streamURL: tvstation.streamURL)
        // Works perfectly fine since I'm not presenting a view controller
    case 1:
        // Issues arise as I need to pass only radio stations to the player view controller.
        let radioStations = stations.filter { $0.medium == "Radio" }
        let position = indexPath.item

        myVC.stations = radioStations
        myVC.position = position
        present(myVC,animated: true)
    default:
        print("nada")
    }
}

func playVideo(streamURL: String) {
    
    do {
        try AVAudioSession.sharedInstance().setCategory(.playback,mode: .moviePlayback)
        try AVAudioSession.sharedInstance().setActive(true,options: .notifyOthersOnDeactivation)
    
        guard let url = URL(string: streamURL) else {
            print("url issue")
            return
        }
    
       let player = AVPlayer(url: url)
       let playerController = AVPlayerViewController()
       playerController.player = player
       present(playerController,animated: true)
       player.play()

    } catch {
        print("error: \(error)")
    }
    
}


func fetchRadioStation() {
    let baseURL = "https://jsonkeeper.com/b/"

    guard let url = URL(string: baseURL) else {
        print("station list URL invalid")
        return
    }

    let session = URLSession(configuration: .default)

    session.dataTask(with: url) { data,response,error in
        if error != nil {
            print(error ?? "error fetching stations")
            return
        }

        if let safeData = data {
            self.parseJSON(data: safeData)
        }
    }.resume()
}

func parseJSON(data: Data) {
    let decoder = JSONDecoder()

    do {
        let decodedData = try decoder.decode(StationData.self,from: data)
        let newsData = decodedData.stations
        
        for item in newsData {
            let name = item.name
            let streamURL = item.streamURL
            let desc = item.desc
            let category = item.category
            let medium = item.medium
            
            let station = Station(name: name,streamURL: streamURL,desc: desc,category: category,medium: medium)
            dispatchQueue.main.async {
                self.stations.append(station)
                self.collectionView.reloadData()
            }
        }
        print("all stations loaded successfully")
    } catch {
        print("Error decoding: \(error)")
    }
}

}

// Media Player VC

import AVFoundation
import BlackLabsColor
import SDWebImage
import UIKit

class MediaPlayerVC: UIViewController {

var backButton: UIButton!
var nextButton: UIButton!

public var station: Int = 0
public var stations = [Station]()

var player: AVPlayer?
var isPlaying: Bool = true

let playPauseButton = UIButton()

override func loadView() {
    super.loadView()
    configure()

}

override func viewDidLoad() {
    super.viewDidLoad()
    configure()
}

func configure() {

    let station = stations[position]
    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)")
    }

}

@objc func playPauseButtonTapped(_ button: UIButton) {
    player?.play()
    isPlaying.toggle()
    if isPlaying == true {
        playPauseButton.setBackgroundImage(UIImage(systemName: "pause"),for: .normal)
    } else {
        player?.pause()
        playPauseButton.setBackgroundImage(UIImage(systemName: "play"),for: .normal)
    }

}

    @objc func nextButtonTapped(_ button: UIButton) {
    if position < stations.count - 1 {
        position = position + 1
        player?.pause()
        for subview in view.subviews {
            subview.removeFromSuperview()
        }
        loadView()
    }
}

@objc func backButtonTapped(_ button: UIButton) {
    if position > 0 {
        position = position - 1
        player?.pause()
        for subview in view.subviews {
            subview.removeFromSuperview()
        }
        loadView()
    }

}

}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)