Realm swift: Empty realm after relaunching app - ios

I started a new project and tried to implement Realm but I can't get it to work properly. My problem is that when I kill my app and relaunch it, all my previously added objects have disappeared and I get empty results from realm.objects.
class RealmManager {
static let shared = RealmManager()
let realm: Realm
init() {
realm = try! Realm()
}
func write(_ completion: ()->Void) {
do {
try realm.write() {
completion()
}
} catch {
print(error)
}
}
func add(_ object: Object) {
realm.add(object)
}
func delete(_ object: Object) {
realm.delete(object)
}
func objects<Element>(_ type: Element.Type) -> Results<Element> where Element : Object {
return realm.objects(type)
}
}
I created this singleton so I don't have to repeat this realm = try! Realm()everywhere in my code. I have this exact same class in another project which works fine.
My model looks like this :
class PrepFile: Object {
#objc dynamic var creationDate: Date = Date()
#objc dynamic var lastModificationDate: Date = Date()
#objc dynamic var title: String = "Pas de titre"
#objc dynamic var activityKind: String = ""
#objc dynamic var seanceNumber: Int = 0
#objc dynamic var level: String = ""
#objc dynamic var duration: Int = 0
#objc dynamic var date: Date = Date()
#objc dynamic var cycle: Int = 0
#objc dynamic var mainGoal: String = ""
#objc dynamic var specificGoal: String = ""
#objc dynamic var material: String = ""
#objc dynamic var isDraft: Bool = true
convenience init(title: String? = nil, activityKind: String? = nil, seanceNumber: Int? = nil, level: String? = nil, duration: Int? = nil, date: Date? = nil, cycle: Int? = nil, mainGoal: String? = nil, specificGoal: String? = nil, material: String? = nil, phases: [Phase] = [], isDraft: Bool = true) {
self.init()
if let tt = title {
self.title = tt
}
if let ak = activityKind {
self.activityKind = ak
}
if let sn = seanceNumber {
self.seanceNumber = sn
}
if let lv = level {
self.level = lv
}
if let dt = duration {
self.duration = dt
}
if let dt = date {
self.date = dt
}
if let cl = cycle {
self.cycle = cl
}
if let mg = mainGoal {
self.mainGoal = mg
}
if let sg = specificGoal {
self.specificGoal = sg
}
if let mt = material {
self.material = mt
}
self.isDraft = isDraft
}
required init() {
}
}
Then in my VC here's what I do :
class PrepFileListViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
lazy var prepFiles: Results<PrepFile> = { RealmManager.shared.objects(PrepFile.self) }()
var completePrepFiles: [PrepFile] = []
var draftPrepFiles: [PrepFile] = []
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
RealmManager.shared.write {
for file in prepFiles {
RealmManager.shared.delete(file)
}
}
RealmManager.shared.write() {
RealmManager.shared.add(PrepFile(title: "Fiche de prep 1"))
RealmManager.shared.add(PrepFile(title: "Fiche de prep 2"))
RealmManager.shared.add(PrepFile(title: "Fiche de prep 3"))
RealmManager.shared.add(PrepFile(title: "Fiche de prep 4"))
RealmManager.shared.add(PrepFile(title: "Fiche de prep 5"))
}
}
override func viewWillAppear(_ animated: Bool) {
prepFiles = RealmManager.shared.objects(PrepFile.self)
completePrepFiles = prepFiles.filter({ !$0.isDraft })
draftPrepFiles = prepFiles.filter({ $0.isDraft })
tableView.reloadData()
}
}
Now when I run this, it works fine. My PrepFile are added to Realm and I retrieve them alright with my RealmManager.shared.objects(PrepFile.self). Now, I comment the part where I delete/add my files in the viewDidLoad and I get nothing. I don't get empty objects from RealmManager.shared.objects(PrepFile.self), I get an empty result like nothing was ever saved there.
What am I doing wrong ?
I am using Xcode 12 and running my app on an iPhone 11 / 13.3 simulator. Realm version is 5.5.0.

Hmm from what I can guess, you either have somewhere else a configuration for realm to be "inMemoryIdentifier" or you do not set the proper configuration with fileURL at beggining of the app.
Configuration local realm: https://realm.io/docs/swift/latest/#realms

Related

How to filter Realm Results<Object>

I use mongoDB to store data. I have a Result array, which array contains multiple same keyword results.
class Keywords: Object {
#objc dynamic var name: String = ""
#objc dynamic var date: Date = Date()
#objc dynamic var rank: Int = 0
#objc dynamic var requestedURL: String = ""
}
Users can not send requests more than once for the same keyword name.
let action = UIAlertAction(title: "Add", style: .default) { action in
if let textSafe = text.text {
let textPrefix = textSafe.removeWhitespace()
if self.keywordModel.keywordNames.count > 0 {
if self.keywordModel.keywordNames.contains(textSafe) {
return
} else {
self.seo.fetchSEO(keyword: textPrefix, requestURL: self.selectedDomain!.domainName, start: 1)
}
} else {
self.seo.fetchSEO(keyword: textPrefix, requestURL: self.selectedDomain!.domainName, start: 1)
}
}
}
My codes are working fine up to this part.
But when users want to refresh to update results there I need to write filter results or somehow must get only the last recent results if keywords are multiple times stored in the database. By the way, I need multiplied keyword data results since I want to use them for date progress charts in the future.
So simply I need to save all results but I want to show only more recent results on UI.
#objc func refresh(_ sender: AnyObject) {
var keywordArray = [String]()
keywordModel.keywordNames.forEach { keyword in
keywordArray.append(keyword)
}
keywordModel.keywordNames = [String]()
keywordModel.keywordRanks = [Double]()
keywordArray.forEach { keyword in
self.seo.fetchSEO(keyword: keyword, requestURL: self.selectedDomain!.domainName)
}
print(keyword!)
let deadLine = DispatchTime.now() + .seconds(3)
DispatchQueue.main.asyncAfter(deadline: deadLine) {
self.refreshControl?.endRefreshing()
}
}
And for further detail, I transfer results to KeywordModel for some calculations, and i manage all tableview through the KeywordModel codes below.
struct KeywordModel {
var keywordRanks = [Double]()
var averageRank: Double? = 0.0
var keywordCount: Int? = 0
var keywordNames = [String]()
var keywordCountString: String? {
return String(keywordCount!)
}
var averageRankString: String? {
return String(format: "%.01f", averageRank!)
}
mutating func averageOfRanks(resultKeyword: Results<Keywords>?) {
keywordCount = resultKeyword?.count
var n = 0
var raw = [Double]()
while n < resultKeyword!.count {
raw.append(Double(resultKeyword![n].rank))
n += 1
}
keywordRanks = raw
let rankSum = keywordRanks.reduce(0, +)
averageRank = rankSum / Double(keywordRanks.count)
}
mutating func saveKeywords(from results: Results<Keywords>?) {
if results!.count > 0 {
var n = 0
var raw = [String]()
while n < results!.count {
raw.append(results![n].name)
n += 1
}
keywordNames = raw
}
}
And there is my loadData method, where I can apply a filter.
func loadData() {
keyword = selectedDomain?.keywords.sorted(byKeyPath: "name")
statisticCalculate(keyword: keyword)
tableView.reloadData()
}

Passing data in PageViewControllers swift

I have a page controller where I added UIViewControllers and display a bunch of form in each viewcontroller. The issue I am facing now is that I need to get the data supplied in each of the forms and save it which is done in the last view controller. I have tried using delegates but the moment the next button is clicked, the previous value stored becomes nil and only the value of the latest VC is displayed. How can I pass data in this textfields. Any help is appritated.
My delegate
protocol NextDelegate: AnyObject {
func next(pageIndex: Int, model: CreatePropertyModel)
func previous(pageIndex: Int, model: CreatePropertyModel)
}
how I created array of VC
lazy var controllers: [UIViewController] = {
let descVC = DescVC()
descVC.delegate = self
let priceVC = PriceVC()
priceVC.delegate = self
let featuresVC = FeaturesVC()
featuresVC.delegate = self
let picturesVC = PicturesVC()
picturesVC.delegate = self
return [descVC, priceVC, featuresVC, picturesVC]
}()
Model Example
class CreatePropertyModel: DictionaryEncodable {
var title: String?
var desc: String?
var property_type_id: Int?
var property_sub_type_id: Int?
var location_id: Int?
var currency: String?
var price: Int?
}
For all your steps, store it in a singleton.
protocol Answer {
var isDone: Bool { get }
}
class Answer1: Answer {
static public let updatedNotification = Notification.Name("Answer1Updated")
var name: String? {
didSet {
NotificationCenter.default.post(name: Answer1.updatedNotification, object: nil)
}
}
var isDone: Bool {
return name != nil
}
}
class Answer2: Answer {
var age: Int?
var isDone: Bool {
return age != nil
}
}
class Form {
static let shared = Form()
var answers: [Answer] = [Answer1(), Answer2()]
var isDone: Bool {
return answers.allSatisfy { $0.isDone == true }
}
private init() {}
func reset() {
answers = [Answer1(), Answer2()]
}
var answer1: Answer1? {
return Form.shared.answers.filter { $0 is Answer1 }.first as? Answer1
}
var answer2: Answer2? {
return Form.shared.answers.filter { $0 is Answer2 }.first as? Answer2
}
}
Then, in your view controller, read / write values like this.
class MyViewControllerForAnswer1: UIViewController {
var answer: Answer1? {
return Form.shared.answer1
}
var name: String? {
get {
return answer?.name
}
set {
answer?.name = newValue
}
}
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(answerUpdated(notification:)), name: Answer1.updatedNotification, object: nil)
}
#objc func answerUpdated(notification: Notification) {
// Update your content
}
}

Adding an array of Json Data to Realm

I'm making an app for airports and I'm getting an array of data from one api, like so:
"data":[
{"id":"001","code":"ABZ","name":"Aberdeen","country":"United Kingdom"},
{"id":"002","code":"AUH","name":"Abu Dhabi","country":"United Arab Emirates"},
.
.
.
]
AND :
"airports":[
{"from":"001",
"to":["1","3","11","13","12","20","23","27","29","31","33"]
},
.
.
.
]
I have created realm model classes:
class AirportsDataRealm: Object {
#objc dynamic var name: String = ""
#objc dynamic var id: Int = 0
#objc dynamic var code: String = ""
#objc dynamic var country: String = ""
override static func primaryKey() -> String? {
return "id"
}
}
class AirportsFromToRealm: Object {
#objc dynamic var fromID: Int = 0
var toID = List<Int>()
override static func primaryKey() -> String? {
return "fromID"
}
}
now I want to save it into realm, I'm using swiftyJSON and I have used for-loop to do it and it is working fine but I think it's taking long time since the array is very long, here is what I've done:
// Airports Data
let countData = json["data"].count
for i in 0...countData - 1{
let airportsDataModel = AirportsDataRealm()
airportsDataModel.code = json["data"][i]["code"].stringValue
airportsDataModel.name = json["data"][i]["name"].stringValue
airportsDataModel.country = json["data"][i]["country"].stringValue
airportsDataModel.id = Int(json["data"][i]["id"].stringValue)!
try! realm.write {
realm.add(airportsDataModel, update: true)
}
}
//Airports FROM-TO
let countFromTo = json["airports"].count
for i in 0...countFromTo - 1{
let fromToDataModel = AirportsFromToRealm()
fromToDataModel.fromID = Int(json["airports"][i]["from"].stringValue)!
let arrayTo = json["airports"][i]["to"].arrayValue.map{ $0.intValue }
fromToDataModel.toID.append(objectsIn: arrayTo)
try! realm.write {
realm.add(fromToDataModel, update: true)
}
}
is there any way to save the whole array in realm in one shot without for-loop?
P.S
"there should be a relation between the two tables because each from 'id' has a list of 'to' id's and the id's are from the data table, for now I managed to create this relations when fetching the data using filters ,, so just ignore this"
Thank you
Simply use map method,
First I needed to add initializers to my object classes and pass json array as a parameter, like so:
class AirportsDataRealm: Object {
#objc dynamic var name: String = ""
#objc dynamic var id: Int = 0
#objc dynamic var code: String = ""
#objc dynamic var country: String = ""
convenience required init(withJSON json : JSON) {
self.init()
self.name = json["name"].stringValue
self.id = json["id"].intValue
self.code = json["code"].stringValue
self.country = json["country"].stringValue
}
override static func primaryKey() -> String? {
return "id"
}
}
class AirportsFromToRealm: Object {
#objc dynamic var fromID: Int = 0
var toID = List<Int>()
convenience required init(withJSON json : JSON) {
self.init()
self.fromID = json["from"].intValue
let toArray = json["to"].arrayValue.map{ $0.intValue }
self.toID.append(objectsIn: toArray)
}
override static func primaryKey() -> String? {
return "fromID"
}
}
Then by using map method the code will look like this:
func updateAirport(json: JSON) {
// Airports Data
let airportsData : [AirportsDataRealm]
let airportsDataJsonArray = json["data"].array
airportsData = airportsDataJsonArray!.map{AirportsDataRealm(withJSON: $0)}
//Airports FROM-TO
let airportsFromTo : [AirportsFromToRealm]
let airportsFromToJsonArray = json["airports"].array
airportsFromTo = airportsFromToJsonArray!.map{AirportsFromToRealm(withJSON: $0)}
//Write To Realm
try! realm.write {
realm.add(airportsData, update: true)
realm.add(airportsFromTo, update: true)
}
}
No for loops anymore ^_^

realm array index out of bounds

I want to save data into realm if the user clicks on a button. Moreover the view should be updated if the user clicks that button. I have the following code:
#IBAction func saveAction(_ sender: UIButton) {
if currentLogWeightTextField.text!.isEmpty || currentLogRepsTextField.text!.isEmpty || currentLogRPETextField.text!.isEmpty {
errorLabel.isHidden = false
return
}
else{
if let weight = Float(currentLogWeightTextField.text!), let reps = Int(currentLogRepsTextField.text!), let rpe = Float(currentLogRPETextField.text!){
errorLabel.isHidden = true
let setToSave = excercisesFromPlan![excerciseCounter].sets[setCounter]
do{
try realm.write{
setToSave.weight = weight
setToSave.repeats = reps
setToSave.rpe = rpe
}
}
catch{
print(error)
}
}
else{
errorLabel.isHidden = false
return
}
if setCounter < excercisesFromPlan![excerciseCounter].sets.count{
setCounter += 1
setupLabels()
print(setCounter)
print(excercisesFromPlan![excerciseCounter].sets.count)
}
else{
let finished = plan!.excercises.count - 1
if excerciseCounter == finished{
performSegue(withIdentifier: SegueIdentifier.finishedWorkout, sender: nil)
return
}
else{
excerciseCounter += 1
setCounter = 1
setupLabels()
}
}
}
}
This is my setupLabel method:
func setupLabels(){
if let excercise = excercisesFromPlan?[excerciseCounter]{
excerciseNameLabel.text = "\(excercise.name)"
setsNumberLabel.text = "\(setCounter)/\(excercise.sets.count)"
}
}
These are the relevant properties:
var excercisesFromPlan: List<Excercise>?
var plan: TrainingPlan?
var excerciseCounter = 0
var setCounter = 1
excercisesFromPlan = plan?.excercises
The plan property is given through a segue.
These are my model classes:
class TrainingPlan: Object {
dynamic var trainingPlanID = NSUUID().uuidString
dynamic var routine: Routine?
dynamic var workout: Workout?
dynamic var selected = false
dynamic var name = ""
dynamic var trainingPlanDescription = ""
dynamic var creationDate = Date(timeIntervalSince1970: 1)
dynamic var lastChangeDate = Date(timeIntervalSince1970: 1)
dynamic var lastUsed = Date(timeIntervalSince1970: 1)
let excercises = List<Excercise>()
override class func primaryKey() ->String?{
return "trainingPlanID"
}
}
class Excercise: Object {
dynamic var excerciseID = NSUUID().uuidString
dynamic var trainingsplan: TrainingPlan?
dynamic var selected = false
dynamic var name = ""
dynamic var excerciseDescription = ""
dynamic var muscleGroup = ""
dynamic var record = 0
dynamic var picture: NSData?
dynamic var copied = false
let sets = List<TrainingSet>()
override class func primaryKey() ->String?{
return "excerciseID"
}
override static func indexedProperties() -> [String] {
return ["name"]
}
}
I have the problem that if I use this code and click the save button, the Labels are updating right and the counter are also working. The only problem is that the else statement
else{
let finished = plan!.excercises.count - 1
if excerciseCounter == finished{
performSegue(withIdentifier: SegueIdentifier.finishedWorkout, sender: nil)
return
}
else{
excerciseCounter += 1
setCounter = 1
setupLabels()
}
}
is never been called. I'm searching for the problem for a few hours now but I can't find it..
Strangely, if I comment out the following from the save function it works perfectly and the else statement is called right:
if let weight = Float(currentLogWeightTextField.text!), let reps = Int(currentLogRepsTextField.text!), let rpe = Float(currentLogRPETextField.text!){
errorLabel.isHidden = true
let setToSave = excercisesFromPlan![excerciseCounter].sets[setCounter]
do{
try realm.write{
setToSave.weight = weight
setToSave.repeats = reps
setToSave.rpe = rpe
}
}
catch{
print(error)
}
}
else{
errorLabel.isHidden = false
return
}
Sorry for so much code.. Does anyone know why this is not working? Thanks in advance!

NSUserDefaults Custom object - Property list invalid for format: 200 (property lists cannot contain objects of type 'CFType')

I must be incorrectly using Custom Objects for NSUserDefaults. The error " Property list invalid for format: 200 (property lists cannot contain objects of type 'CFType')". Below is my code, the Goal class is of particular interest, since this is where I am adopting the NSCoding protocol.
This code is global.
func saveGoals (goals : [Goal]) {
var updatedGoals = NSKeyedArchiver.archivedDataWithRootObject(goals)
NSUserDefaults.standardUserDefaults().setObject(updatedGoals, forKey: "Goals")
NSUserDefaults.standardUserDefaults().synchronize()
}
func loadCustomObjectWithKey() -> [Goal] {
if let encodedObject : NSData = NSUserDefaults.standardUserDefaults().objectForKey("Goals") as? NSData {
var encodedObject : NSData? = NSUserDefaults.standardUserDefaults().objectForKey("Goals") as? NSData
var goal : [Goal] = NSKeyedUnarchiver.unarchiveObjectWithData(encodedObject!) as [Goal]
return goal
} else {
return [Goal]()
}
}
This code is in GoalsViewController.
class GoalsViewController: MainPageContentViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var tableView: GoalsTableView!
var cell = GoalTableViewCell()
var goalsArray : Array<Goal> = [] //
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
if var storedGoals: [Goal] = loadCustomObjectWithKey() as [Goal]? {
goalsArray = storedGoals
}
//retrieve data.
var goal = Goal(title: "Walk the Dog")
goalsArray.append(goal)
saveGoals(goalsArray)
self.tableView?.reloadData()
tableView.estimatedRowHeight = 44.0
tableView.rowHeight = UITableViewAutomaticDimension
var notification = NSNotificationCenter.defaultCenter()
notification.addObserver(self, selector: "finishCreatingGoal:", name: "FinishCreatingGoal", object: nil)
}
func finishCreatingGoal(notification : NSNotification) {
if (notification.name == "FinishCreatingGoal") {
var userInfo = notification.userInfo!
var text = userInfo["text"]! as String
var index = userInfo["index"]! as Int
var cell = self.tableView.cellForRowAtIndexPath(NSIndexPath(forRow: index, inSection: 0)) as GoalTableViewCell
goalsArray[index].title = cell.goalTextField.text
saveGoalList(goalsArray)
self.tableView.reloadData()
self.tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: index, inSection: 0), atScrollPosition: UITableViewScrollPosition.Middle, animated: true)
}
}
This code is in the Goal class.
import UIKit
class Goal : NSObject, NSCoding {
var title : String? = ""
var checkmarked : Bool? = false
var isLastCell : Bool? = false
var enabled : Bool? = true
var priority = Priority.defaultPriority
override init() {
}
init(title : String) {
self.title = title
}
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(title!, forKey: "title")
aCoder.encodeBool(checkmarked!, forKey: "checkmarked")
aCoder.encodeBool(isLastCell!, forKey: "isLastCell")
aCoder.encodeBool(enabled!, forKey: "enabled")
}
required init(coder aDecoder: NSCoder) {
title = aDecoder.decodeObjectForKey("title") as String!
checkmarked = aDecoder.decodeBoolForKey("checkmarked") as Bool
isLastCell = aDecoder.decodeBoolForKey("isLastCell") as Bool
enabled = aDecoder.decodeBoolForKey("enabled") as Bool
}
}
I am going to just copy code from a working project I have:
here is the Game object class with data from a math flash card game:
import Foundation
class GameData: NSObject {
var sign: String = "+"
var level: Int = 1
var problems: Int = 10
var time: Int = 30
var skipWrong: Bool = true
var usedTime: Int = 0
var correctCount: Int = 0
var correctTopNumber: [Int] = [Int]()
var correctBottomNumber: [Int] = [Int]()
var wrongTopNumber: [Int] = [Int]()
var wrongBottomNumber: [Int] = [Int]()
var date: NSDate = NSDate()
func encodeWithCoder(aCoder: NSCoder!) {
aCoder.encodeObject(sign, forKey: "sign")
aCoder.encodeInteger(level, forKey: "level")
aCoder.encodeInteger(problems, forKey: "problems")
aCoder.encodeInteger(time, forKey: "time")
aCoder.encodeBool(skipWrong, forKey: "skipWrong")
aCoder.encodeInteger(usedTime, forKey: "usedTime")
aCoder.encodeInteger(correctCount, forKey: "correctCount")
aCoder.encodeObject(correctTopNumber, forKey: "correctTopNumber")
aCoder.encodeObject(correctBottomNumber, forKey: "correctBottomNumber")
aCoder.encodeObject(wrongTopNumber, forKey: "wrongTopNumber")
aCoder.encodeObject(wrongBottomNumber, forKey: "wrongBottomNumber")
aCoder.encodeObject(date, forKey: "date")
}
init(coder aDecoder: NSCoder!) {
sign = aDecoder.decodeObjectForKey("sign") as String
level = aDecoder.decodeIntegerForKey("level")
problems = aDecoder.decodeIntegerForKey("problems")
time = aDecoder.decodeIntegerForKey("time")
skipWrong = aDecoder.decodeBoolForKey("skipWrong")
usedTime = aDecoder.decodeIntegerForKey("usedTime")
correctCount = aDecoder.decodeIntegerForKey("correctCount")
correctTopNumber = aDecoder.decodeObjectForKey("correctTopNumber") as Array
correctBottomNumber = aDecoder.decodeObjectForKey("correctBottomNumber") as Array
wrongTopNumber = aDecoder.decodeObjectForKey("wrongTopNumber") as Array
wrongBottomNumber = aDecoder.decodeObjectForKey("wrongBottomNumber") as Array
date = aDecoder.decodeObjectForKey("date") as NSDate
}
override init() {
}
}
This part looks about the same as yours, but with more variable types. The archiver and retriever classes differ from you:
import Foundation
class ArchiveGameData:NSObject {
var documentDirectories:NSArray = []
var documentDirectory:String = ""
var path:String = ""
func ArchiveResults(#dataSet: [GameData]) {
documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
documentDirectory = documentDirectories.objectAtIndex(0) as String
path = documentDirectory.stringByAppendingPathComponent("results3.archive")
if NSKeyedArchiver.archiveRootObject(dataSet, toFile: path) {
//println("Success writing to file!")
} else {
println("Unable to write to file!")
}
}
func RetrieveGameData() -> NSObject {
var dataToRetrieve = [GameData]()
documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
documentDirectory = documentDirectories.objectAtIndex(0) as String
path = documentDirectory.stringByAppendingPathComponent("results3.archive")
if let dataToRetrieve2 = NSKeyedUnarchiver.unarchiveObjectWithFile(path) as? [GameData] {
dataToRetrieve = dataToRetrieve2
}
return(dataToRetrieve)
}
}
Finally, the code for storing and retrieving from within a ViewController:
//retrieveing
var gameDataArray = ArchiveGameData().RetrieveGameData() as [GameData]
//Archiving
gameData = GameData() //create local object then append all the new data, then store it
gameData.sign = buttonStates.sign
gameData.level = buttonStates.level
gameData.problems = buttonStates.problems
gameData.time = buttonStates.time
//etc. for all properties
ArchiveGameData().ArchiveResults(dataSet: gameDataArray)

Resources