它表示"Build Succeeded"
。然而,在画布上,它写着"Could not view this file - crashed"
。APP也崩溃了。
来自JSONDecoder.swift的问题
Thread 1: Fatal error: Failed to decode productsTest.json from app bundle.
内容视图(文件名:ContentView.swift)
struct ContentView: View {
let menu = Bundle.main.decode([ProductSection].self, from: "productsTest.json")
var body: some View {
NavigationView{
VStack{
List {
ForEach(menu) { section in
Text(section.category)
}
}
}.navigationTitle("Products")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
可编码的扩展来解码json(文件名:JSONDecoder.swift)
extension Bundle {
func decode<x: Decodable>(_ type: x.Type, from filename: String) -> x {
guard let json = url(forResource: filename, withExtension: nil) else {
fatalError("Failed to locate \(filename) in app bundle.")
}
guard let jsonData = try? Data(contentsOf: json) else {
fatalError("Failed to load \(filename) from app bundle.")
}
let decoder = JSONDecoder()
guard let result = try? decoder.decode(x.self, from: jsonData) else {
fatalError("Failed to decode \(filename) from app bundle.")
}
return result
}
}
引导阅读JSON的Swift文件(文件名:ProductsTest.swift)
struct ProductSection: Codable, Identifiable {
var id: UUID
var category: String
var items: [ItemList]
}
struct ItemList: Codable, Equatable, Identifiable {
var id: UUID
var status: String
var quantity: Int
var name: String
var price: Double
var image: String
var moreImage: [String]
var productCode: String
var UPCCode: String
var servingSize: String
var servingPerContainer: String
var amountPerServing: [String]
var percentageDailyValue: String
var description: [String]
var suggestedUse: String
var otherIngredients: [String]
var warning: [String]
#if DEBUG
static let example = ItemList(
id: UUID(),
status: "in-stock",
quantity: 10,
name: "Doctor's Best, Vitamin D3, 25 mcg (1,000 IU), 180 Softgels",
price: 4.98,
image: "753950002098.front",
moreImage: ["753950002098.back"],
productCode: "DRB-00209",
UPCCode: "753950002098",
servingSize: "1 Softgel",
servingPerContainer: "180 servings",
amountPerServing: ["Vitamin D3: 25 mcg (1000 IU)"],
percentageDailyValue: "125%",
description: ["Empty, Empty"],
suggestedUse: "Adult Use: Take 1 softgel daily with food, or as recommended by a nutritionally-informed physician.",
otherIngredients: ["Extra virgin olive oil; softgel capsule (bovine gelatin; glycerin; purified water)"],
warning: ["Store in a cool dry place."]
)
#endif
}
JSON文件(已验证)(文件名:productsTest.json)
[
{
"id": "EF1CC5BB-4785-4D8E-AB98-5FA4E00B6A66",
"category": "SUPPLEMENT",
"items": [
{
"id": "EDCD038C-036F-4C40-826F-61C88CD84DDD",
"status" : "in-stock",
"quantity" : 10,
"name": "Doctor's Best, Vitamin D3, 25 mcg (1,000 IU), 180 Softgels",
"price" : 4.98,
"image" : "753950002098.front",
"moreImage": ["753950002098.back"],
"productCode" : "DRB-00209",
"UPCCode" : "753950002098",
"servingSize" : "1 Softgel",
"servingPerContainer" : "180 servings",
"amountPerServing" : ["Vitamin D3: 25 mcg (1000 IU)"],
"percentageDailyValue" : "125%",
"description" : ["Empty, Empty"],
"suggestedUse" : "Adult Use: Take 1 softgel daily with food, or as recommended by a nutritionally-informed physician.",
"otherIngredients" : ["Extra virgin olive oil; softgel capsule (bovine gelatin; glycerin; purified water)"],
"warning" : ["Store in a cool dry place."]
},
{
"id": "36A7CC40-18C1-48E5-BCD8-3B42D43BEAEE",
"status" : "in-stock",
"quantity" : 5,
"name": "Now Foods, High Potency Vitamin D-3, 50 mcg (2000 IU), 120 Softgels",
"price" : 4.26,
"image" : "733739003676.front",
"moreImage": ["733739003676.back"],
"productCode" : "NOW-00367",
"UPCCode" : "753950002098",
"servingSize" : "1 Softgel",
"servingPerContainer" : "120 servings",
"amountPerServing" : ["Vitamin D4: 50 mcg (2000 IU)"],
"percentageDailyValue" : "250%",
"description" : ["Empty, Empty"],
"suggestedUse" : "Take 1 softgel daily with a meal.",
"otherIngredients" : ["Extra virgin olive oil and softgel capsule (bovine gelatin; water; glycerin)., Not manufactured with yeast; wheat; gluten; soy; corn; milk; egg; fish or shellfish ingredients. Produced in a GMP facility that processes other ingredients containing these allergens."],
"warning" : ["For adults only, Consult physician if pregnant/nursing; taking medication; or have a medical condition. Keep out of reach of children, Natural color variation may occur in this product, Store in a cool, dry place after opening."]
}
]
},
{
"id": "3D97FAB4-50AC-40FC-9BF0-3F46BB6A92F5",
"category": "ELECTRONICS",
"items": [
{
"id": "empty",
"status" : "empty",
"quantity" : 0,
"name": "empty",
"price" : 0.00,
"image" : "empty",
"moreImage": ["empty"],
"productCode" : "empty",
"UPCCode" : "empty",
"servingSize" : "empty",
"servingPerContainer" : "empty",
"amountPerServing" : ["empty"],
"percentageDailyValue" : "empty",
"description" : ["empty"],
"suggestedUse" : "empty",
"otherIngredients" : ["empty"],
"warning" : ["empty"]
}
]
}
]
崩溃控制台报告
...
Exception Type: EXC_BAD_INSTRUCTION (SIGILL)
Exception Codes: 0x0000000000000001, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Termination Signal: Illegal instruction: 4
Termination Reason: Namespace SIGNAL, Code 0x4
Terminating Process: exc handler [4837]
Application Specific Information:
JOCO/DecodeJson.swift:23: Fatal error: Failed to decode products.json from app bundle.
...
2条答案
按热度按时间zz2j4svz1#
你几乎不应该使用
try?
-它只会丢弃错误。如果不能用更好的方式处理错误,至少应该捕获并打印错误;至少你知道哪里出了问题。将JSON解码更改为:
会给你一个错误
加载和解码JSON数据失败Corrupted(Swift.DecodingError.Context(codingPath:[_JSONKey(stringValue:“Index 1”,intValue:1),CodingKeys(stringValue:“items”,intValue:nil),_JSONKey(stringValue:“索引0”,intValue:0)、CodingKeys(stringValue:“id”,intValue:nil)],debugDescription:“尝试从无效的UUID字符串解码UUID。",underlyingError:(无))
这直接指向了问题-外部数组的第二个元素(索引1)中的第一个
item
(索引0)有一个无效的id
-果然,它有一个“空”的id
-不能转换为UUID。因此,要么修复数据,要么将id
的类型更改为String
。e7arh2l62#
由于编辑队列,我重新发布它与补充(从Reading in a JSON File Using Swift):
像这样使用它:
Swift 4.x和5.x使用Decodable
P.S.如果你想用它来加载任何扩展名的文件,请将func loadJson body从
let url = Bundle.main.url(forResource: fileName, withExtension: "json")
改为let url = Bundle.main.url(forResource: fileName, withExtension: nil)
,并像这样使用它:P.P.S.此外,为了提高可读性,将func
loadJson
重命名为decode