传递数据委托和协议 swift

passing data delegates and protocols swift

大家好,希望你们一切顺利,我正在研究 swift 的代表和协议。我的 viewcontroller 遇到了一些问题,它说 found nil while unwrapping an Optional value 将值作为参数之一传递时,我不确定该怎么做,因为如果我打印 artistViewModel?.artistName我确实得到了数据。我不确定这是否与异步或完成处理程序有关。

这是我的 viewcontroller

的代码
import UIKit
import Alamofire
import SwiftyJSON

protocol artistViewModelDelegate {
    func loadArtistViewModel(data: ArtistViewModel)
}

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, artistSearchDelegate {
   
    @IBOutlet weak var tableView: UITableView!
    
    var data: [ArtistItem] = []
    var delegate: artistViewModelDelegate!
    var artistViewModel: ArtistViewModel?
    var params = [API_CONSTANTS.URL_TYPES.PARAMETERS.TERM: "Maroon 5", API_CONSTANTS.URL_TYPES.PARAMETERS.MEDIA: API_CONSTANTS.URL_TYPES.PARAMETERS.MUSIC]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        getItunesData()

        tableView.dataSource = self
        tableView.delegate = self
        tableView.register(UINib(nibName: "artistCell", bundle: nil), forCellReuseIdentifier: "artistCell")
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return data.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "artistCell", for: indexPath) as! artistCell

        cell.artistName.text = data[indexPath.row].artistName
        cell.albumName.text = data[indexPath.row].albumName
        cell.genre.text = data[indexPath.row].genre
        cell.trackPrice.text = "$\(String(data[indexPath.row].trackPrice))"
        cell.albumArtwork.load(url: data[indexPath.row].artwork)

        cell.layer.cornerRadius = 5
        cell.layer.masksToBounds = true
        
        return cell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        artistViewModel = ArtistViewModel(artist: data[indexPath.row])
        let artistViewController = storyboard?.instantiateViewController(withIdentifier: "ArtistViewController") as! ArtistViewController

        delegate.loadArtistViewModel(data: artistViewModel!) // ----> Unexpectedly found nil while unwrapping an Optional value
        present(artistViewController, animated: true, completion: nil)
    }

    func getItunesData(){
        Alamofire.request(API_CONSTANTS.URL_TYPES.URL, method: .get, parameters: params).responseJSON
            { response in
            if response.result.isSuccess {
                let json = JSON(response.result.value)
                self.data = ArtistModel(json: json).artistItems
                self.tableView.reloadData()

            } else {
            }
        }
    }
    func didTapSearch(artist: String) {
        params = [API_CONSTANTS.URL_TYPES.PARAMETERS.TERM:"\(artist)"]
        getItunesData()
    }
    @IBAction func searchButton(_ sender: Any) {
        let popupSearchVC = storyboard?.instantiateViewController(withIdentifier: "popupSearchView") as! PopupViewController
        popupSearchVC.delegate = self
        present(popupSearchVC, animated: true, completion: nil)
    }
}

此处 ArtistViewController 将接收数据

import UIKit

class ArtistViewController: UIViewController, artistViewModelDelegate {

    func loadArtistViewModel(data: ArtistViewModel) {
        print(data.artistName)
    }
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

而对于模型 ArtistViewModel

import Foundation
class ArtistViewModel {
    var artistId: Int
    var artistName: String
    var artwork: URL
    var albumName: String
    var releaseDate: String
    var genre: String
    var trackPrice: Double

    init(artist: ArtistItem){
        self.artistId = artist.artistId
        self.artistName = artist.albumName
        self.artwork = artist.artwork
        self.albumName = artist.albumName
        self.releaseDate = artist.releaseDate
        self.genre = artist.genre
        self.trackPrice = artist.trackPrice
    }
}



Hope you guys can help me with this one. Cheers

根据您的代码,您的 delegate 字段未设置。 ! 将强制展开可选的 delegate 字段。你必须在调用它之前设置你的 delegate

直接给它赋值,或者用optional chaining.

例如,您可以:

  • viewDidLoad()方法中设置一个值为delegate,例如
override func viewDidLoad() {
    super.viewDidLoad()
    // HERE
    self.delegate = ArtistViewController()
    getItunesData()

    tableView.dataSource = self
    tableView.delegate = self
    tableView.register(UINib(nibName: "artistCell", bundle: nil), forCellReuseIdentifier: "artistCell")
}
  • 仅在使用 delegate?.loadArtistViewModel(_:) 设置时调用委托。

您可以将 var delegate: artistViewModelDelegate! 替换为 var delegate: artistViewModelDelegate? 以防止此类错误。