为JSON Tableview使用不同的URL链接

时间:2018-04-03 21:51:37

标签: ios json swift tableview

我要做的是让我的JSON从不同的链接(4个不同的链接)加载,具体取决于我的应用程序中发生的事情。这是一个有4个不同电台的无线电网络应用程序。我可以将当​​前正在播放的电台推到我的JSON ViewController,但问题是我如何让JSON做“如果这个当前电台正在播放那么来自这个链接:LINK TO JSON INFO”?我知道这是可能的,但不知道如何实现它。这是我的JSON TableviewViewController的代码:

    import UIKit

//----------
//MARK: JSON
//----------

//The Initial Response From The JSON
struct Response: Codable {

    var playHistory: Album

}

//The Album Received Which Is An Array Of Song Data
struct Album: Codable {
    var song: [SongData]

}

//The SongData From The PlayHistory Album
struct SongData: Codable{

    var album: String
    var artist: String
    var cover: String
    var duration: String
    var programStartTS: String
    var title: String
}


class TableViewController: UITableViewController {

    //1. Create An Array To Store The SongData
    var songs = [SongData]()
    var currentStation: RadioStation!
    var downloadTask: URLSessionDownloadTask?

    override func viewDidLoad() { super.viewDidLoad()


        self.tableView.delegate = self
        self.tableView.dataSource = self

        //2. Load The JSON From The Main Bundle

        guard let urlText = URL (string: currentStation.longDesc)
            else { return }


        do{
            //a. Get The Data From The From The File
            let data = try Data(contentsOf: urlText)

            //b. Decode The Data To Our Structs
            let albumData = try JSONDecoder().decode(Response.self, from: data)

            //c. Append The Songs Array With The PlayHistory
            albumData.playHistory.song.forEach { songs.append($0) }

            //d. Test Some Data
            print("""
                **The First Album Details**
                Album = \(songs[0].album)
                Artist = \(songs[0].artist)
                Cover = \(songs[0].cover)
                Duration = \(songs[0].duration)
                Start = \(songs[0].programStartTS)
                Title = \(songs[0].title)
                """)

            //3. Load The Data
            DispatchQueue.main.async {
                self.tableView.reloadData()
            }
        }catch{

            print(error)
        }

    }

    //-----------------
    //MARK: UITableView
    //-----------------


    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return songs.count
    }


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {


        //1. Create A Cell
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell

        //2. Set It's Text
        cell.songTitle.text = songs[indexPath.row].title
        cell.artistLabel.text = songs[indexPath.row].artist

        //3. Get The Image
        if let imageURL = URL(string: songs[indexPath.row].cover){

            let request = URLSession.shared.dataTask(with: imageURL) { (imageData, response, error) in

                if let error = error{

                    print(error)

                }else{

                    guard let image = imageData else { return }

                    DispatchQueue.main.async {
                        cell.songCover.image = UIImage(data: image)
                        cell.setNeedsLayout()
                        cell.layoutIfNeeded()
                    }

                }
            }


            request.resume()
        }

        return cell

    }


    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        print("""
            **Album \(indexPath.row) Selected**
            Album = \(songs[indexPath.row].album)
            Artist = \(songs[indexPath.row].artist)
            Cover = \(songs[indexPath.row].cover)
            Duration = \(songs[indexPath.row].duration)
            Start = \(songs[indexPath.row].programStartTS)
            Title = \(songs[indexPath.row].title)
            """)
    }

}

以下是我的“正在播放ViewController”中的代码:

import UIKit
import MediaPlayer

//*****************************************************************
// NowPlayingViewControllerDelegate
//*****************************************************************

protocol NowPlayingViewControllerDelegate: class {
    func didPressPlayingButton()
    func didPressStopButton()
    func didPressNextButton()
    func didPressPreviousButton()
}

//*****************************************************************
// NowPlayingViewController
//*****************************************************************

class NowPlayingViewController: UIViewController {

    weak var delegate: NowPlayingViewControllerDelegate?

    // MARK: - IB UI

    @IBOutlet weak var albumHeightConstraint: NSLayoutConstraint!
    @IBOutlet weak var albumImageView: SpringImageView!
    @IBOutlet weak var artistLabel: UILabel!
    @IBOutlet weak var playingButton: UIButton!
    @IBOutlet weak var songLabel: SpringLabel!
    @IBOutlet weak var stationDescLabel: UILabel!
    @IBOutlet weak var volumeParentView: UIView!
    @IBOutlet weak var previousButton: UIButton!
    @IBOutlet weak var nextButton: UIButton!
    @IBOutlet weak var recentlyPlayed: UIButton!

    // MARK: - Properties

    var currentStation: RadioStation!
    var currentTrack: Track!

    var newStation = true
    var nowPlayingImageView: UIImageView!
    let radioPlayer = FRadioPlayer.shared

    var mpVolumeSlider: UISlider?

    //*****************************************************************
    // MARK: - ViewDidLoad
    //*****************************************************************

    override func viewDidLoad() {
        super.viewDidLoad()

        // Create Now Playing BarItem
        createNowPlayingAnimation()

        // Set AlbumArtwork Constraints
        optimizeForDeviceSize()

        // Set View Title
        self.title = currentStation.name


        // Set UI
        albumImageView.image = currentTrack.artworkImage
        stationDescLabel.text = currentStation.desc
        stationDescLabel.isHidden = currentTrack.artworkLoaded

        // Check for station change
        newStation ? stationDidChange() : playerStateDidChange(radioPlayer.state, animate: false)

        // Setup volumeSlider
        setupVolumeSlider()

        // Hide / Show Next/Previous buttons
        previousButton.isHidden = hideNextPreviousButtons
        nextButton.isHidden = hideNextPreviousButtons
    }

    //*****************************************************************
    // MARK: - Setup
    //*****************************************************************

    func setupVolumeSlider() {
        // Note: This slider implementation uses a MPVolumeView
        // The volume slider only works in devices, not the simulator.
        for subview in MPVolumeView().subviews {
            guard let volumeSlider = subview as? UISlider else { continue }
            mpVolumeSlider = volumeSlider
        }

        guard let mpVolumeSlider = mpVolumeSlider else { return }

        volumeParentView.addSubview(mpVolumeSlider)

        mpVolumeSlider.translatesAutoresizingMaskIntoConstraints = false
        mpVolumeSlider.leftAnchor.constraint(equalTo: volumeParentView.leftAnchor).isActive = true
        mpVolumeSlider.rightAnchor.constraint(equalTo: volumeParentView.rightAnchor).isActive = true
        mpVolumeSlider.centerYAnchor.constraint(equalTo: volumeParentView.centerYAnchor).isActive = true

        mpVolumeSlider.setThumbImage(#imageLiteral(resourceName: "slider-ball"), for: .normal)
    }

    func stationDidChange() {
        radioPlayer.radioURL = URL(string: currentStation.streamURL)
        title = currentStation.name
    }

    //*****************************************************************
    // MARK: - Player Controls (Play/Pause/Volume)
    //*****************************************************************

    // Actions

    @IBAction func playingPressed(_ sender: Any) {
        delegate?.didPressPlayingButton()
    }

    @IBAction func stopPressed(_ sender: Any) {
        delegate?.didPressStopButton()
    }

    @IBAction func nextPressed(_ sender: Any) {
        delegate?.didPressNextButton()
    }

    @IBAction func previousPressed(_ sender: Any) {
        delegate?.didPressPreviousButton()
    }

    //*****************************************************************
    // MARK: - Load station/track
    //*****************************************************************

    func load(station: RadioStation?, track: Track?, isNewStation: Bool = true) {
        guard let station = station else { return }

        currentStation = station
        currentTrack = track
        newStation = isNewStation
    }

    func updateTrackMetadata(with track: Track?) {
        guard let track = track else { return }

        currentTrack.artist = track.artist
        currentTrack.title = track.title

        updateLabels()
    }

    // Update track with new artwork
    func updateTrackArtwork(with track: Track?) {
        guard let track = track else { return }

        // Update track struct
        currentTrack.artworkImage = track.artworkImage
        currentTrack.artworkLoaded = track.artworkLoaded

        albumImageView.image = currentTrack.artworkImage

        if track.artworkLoaded {
            // Animate artwork
            albumImageView.animation = "wobble"
            albumImageView.duration = 3
            albumImageView.animate()
            stationDescLabel.isHidden = true
        } else {
            stationDescLabel.isHidden = false
        }

        // Force app to update display
        view.setNeedsDisplay()
    }

    private func isPlayingDidChange(_ isPlaying: Bool) {
        playingButton.isSelected = isPlaying
        startNowPlayingAnimation(isPlaying)
    }

    func playbackStateDidChange(_ playbackState: FRadioPlaybackState, animate: Bool) {

        let message: String?

        switch playbackState {
        case .paused:
            message = "Station Paused..."
        case .playing:
            message = nil
        case .stopped:
            message = "Station Stopped..."
        }

        updateLabels(with: message, animate: animate)
        isPlayingDidChange(radioPlayer.isPlaying)
    }

    func playerStateDidChange(_ state: FRadioPlayerState, animate: Bool) {

        let message: String?

        switch state {
        case .loading:
            message = "Loading Station ..."
        case .urlNotSet:
            message = "Station URL not valide"
        case .readyToPlay, .loadingFinished:
            playbackStateDidChange(radioPlayer.playbackState, animate: animate)
            return
        case .error:
            message = "Error Playing"
        }

        updateLabels(with: message, animate: animate)
    }

    //*****************************************************************
    // MARK: - UI Helper Methods
    //*****************************************************************

    func optimizeForDeviceSize() {

        // Adjust album size to fit iPhone 4s, 6s & 6s+
        let deviceHeight = self.view.bounds.height

        if deviceHeight == 480 {
            albumHeightConstraint.constant = 106
            view.updateConstraints()
        } else if deviceHeight == 667 {
            albumHeightConstraint.constant = 230
            view.updateConstraints()
        } else if deviceHeight > 667 {
            albumHeightConstraint.constant = 260
            view.updateConstraints()
        }
    }

    func updateLabels(with statusMessage: String? = nil, animate: Bool = true) {

        guard let statusMessage = statusMessage else {
            // Radio is (hopefully) streaming properly
            songLabel.text = currentTrack.title
            artistLabel.text = currentTrack.artist
            shouldAnimateSongLabel(animate)
            return
        }

        // There's a an interruption or pause in the audio queue

        // Update UI only when it's not aleary updated
        guard songLabel.text != statusMessage else { return }

        songLabel.text = statusMessage
        artistLabel.text = currentStation.name

        if animate {
            songLabel.animation = "flash"
            songLabel.repeatCount = 3
            songLabel.animate()
        }
    }

    // Animations

    func shouldAnimateSongLabel(_ animate: Bool) {
        // Animate if the Track has album metadata
        guard animate, currentTrack.title != currentStation.name else { return }

        // songLabel animation
        songLabel.animation = "zoomIn"
        songLabel.duration = 1.5
        songLabel.damping = 1
        songLabel.animate()
    }

    func createNowPlayingAnimation() {

        // Setup ImageView
        nowPlayingImageView = UIImageView(image: UIImage(named: "NowPlayingBars-3"))
        nowPlayingImageView.autoresizingMask = []
        nowPlayingImageView.contentMode = UIViewContentMode.center

        // Create Animation
       // nowPlayingImageView.animationImages = AnimationFrames.createFrames()
       // nowPlayingImageView.animationDuration = 0.7

        // Create Top BarButton
        let barButton = UIButton(type: .custom)
        barButton.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
        barButton.addSubview(nowPlayingImageView)
        nowPlayingImageView.center = barButton.center

        //let barItem = UIBarButtonItem(customView: barButton)
        //self.navigationItem.rightBarButtonItem = barItem
    }

    func startNowPlayingAnimation(_ animate: Bool) {
        animate ? nowPlayingImageView.startAnimating() : nowPlayingImageView.stopAnimating()
    }

    //*****************************************************************
    // MARK: - Segue
    //*****************************************************************





    @IBAction func shareButtonPressed(_ sender: UIButton) {
        let songToShare = "I'm listening to \(currentTrack.title) by: \(currentTrack.artist) on \(currentStation.name)"
        let activityViewController = UIActivityViewController(activityItems: [songToShare, currentTrack.artworkImage!], applicationActivities: nil)
        activityViewController.completionWithItemsHandler = {(activityType: UIActivityType?, completed:Bool, returnedItems:[Any]?, error: Error?) in
            if completed {
                    // do something on completion if you want
                            }
                    }
        present(activityViewController, animated: true, completion: nil)
    }
}

2 个答案:

答案 0 :(得分:1)

您需要将currentStation传递给TableViewController

您声明故事板中有segue,从NowPlayingViewControllerTableViewController

在这种情况下,您需要在prepare(for segue:sender:) NowPlayingViewController中执行以下操作:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let vc = segue.destination as? TableViewController {
        vc.currentStation = currentStation
    }
}

答案 1 :(得分:0)

对于不同的广播电台,您有不同的链接,然后创建一个var currentStationUrl来存储该特定电台的链接,如果更新URL,则调用您的API以获取相应的更新数据到那个链接

var currentStationUrl: String!{
        didSet{
            loadData(urlString: self.currentStationUrl) { (album, status) in
                if status == true{
                    // Do your stuff with response data here
                    print(album?.playHistory.song[0].title)
                }else{
                    print("Can't get data from radio station")
                }
            }
        }
    }

在RadioStation更改时更新RadioStation的链接。

    var currentStation: RadioStation!{
        didSet{
            if self.currentStation == YOUR_RADIO_STATION_1{
                self.currentStationUrl = "http://streamdb3web.securenetsystems.net/player_status_update/JACKSON1_history.txt"
            }
            else if self.currentStation == YOUR_RADIO_STATION_2{
                self.currentStationUrl = LINK_FOR_RADIO_STATION_2
            }
            else if self.currentStation == YOUR_RADIO_STATION_3{
                self.currentStationUrl = LINK_FOR_RADIO_STATION_3
            }
            else if self.currentStation ==YOUR_RADIO_STATION_4{
                self.currentStationUrl = LINK_FOR_RADIO_STATION_4
            }
        }
    }

最后&重要的任务是,为无线电台呼叫您的链接(API),以单独的方法进行,以便您可以重复使用它。

func loadData(urlString: String,completion: @escaping (Response?, Bool ) -> ()) {

        guard let url = URL(string: urlString) else {
            completion(nil, false)
            return
        }

        URLSession.shared.dataTask(with: url) { (data, response, error) in
            if error != nil {
                print(error!.localizedDescription)
                completion(nil, false)
            }
            guard let data = data else {
                completion(nil, false)
                return }
            do {
                let albumData = try JSONDecoder().decode(Response.self, from: data)
                completion(albumData, true)

            } catch let jsonError {
                completion(nil, false)
                print(jsonError)
            }
            }.resume()
    }

要从新工作站获取更新数据,只需更新currentStation的值。

self.currentStation == YOUR_RADIO_STATION_1