Чтение из файла JSON или XML и запись в массив основных объектов данных - PullRequest
0 голосов
/ 07 марта 2019

И я создал Базовый объект данных («Exstand»), который выглядит как структура JSON ниже (те же поля), и я пытаюсь читать из файла JSON и записывать в массив объектов Core Data.

У меня есть локальный (хранящийся в 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. Мне все равно, откуда его читать, все, что я хочу, - это мое приложение, чтобы фактически читать и хранить данные.

Заранее спасибо за любой полезный совет.

Ответы [ 2 ]

0 голосов
/ 07 марта 2019

Ошибка возникает из-за того, что stand равен nil и никогда не создается.

Принятие (De)codable в подклассе NSManagedObject немного сложно, потому что вам нужно вызвать назначенный инициализатор, который требуетконтекст управляемого объекта.

Основанный на этот замечательный ответ от casademora сначала создает расширение CodingUserInfoKey и JSONDecoder, чтобы иметь возможность передавать контекст управляемого объекта.

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
    }        
}

Другие структуры / классы не нужны.

0 голосов
/ 07 марта 2019

Ваш json здесь недействителен

"адрес": "1 Случайная улица

до

" адрес ":" 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)
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...