【问题标题】:Why am not able to access my model class in Swift Project?为什么无法在 Swift Project 中访问我的模型类?
【发布时间】:2021-08-02 04:48:33
【问题描述】:

如何从 ViewController 访问我的模型并使用模型数据加载到表格视图中????

源码Link

我的 ViewController 是这样的

import UIKit

class ViewController: UIViewController {
    var cclm: CountryCodeListModel?

    override func viewDidLoad() {
        super.viewDidLoad()
        Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(hello), userInfo: nil, repeats: true)
        readLocalJSONFile(forName: "countryList")

        // Do any additional setup after loading the view.
    }

    override func viewDidAppear(_ animated: Bool) {
        
    }
    
    @objc func hello()
     {
        print(cclm?.data?[0].flag)
     }

}

我的模型类看起来像这样

struct CountryCodeList : Decodable {
    var alpha2Code: String?
    var alpha3Code: String?
    var flag      : String?
    var name      : String?
    var code      : String?
}

public struct CountryCodeListModel : Decodable {
    var data      : [CountryCodeList]?
}

var cclm: CountryCodeListModel?


//Method to load json

func readLocalJSONFile(forName name: String) {
    do {
        if let filePath = Bundle.main.path(forResource: name, ofType: "json") {
            let fileUrl = URL(fileURLWithPath: filePath)
            let data = try Data(contentsOf: fileUrl)
            if let countryCodeObject = parse(jsonData: data) {
                cclm = countryCodeObject
                print(cclm?.data?[1].alpha2Code ?? "")  //Printing Correct Value
            }
        }
    } catch {
        print("error: \(error)")
    }
}



func parse(jsonData: Data) -> CountryCodeListModel?{
    var dataArray : [Dictionary<String,Any>] = [[:]]
    var country = Dictionary<String,Any>()
    var modelData = Dictionary<String,Any>()
    do {
        // make sure this JSON is in the format we expect
        if let json = try JSONSerialization.jsonObject(with: jsonData, options: []) as? Dictionary<String,Any> {
            dataArray.removeAll()
            for item  in json["data"] as! [Dictionary<String, Any>] {
                country = item
                
                let url = URL(string: country["flag"] as? String ?? "")
                let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
                let image = UIImage(data: data!)
                let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
                let fileName = url?.lastPathComponent // name of the image to be saved
                let fileURL = documentsDirectory.appendingPathComponent(fileName ?? "")
                if let data = image?.jpegData(compressionQuality: 1.0){
                    do {
                        try data.write(to: fileURL)
                        country["flag"] = fileURL.absoluteString
                        //print("file saved")
                        //urlAsString = fileURL.absoluteString
                    } catch {
                        print("error saving file:", error)
                    }
                }
                
                dataArray.append(country)
                country.removeAll()
                
                    
                
            }
            modelData["data"] = dataArray
            //print(modelData)
            let jsonData1 = try JSONSerialization.data(withJSONObject: modelData, options: [])
            
            do {
                    let decodedData = try JSONDecoder().decode(CountryCodeListModel.self, from: jsonData1)
                
                    return decodedData
                } catch {
                    print("error: \(error)")
                }
            
        }
    } catch let error as NSError {
        print("Failed to load: \(error.localizedDescription)")
    }
    return nil
}

问题陈述:

我正在读取本地json并获取flag key的url值并将相应的图像下载到本地。下载后,我将获取本地路径并在字典中更新,然后创建 JSON 对象并更新我的模型类。

现在,我正在尝试从 ViewController 访问我的模型类,如下所示

print(CountryCodeListModel?.data?[0].name) //check screenshot for error
 print(cclm?.data?[0].flag)                 // this prints nil always

请检查附上的错误截图2

我的 JSON 看起来像这样

{
   "meta":{
      "success":true,
      "message":"Successfully retrieved country details",
      "code":"200"
   },
   "data":[
      {
         "alpha2Code":"AF",
         "alpha3Code":"AFG",
         "flag":"https://raw.githubusercontent.com/DevTides/countries/master/afg.png",
         "name":"Afghanistan",
         "code":"+93"
      },
      {
         "alpha2Code":"AX",
         "alpha3Code":"ALA",
         "flag":"https://raw.githubusercontent.com/DevTides/countries/master/ala.png",
         "name":"Aland Islands",
         "code":"+358"
      },
      {
         "alpha2Code":"AL",
         "alpha3Code":"ALB",
         "flag":"https://raw.githubusercontent.com/DevTides/countries/master/alb.png",
         "name":"Albania",
         "code":"+355"
      },
      {
         "alpha2Code":"DZ",
         "alpha3Code":"DZA",
         "flag":"https://raw.githubusercontent.com/DevTides/countries/master/dza.png",
         "name":"Algeria",
         "code":"+213"
      },
      {
         "alpha2Code":"AS",
         "alpha3Code":"ASM",
         "flag":"https://raw.githubusercontent.com/DevTides/countries/master/asm.png",
         "name":"American Samoa",
         "code":"+1684"
      }
]
}

【问题讨论】:

  • CountryCodeListModel 是一个类。您可以将其视为蓝图。它定义了属性 flagname... 但它只是一个蓝图。这不是真的。
  • cclm?.data?[0].flag 是正确的方法。但它为零,因为您从未初始化它(初始化就像从该蓝图创建一个实际对象。您需要这样做cclm = CountryCodeListModel()
  • 但是,您正在从 JSON 解码。 if let countryCodeObject = parse(jsonData: data) { cclm = countryCodeObject } 将初始化 cclm,但前提是 parse() 方法不返回 nil。这似乎返回 nil... 这意味着您的 JSON 可能有问题。
  • 为什么每 3 秒从包中加载相同的数据?以及为什么要来回转换数据三次(使用JSONSerializationJSONDecoder)?这很令人困惑。
  • @aheze CountryCodeListModel 是一个结构而不是一个类。

标签: ios json swift uitableview nsdictionary


【解决方案1】:

您正在尝试解码不存在的内容。

print(CountryCodeListModel?.data?[0].name) //check screenshot for error
 print(cclm?.data?[0].flag)                 // this prints nil always

上面的代码说明了你想要的:

  1. 的名字
  2. 位置0的可变数据
  3. 结构CountryCodeListModel

你想做的是:

  1. 的名字
  2. 位置 0 的变量
  3. CountryCodeListModel 结构的实例。

例如...

func readLocalJSONFile(forName name: String) {
    do {
        if let filePath = Bundle.main.path(forResource: name, ofType: "json") {
            let fileUrl = URL(fileURLWithPath: filePath)
            let data = try Data(contentsOf: fileUrl)
            if let countryCodeObject = parse(jsonData: data) {
                cclm = countryCodeObject
                print(cclm?.data?[1].alpha2Code ?? "")  //Printing Correct Value
                print(cclm?.data?[0].flag ?? "")
                print(countryCodeObject?.data[0].flag ?? "") // Same as the line above
            }
        }
    } catch {
        print("error: \(error)")
    }
}

除非您尝试使用static 变量(您将使用CountryCodeListModel.data),否则您需要确保您实际使用的是结构的实例或类的对象来引用您的属性。

警告

CountryCodeListModel 是一个结构。 CountryCodeListModel() 是结构 CountryCodeListModel 的一个实例。由于您可以拥有结构的多个实例,因此在访问数据时需要引用特定的结构。因此,CountryCodeListModel.data 将不起作用,它必须是CountryCodeListModel().data。在这种情况下,您拥有cclm.data

【讨论】:

  • 你读过我的问题吗???我还能够在我知道的 readLocalJsonFile 中获得正确的打印结果。所有人都在问为什么我的打印语句在 viewController 中总是为零
  • 所有我想做的就是在视图控制器中打印它并尝试获得正确的值而不是 nil。所以你有什么想法吗?
  • 我可以从我的打印语句中看到我已经正确地将数据添加到 readLocalJSONFile() 内部的模型中,之后当我尝试打印时它总是为零。那是我的确切问题
  • 1.我读了你的问题。 2. 我是来帮忙的,别做个混蛋。 3. print(CountryCodeListModel?.data?[0].name) 离工作不远了,除非你有一个不是你所拥有的 static 变量。这就是为什么print(cclm?.data?[1].alpha2Code ?? "") 有效而print(CountryCodeListModel?.data?[0].name) 无效的原因。正如我的回答所说,您的 print(CountryCodeListModel?.data?[0].name) 始终为零,因为您没有引用任何数据。您需要引用结构的特定实例。例如print(cclm?.data?[0].flag ?? "")
  • 我看到了你的一个问题......你的hello 函数中有print(cclm?.data?[0].flag ?? ""),它在你的类ViewController 中引用了你的cclm。当然它不会有任何数据,你没有设置cclm 等于任何东西。就目前而言,cclm 将是一些东西,但它目前什么都不是。你必须做cclm = SOMETHING 然后它会有数据。
猜你喜欢
  • 2020-08-02
  • 2021-05-26
  • 2019-06-01
  • 2015-01-07
  • 1970-01-01
  • 2012-03-19
  • 1970-01-01
  • 2014-09-21
  • 1970-01-01
相关资源
最近更新 更多