繁体   English   中英

从JSON或XML文件读取并写入Core Data Objects数组

[英]Read from JSON or XML file and write into array of Core Data Objects

并且我创建了一个看起来像下面的JSON结构(相同字段)的核心数据实体(“展示”),然后尝试从JSON文件中读取并写入到一组核心数据对象中。

我有一个本地(存储在Xcode中)JSON文件,其中包含如下所示的数据:

[{
    "objectid": 13003,
    "lat": 40.198539203831054,
    "long": 20.294164128143816,
    "adresse": "1 Random Street
    "zeitraum": "v. 7-20h",
    "stellplatzanzahl": 3
},
{
    "objectid": 13004,
    "lat": 50.25018761410509,
    "long": 30.44382262875748,
    "adresse": "2 Random Street",
    "zeitraum": "",
    "stellplatzanzahl": 6
}]

我在这里浏览了许多教程和文章,但是由于我要么打开一个远程文件和/或不尝试将其存储到Core Data中,但我终生无法使用它。

这是我到目前为止的代码,当我尝试将对象附加到数组时会崩溃。 当.append行被注释时,我可以在控制台中看到它实际上并没有将数据写入“ stand”。

class EventDetails: UIViewController, CLLocationManagerDelegate {

@IBOutlet weak var eventMap: MKMapView!


var annotation:MKAnnotation!

var Standarray: [Exstand] = []
var stand:Exstand? = nil
override func viewDidLoad() {
    super.viewDidLoad()



    do {
        let data = NSData(contentsOf: url!)
        let jsonData = try JSONDecoder().decode([Nstand].self, from: data! as Data)

        for detail in jsonData {

            self.stand?.adresse = detail.adresse as String
            self.stand?.lat = detail.lat as Double
            self.stand?.long = detail.long as Double
            self.stand?.stellplatzanzahl = Int16(detail.stellplatzanzahl as Int)
            self.stand?.zeitraum = detail.zeitraum as String

            print(stand?.adresse)
            print("adressen!")
//The line below crashes the app Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
            Standarray.append(stand!)                 
        }
        print("array!")
        print(Standarray)            
    } catch {
     print(error)   // Handle Error
    }        
    }
}

我还创建了该结构,因为在某些教程中,他们使用了该结构而不是Core Data实体,因此如果更好,我也可以使用它。

struct NStand : Codable{    
var objectid: Int
var lat: Double
var long: Double
var adresse: String
var zeitraum: String
var stellplatzanzahl: Int
}

我还将JSON数据保存在XML文件中。 我不在乎从哪里读取它,我想要的只是我的应用程序实际读取和存储数据。

在此先感谢您提供任何有用的建议。

您的json在这里无效

“ adresse”:“随机街1号

“ adresse”:“随机街1号”,

应该

[{
    "objectid": 13003,
    "lat": 40.198539203831054,
    "long": 20.294164128143816,
    "adresse": "1 Random Street",
    "zeitraum": "v. 7-20h",
    "stellplatzanzahl": 3
    },
 {
    "objectid": 13004,
    "lat": 50.25018761410509,
    "long": 30.44382262875748,
    "adresse": "2 Random Street",
    "zeitraum": "",
    "stellplatzanzahl": 6
    }
]

struct NStand : Codable{  // for core-data NSManagedObject
    let objectid,stellplatzanzahl: Int
    let lat,long: Double 
    let adresse,zeitraum: String 
}

        let str = """

[{
"objectid": 13003,
"lat": 40.198539203831054,
"long": 20.294164128143816,
"adresse": "1 Random Street",
"zeitraum": "v. 7-20h",
"stellplatzanzahl": 3
},
{
"objectid": 13004,
"lat": 50.25018761410509,
"long": 30.44382262875748,
"adresse": "2 Random Street",
"zeitraum": "",
"stellplatzanzahl": 6
}]


"""

        do {

            let res = try JSONDecoder().decode([NStand].self, from: Data(str.utf8))

            print(res)
        }
        catch {

            print(error)
        }

发生错误是因为stand nil并且从未创建。

NSManagedObject子类中采用(De)codable有点棘手,因为您必须调用需要托管对象上下文的指定初始化程序。

基于casademora的出色回答 ,首先创建CodingUserInfoKeyJSONDecoder的扩展,以便能够传递托管对象上下文。

extension CodingUserInfoKey {
    static let context = CodingUserInfoKey(rawValue: "context")!
}

extension JSONDecoder {
    convenience init(context: NSManagedObjectContext) {
        self.init()
        self.userInfo[.context] = context
    }
}

然后将CodingKeys和所需的初始化程序添加到您的NSManagedObject子类中(在该类中,而不是在扩展名中)。

class Exstand: NSManagedObject, Decodable {

    private enum CodingKeys: String, CodingKey { case objectid, lat, long, adresse, zeitraum, stellplatzanzahl }

    public required convenience init(from decoder: Decoder) throws {
        guard let context = decoder.userInfo[.context] as? NSManagedObjectContext else { fatalError("Exstand Error: no managed object context!") }
        let entity = NSEntityDescription.entity(forEntityName: "Exstand", in: context)!
        self.init(entity: entity, insertInto: context)
        let values = try decoder.container(keyedBy: CodingKeys.self)
        let objectid = try values.decode(String.self, forKey: .objectid) // do something with objectid
        adresse = try values.decode(String.self, forKey: . adresse)
        lat = try values.decode(Double.self, forKey: .lat)
        long = try values.decode(Double.self, forKey: .long)
        zeitraum = try values.decode(String.self, forKey: .zeitraum)
        stellplatzanzahl = try values.decode(Int16.self, forKey: .stellplatzanzahl)
    }
  ...
}

这就是您所需要的,现在您可以将JSON直接解码为Core Data

var standArray = [Exstand]()

override func viewDidLoad() {
    super.viewDidLoad()
    do {
        let data = try Data(contentsOf: url!)
        let context = // here add the reference to the managed object context
        let decoder = JSONDecoder(context: context)
        standArray = try decoder.decode([Exstand].self, from: data)
        try context.save()         
    } catch {
        print(error)   // Handle Error
    }        
}

不需要其他结构/类。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM