首页 > 解决方案 > 如何在 JSON 模型中快速添加自定义变量?

问题描述

请告诉我,是否可以在模型中添加一个新的(自定义)变量NewResult,其中数据来自 API?我想将isFavorite: Bool变量添加到模型中,以便将来跟踪更改并交换此变量。

这是我的模型:

class News: Codable {
    var results: [NewResult]?
}


class NewResult: Codable {
    var isFavorite = false
    let url: String?
    let section: String?
    let byline: String?
    let title, abstract, publishedDate: String?
    let media: [Media]?

enum CodingKeys: String, CodingKey {
    case url
    case section
    case byline
    case title
    case abstract
    case publishedDate = "published_date"
    case media
  }
}

class Media: Codable {
    let mediaMetadata: [MediaMetadata]?

enum CodingKeys: String, CodingKey {
    case mediaMetadata = "media-metadata"
  }
}


class MediaMetadata: Codable {
    let url: String?

}

我使用 Alamofire,所以这是我的 requestData 方法:

static func requestData(url: String, completion: @escaping (News) -> ()) {

    guard let url = URL(string: url) else { return }

    request(url).responseData { (responseData) in

        switch responseData.result {

        case .success(let data):

            guard let news = try? JSONDecoder().decode(News.self, from: data) else { return }

            completion(news)

        case .failure(let error):
            print(error.localizedDescription)
        }
    }

在我的MainVC课堂上,我有标准的TableViewDelegate,TableViewDataSourceNavigationto方法Detail VC

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    guard let indexPath = tableView.indexPathForSelectedRow else { return }

    guard let destination = segue.destination as? DetailViewController else { return }
    destination.currentNew = news?.results?[indexPath.row]
}

DetailVC我有webView

// MARK: - Properties

var currentNew: NewResult!
private var isFavorite = false

// MARK: - @IBOutlets

@IBOutlet var progressView: UIProgressView!
@IBOutlet var webView: WKWebView!
@IBOutlet var favoriteButton: UIBarButtonItem!

override func viewDidLoad() {
    super.viewDidLoad()

    let newUrl = currentNew.url

    guard let url = URL(string: newURL) else { return }
    let request = URLRequest(url: url)

    webView.load(request)
  }

 // MARK: - @IBAction

@IBAction func addToFavorite(_ sender: UIBarButtonItem) {

    self.isFavorite.toggle()

    self.currentNew.isFavorite = self.isFavorite

    setFavoriteButton(isFavorite: self.isFavorite)

  }

 // MARK: - Methods

private func setFavoriteButton(isFavorite: Bool) {

    if isFavorite {
        favoriteButton.image = UIImage(named: "favoriteTrue")
        // and here I should change variable isFavorite in currentNew and in news
    } else {
        favoriteButton.image = UIImage(named: "favoriteFalse")
        // and also here
    }
}
}

当我返回MainVC并选择results[indexPath.row]已经在我的收藏夹中时,results即使在应用程序重新启动后也应该进行更改。

标签: swiftapinetworkingmodel

解决方案


isFavourite只需在 中创建一个属性NewResult,即

struct NewResult: Codable {
    //all other properties....
    var isFavorite = false

    enum CodingKeys: String, CodingKey {
        //don't include isFavorite here...
        //all the other cases...
    }
}

不要包含casefor isFavouritein enum CodingKeys

用法:

既然要results稍后修改,所以把它从let改为var,即

struct News: Codable {
    var results: [NewResult]?
}

现在,解析 JSON 并修改resultswithisFavourite = true

if let data = data {
    do {
        var news = try JSONDecoder().decode(News.self, from: data)
        news.results = news.results?.map({
            var tempResult = $0
            tempResult.isFavourite = true
            return tempResult
        })
        print(news)
    } catch {
        print(error)
    }
}

DetailVC中,您必须具有类型的属性NewResult选择/取消选择时,请根据starButton其更新基于该值的值,即isFavouriteresult

class DetailVC: UIViewController {
    var result: NewResult?

    func onTapStarButton(_ sender: UIButton) {
        sender.isSelected = !sender.isSelected
        self.result?.isFavourite = sender.isSelected
    }
}

注意:制作您的模型class,而不是struct为了跨多个屏幕跟踪更改。


推荐阅读