【问题标题】:Read from JSON or XML file and write into array of Core Data Objects从 JSON 或 XML 文件读取并写入核心数据对象数组
【发布时间】:2019-07-29 03:54:17
【问题描述】:

我创建了一个核心数据实体(“Exstand”),它看起来像下面的 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
}

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

提前感谢您提供任何有用的建议。

【问题讨论】:

    标签: arrays json swift xcode core-data


    【解决方案1】:

    你的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)
            }
    

    【讨论】:

      【解决方案2】:

      发生错误是因为standnil 并且永远不会被创建。

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

      casademora 基于this great answer 首先创建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
          }        
      }
      

      不需要其他结构/类。

      【讨论】:

      • 非常感谢。我试图用你的建议解决它 - 我无法让它工作。我已经花了几天时间寻找解决方案,在尝试了你的解决方案后,我感到很沮丧,只是将数据上传到 Firebase,并能够通过“(snapshot.value!as!NSDictionary)”读取数据。我不明白为什么这样更容易,但我已经很长时间没有编程了,你可能知道。仍然感谢您,很抱歉没有使用您建议的解决方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-22
      • 1970-01-01
      • 2019-06-01
      • 2012-08-10
      相关资源
      最近更新 更多