Adding a new relationship to an existing model in Realm - ios

I'm developing an iOS application using Realm and have a object MedicationObject which contains the information about the Medication being used. This then has a many to one relationship class MedicationRecording which stores the information when the time the medication was taken.
import Foundation
import RealmSwift
class MedicationObject : Object {
//This model requires a Primary Key
#objc dynamic var id = 0
override static func primaryKey() -> String? {
return "id"
}
#objc dynamic var medicationName : String = ""
//stores the refrences to medication recoridngs
var messurements = List<MedicationRecording>()
public func addNewMesurment() {
print(self)
let medicationRecording = MedicationRecording()
medicationRecording.medicationTaken = self
medicationRecording.timeTaken = Date()// this saves the time to now
medicationRecording.medicationTaken = self
RealmAccess().updateMedicationObject(medicationObject: self, medicationRecord: medicationRecording) //this should work
}
}
here is my MedicationRecording:
import Foundation
import RealmSwift
class MedicationRecording : Object {
#objc dynamic var medicationTaken : MedicationObject? = MedicationObject()
#objc dynamic var timeTaken : Date = Date()
#objc dynamic var id = 0
override static func primaryKey() -> String? {
return "id"
}
}
and this is the method I'm calling to save the data to
func updateMedicationObject(medicationObject : MedicationObject, medicationRecord : MedicationRecording) {
let realm = try! getRealmAccess()
let mediObject = MedicationObject()
mediObject.medicationName = medicationObject.medicationName
do {
try! realm.write {
realm.add(medicationRecord, update: true)
medicationObject.messurements.append(medicationRecord)
}
}
}
At the moment when I'm saving the data it is then losing all the information in MedicationObject and only saving the last data.
Any help with be greatly appreciated
Thank you

Related

Separate Realm SWIFT data into lists -- and bring data back together?

So, I am a COMPLETE newbie, learning by doing real hands-on projects. I am attempting to create an app that can keep track of car parts. I'm trying to use Realm Database. In order to be organized, I'd like to keep everything separated by key bunches: "partInfo", "storeInfo", and "mechanicInfo" and then bring this back together again with the list feature of realm. Please see my code below and tell help me learn how to go about it? Thanks in advance!
I'm also trying to do MVC pattern--not sure if I did this right by separating everything out or not.
Here's my code for storeinfo.swift
import Foundation
import RealmSwift
class StoreInfo: Object {
#objc dynamic var _id = ObjectId.generate()
#objc dynamic var storeName: String = ""
#objc dynamic var storeNumber: String? = ""
#objc dynamic var storeAddress: String = ""
var catalog = LinkingObjects(fromType: Catalog.self, property: "stores")
//var itemImgs = List<String>()
override static func primaryKey() -> String? {
return "_id"
}
}
Here's my code for partinfo.swift
import Foundation
import RealmSwift
class PartInfo: Object {
#objc dynamic var _id = ObjectId.generate()
#objc dynamic var partName: String = ""
#objc dynamic var partNumber: String = ""
#objc dynamic var partDescription: String? = ""
#objc dynamic var partCost: Double = 0.00
#objc dynamic var partQuantity: Int = 0
#objc dynamic var purchaseDate: String = ""
#objc dynamic var hasWarranty: Bool = true
#objc dynamic var warrantyLength: String? = ""
var catalog = LinkingObjects(fromType: Catalog.self, property: "parts")
//var itemImgs = List<String>()
override static func primaryKey() -> String? {
return "_id"
}
}
here's my code for mechanicinfo.swift
import Foundation
import RealmSwift
class MechanicInfo: Object {
#objc dynamic var _id = ObjectId.generate()
#objc dynamic var mechanicName: String = ""
#objc dynamic var mechanicNumber: String = ""
#objc dynamic var mechanicAddress: String? = ""
#objc dynamic var mechanicCost: Double = 0.00
#objc dynamic var serviceDate: String = ""
var catalog = LinkingObjects(fromType: Catalog.self, property: "mechanics")
//var itemImgs = List<String>()
override static func primaryKey() -> String? {
return "_id"
}
}
and finally (where I'm stuck at) -- the code for Catalog.swift
import Foundation
import RealmSwift
class Catalog: Object {
#objc dynamic var _id = ObjectId.generate()
var parts = RealmSwift.List<PartInfo>()
var stores = RealmSwift.List<StoreInfo>()
var mechanics = RealmSwift.List<MechanicInfo>()
//var itemImgs = List<String>()
override static func primaryKey() -> String? {
return "_id"
}
when I go to try to use it, I'm getting an error of already using the same name. can't use it twice: (so I had to do 3 instances of wipers, which works, but it's not what I wanted...please help!)
My ViewController:
import UIKit
import RealmSwift
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let realm = try! Realm()
print(Realm.Configuration.defaultConfiguration.fileURL!)
let wipers = PartInfo()
wipers.partName = "TRICO HD 32 Inch Wiper Blades"
wipers.partNumber = "67-324"
wipers.hasWarranty = true
wipers.warrantyLength = "2 years"
wipers.purchaseDate = "04/21/2021"
wipers.partCost = 34.99
wipers.partQuantity = 2
wipers.partDescription = "Great set. Lifespan of 6 - 9 months."
let wipers2 = StoreInfo()
wipers2.storeName = "O'Reilly AutoParts"
wipers2.storeAddress = "1003 W Broad St, Groveland, FL 34736"
wipers2.storeNumber = "4474"
let wipers3 = MechanicInfo()
wipers3.serviceDate = "04/24/2021"
wipers3.mechanicAddress = "17605 Sunshine Circle, Winter Garden, FL, 34787"
wipers3.mechanicCost = 289.58
wipers3.mechanicName = "Bob Barnicles"
wipers3.mechanicNumber = "353-256-7893"
try! realm.write {
realm.add(wipers)
realm.add(wipers2)
realm.add(wipers3)
}
}
}

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 ^_^

How to make search query to get all Objects in Realm

I am creating a Realm object like below
import RealmSwift
class Item: Object {
#objc dynamic var ID = 0
#objc dynamic var notificationTitleString = ""
#objc dynamic var notificationBodyString = ""
#objc dynamic var notificationDateString = ""
#objc dynamic var notificationType = ""
#objc dynamic var notificationUrl = ""
#objc dynamic var notificationActivity = ""
#objc dynamic var notificationIsRead = ""
override static func primaryKey() -> String? {
return "ID"
}
}
I am using the below method to get a particular item type
import UIKit
import RealmSwift
class DBManager {
private var database: Realm
static let sharedInstance = DBManager()
private init() {
database = try! Realm()
print(Realm.Configuration.defaultConfiguration.fileURL!)
}
func fetchNotificationType(type: String) -> Results<Item> {
let predicate = NSPredicate(format: "notificationType = %#", type)
let results : Results = database.objects(Item.self).filter(predicate)
return results
}
}
Using the above fetchNotificationType method i am able to get a single object, But i want all the objects in a single query. I do not know how to do that, I am trying Realm for the first time.
I searched SO, but i did not get any related answers.

EVReflection + Moya + Realm + RxSwift - Could not create an instance for type dict

I'm stuck putting all of the above together. I'll appreciate if I can get any input.
Here's my short setup:
typealias RealmObject = Object
/// Extension to ignore undefined keys when mapping
extension RealmObject : EVReflectable {
open override func setValue(_ value: Any?, forUndefinedKey key: String) { }
}
Sample Realm models:
class Product: RealmObject {
dynamic var productId: String = ""
let productLanguages = List<ProductLanguage>()
override static func primaryKey() -> String? {
return "productId"
}
}
class ProductLanguage: RealmObject {
dynamic var productLanguageId: String = ""
dynamic var languageCode: String = ""
dynamic var productName: String = ""
override static func primaryKey() -> String? {
return "productLanguageId"
}
}
To fetch product details I use Moya and RxSwift:
func getProduct(productItemKey: String) -> Observable<Product> {
return provider.request(.product(productId: productItemKey)).map(to: Product.self)
}
I think .map(to: Product.self) does not work with realm Lists out of the box. For each object inside the list I get an error:
ERROR: Could not create an instance for type
dict:{
CreateDate = "2015-10-12T11:11:50.013Z";
IngredientList = "Acao ingredient";
LanguageCode = "en-US";
ProductId = "d6bb0084-6838-11e5-9225-00ac14ef2300";
ProductLanguageId = "f96848d0-df77-4594-99b7-d390bb127891";
ProductName = Acao;
Tagline = "The smart drink - 100% organic, vegan energy booster with guara"
}
Is there any other way to map Moya response into Realm objects?
Thank you very much for any input!
Turns out it was a bug in EVReflection. Fixed in 4.17.0

How to check what class belongs AnyObject?

For example, there are two models Realm Information
import Foundation
import RealmSwift
class Music: Object {
dynamic var id = ""
dynamic var title = ""
dynamic var url = ""
}
class DownloadMusic: Object {
dynamic var id = ""
dynamic var title = ""
dynamic var path = ""
}
And there is a certain function
func test(object: AnyObject) {
}
When a call is transferred as an argument 'realm.objects(Music)[0]'
let realm = try! Realm()
test(realm.objects(Music)[0])
Can I check in function, the object belongs to a class 'Music' or to a 'DownloadMusic'
Try this:
func test(object: AnyObject) {
if object is Music {
print("music")
} else if object is DownloadMusic {
print("downloadmusic")
}
}

Resources