如何从本地JSON更新标签和UIImage占位符?

时间:2019-04-11 21:17:24

标签: json swift

所以我有一个JSON文件,我需要解析和更新标签和图像。在我的情节提要中,我有4个标签(动物的图像,区域,重量和长度)和uiimage,我需要在其中贴上图片。 我需要通过解析JSON更新标签和图像。 这是我能够到达的距离...

我的JSON看起来像这样:

"data":[
     {
         "name":"Lion",
         "thumbnail":"https://kopelion.org/wp-content/uploads/2016/10/Kimani.jpg",
         "region":"Africa",
         "stats":{
            "max_weight":180,
            "length":250
         }
      }
]

我试图通过写作来解决这个问题:

override func viewDidLoad() {
        super.viewDidLoad()

        guard let path = Bundle.main.path(forResource: "data", ofType: "json") else { return }
        let url = URL(fileURLWithPath: path)

        do {
            let data = try Data(contentsOf: url)
            let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers)
            print(json)

            guard let array = json as? [Any] else { return }

            for animal in array {
                guard let animalDict = animal as? [String: Any] else { return }
                guard let animalName = animalDict["name"] as? String else { return }
                guard let animalRegion = animalDict["region"] as? String else { return }
                guard let animalStats = animalDict["stats"] as? String else { return }

                print(animalName)
                print(animalRegion)
                print(animalStats)
            }
        } catch {
            print(error)
        }


    }

3 个答案:

答案 0 :(得分:0)

您需要在类中具有要设置的情节提要项的属性。例如:

@IBOutlet weak var name: UILabel! // outside functions but inside class, and hooked up in Storyboard

// inside viewDidLoad

name.text = animalDict["name"] as? String

除非您真的需要它们,否则我不会打扰中间变量。

答案 1 :(得分:0)

首先要注意的是,多数情况下,罪魁祸首是json文件本身,就像您的情况一样。

您首先需要fix文件代码中的jsonadding "{" at the top "}" at the bottom json代码。

这将使其valid json

然后是do the following

替换您的代码行:

// 1
guard let array = json as? [Any] else { return }

// 2
guard let animalStats = animalDict["stats"] as? String else { return }

与此:

// 1
guard let dictionary = json as? [String:[Any]] else { return }
guard let array = dictionary["data"]  else { return }

//2
guard let animalRegion = animalDict["region"] as? String else { return }
  

问题提示:1.使用https://codebeautify.org/jsonviewer

等在线工具检查json      
      
  1. 尝试使用JSONDecoder和JSONEncoder而不是JSONSerialization
  2.   

答案 2 :(得分:0)

由于您负责JSON,因此删除封闭的字典data,这是不需要的。

[{
   "name":"Lion",
   "thumbnail":"https://kopelion.org/wp-content/uploads/2016/10/Kimani.jpg",
   "region":"Africa",
   "stats":{
      "max_weight":180,
      "length":250
   }
}]

创建两个结构

struct Animal: Decodable {
    let name: String
    let thumbnail: URL
    let region: String
    let stats: Stats
}

struct Stats: Decodable {
    let maxWeight, length: Int
}

在视图控制器中声明一个数据源数组

var animals = [Animal]()

viewDidLoad中,用JSONDecoder解析数据,并将结果分配给数据源数组

override func viewDidLoad() {
    super.viewDidLoad()

    let url = Bundle.main.url(forResource: "data", withExtension: "json")!
    let data = try! Data(contentsOf: url)
    let decoder = JSONDecoder()
    decoder.keyDecodingStrategy = .convertFromSnakeCase
    self.animals = try! decoder.decode([Animal].self, from: data)
}

实际上不需要所有guardtry。该文件必须在编译时存在,并且不能在运行时进行修改,因此代码不得崩溃。

您可以通过

获得动物的属性
let animal = animals[0]
let name = animal.name
let weight = animal.stats.weight
print(name, weight)

假设JSON中有更多动物使用循环

for animal in animals {
    let name = animal.name
    let weight = animal.stats.weight
    print(name, weight)
}

不清楚如何更新标签,因为问题中没有有关该设计的重要信息。

要使用URLSession异步加载图像