我有一個本地 json 并創建了可以決議和獲取資料的資料模型,我想從資料模型創建一個視圖模型以在視圖控制器中使用,可以建議如何使用 swift 高階函式。
JSON:
{
"segment": {
"user1": {
"banners": {
"order": 1,
"items": [1, 3, 4]
},
"products": {
"order": 2,
"items": [1, 2, 3, 4]
}
},
"user2": {
"banners": {
"order": 2,
"items": [4, 3]
},
"products": {
"order": 1,
"items": [2, 3, 4]
}
}
},
"productsList": [{
"productId": 1,
"title": "Title of the product",
"description": "Desciprtion of the product"
}, {
"productId": 2,
"title": "Title of the product",
"description": "Desciprtion of the product"
}, {
"productId": 3,
"title": "Title of the product",
"description": "Desciprtion of the product"
}, {
"productId": 4,
"title": "Title of the product",
"description": "Desciprtion of the product"
}]
}
資料模型::
struct dataModel : Codable {
let segment : Segment?
let productsList : [ProductsList]?
enum CodingKeys: String, CodingKey {
case segment = "segment"
case productsList = "productsList"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
segment = try values.decodeIfPresent(Segment.self, forKey: .segment)
productsList = try values.decodeIfPresent([ProductsList].self, forKey: .productsList)
}
}
struct Banners : Codable {
let order : Int?
let items : [Int]?
enum CodingKeys: String, CodingKey {
case order = "order"
case items = "items"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
order = try values.decodeIfPresent(Int.self, forKey: .order)
items = try values.decodeIfPresent([Int].self, forKey: .items)
}
}
struct Products : Codable {
let order : Int?
let items : [Int]?
enum CodingKeys: String, CodingKey {
case order = "order"
case items = "items"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
order = try values.decodeIfPresent(Int.self, forKey: .order)
items = try values.decodeIfPresent([Int].self, forKey: .items)
}
}
struct ProductsList : Codable {
let productId : Int?
let title : String?
let description : String?
enum CodingKeys: String, CodingKey {
case productId = "productId"
case title = "title"
case description = "description"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
productId = try values.decodeIfPresent(Int.self, forKey: .productId)
title = try values.decodeIfPresent(String.self, forKey: .title)
description = try values.decodeIfPresent(String.self, forKey: .description)
}
}
struct Segment : Codable {
let user1 : User1?
let user2 : User1?
enum CodingKeys: String, CodingKey {
case user1 = "user1"
case user2 = "user2"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
user1 = try values.decodeIfPresent(User1.self, forKey: .user1)
user2 = try values.decodeIfPresent(User1.self, forKey: .user2)
}
}
struct User1 : Codable {
let banners : Banners?
let products : Products?
enum CodingKeys: String, CodingKey {
case banners = "banners"
case products = "products"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
banners = try values.decodeIfPresent(Banners.self, forKey: .banners)
products = try values.decodeIfPresent(Products.self, forKey: .products)
}
}
在視圖模型中,每個用戶都需要一組具有以下條件的部分。
- 部分必須基于json 中的順序鍵放置,例如,如果順序為 1,則它應該是用戶陣列中的第一個元素,而在某種意義上它應該是用戶陣列中的第二個元素,則它應該是 2。
- items陣串列示productsList 陣列中的productId,如果 items 陣列有 3 則在用戶陣列中它應該附加prodouctId:3。
在上述兩個條件下,如何為 user1 和 user2 創建兩個陣列。例如,按照上面的 json,它應該回傳如下。
user1 = [<banners items products>, <products items products>] //Based on order key sorting in array.
user2 = [< products items products>, < banners items products>] //Based on order key sorting in array.
如下創建的 ViewModel 可以從 viewDidLoad 呼叫 viewModel 并且它應該為每個用戶回傳資料。任何人都可以建議在上述條件下執行此操作的正確方法我花了很多時間來做它沒有按預期作業。
struct viewModel {
func getUser1Data() -> []{ ///As per json should return banners items as first element and then products items
}
func getUser2Data() -> [] { ///As per json should return products items as first element and then banners items
}
}
struct User {
var title: String?
var description: String?
}
獲取和決議 json 的函式。
func getModelFromJson(fileName: String) -> dataModel? {
let decoder = JSONDecoder()
let url = Bundle.main.url(forResource: fileName, withExtension: "json")
let data = try? Data(contentsOf: url!)
do {
let result = try decoder.decode(dataModel.self, from: data!)
return result
} catch {
print(error)
}
return nil
}
uj5u.com熱心網友回復:
這是我將如何做(代碼中的注釋)......我不知道你為什么提到高階函式,我看不出有任何理由在這里使用一個......
struct Response: Codable {
let segment: Segment
let productsList: [ProductsList]
}
struct ProductsList: Codable {
let productId: Int
let title: String
let description: String
}
struct Segment: Codable {
let user1: User
let user2: User
}
struct User: Codable {
let banners: BannersProducts
let products: BannersProducts
// return items that are sorted the way you want.
var items: [Int] {
[banners, products]
.sorted(by: { $0.order < $1.order })
.flatMap { $0.items }
}
}
// one type for both Banners and Products
struct BannersProducts: Codable {
let order: Int
let items: [Int]
}
func getUsersFromJson(fileName: String) -> (user1: [ProductsList], user2: [ProductsList]) {
let decoder = JSONDecoder()
let url = Bundle.main.url(forResource: fileName, withExtension: "json")!
let data = try! Data(contentsOf: url)
let response = try! decoder.decode(Response.self, from: data)
// put the products in a dictionary for easy lookup
let products = Dictionary(grouping: response.productsList, by: { $0.productId })
let user1 = response.segment.user1.items.map { products[$0]!.first! } // user1 products
let user2 = response.segment.user2.items.map { products[$0]!.first! }// user2 products
return (user1, user2)
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/399402.html
