为JSON Tableview使用不同的URL链接

我想要做的是根据我的应用程序中发生的事情,从不同的链接(4个不同的链接)加载我的JSON。 这是一个有4个不同电台的无线电网络应用程序。 我可以将当​​前正在播放的电台推送到我的JSON ViewController,但问题是如何让JSON做“如果这个当前电台正在播放那么从这个链接拉动:链接到JSON信息”? 我知道这是可能的,但不知道如何实现它。 这是我的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) } } 

您需要将currentStation传递给TableViewController

你声明你在故事板中有一个从NowPlayingViewControllerTableViewControllersegue

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

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

对于不同的Radio Station,您有不同的链接,然后创建一个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