Realm list property not saving data - ios

I have two models, lets call them Schools, and Teachers. Models are as under
#objcMembers public class Schools : Object {
dynamic var Id : String = ""
dynamic var UserId : Int64 = 0
dynamic var Name : String? = ""
dynamic var listTeachers : List<Teachers>? = nil
dynamic var teachersList : [Teachers]? = []
}
#objcMembers public class Teachers : Object {
dynamic var Id : String = ""
dynamic var UserId : Int64 = 0
dynamic var Name : String? = ""
}
now before saving data I m putting Teachers objects (list) in School object then I save that School object in realm write closure.
after that I just get the School realm object and when I get the Teachers list, it always gets Nil. What is the case?
Am i missing something or missing something to understand the real LIST property??
please help
Update: This is how I am getting object
let mSavedItems = mDbHelper.realmObj.objects(Schools.self)
if let teachers = mSavedItems[0].teachersList{// here teacher list is nil
}

Your Schools declaration is flawed. You shouldn't declare a List as dynamic or mutable, nor should you make it Optional. As the docs clearly state, let listTeachers = List<Teachers>() is the correct way to declare a many-to-many relationship.
Storing a property of type Array is also not supported by Realm, so you should delete the teachersList : [Teachers]? property.
#objcMembers public class Schools : Object {
dynamic var Id : String = ""
dynamic var UserId : Int64 = 0
dynamic var Name : String? = ""
let listTeachers = List<Teachers>()
}

Related

Realm Relation how to implement

I am working on iOS and that is saving product. and this product has some more things inside its model
let suppose the following model
#objcMembers public class ProductModel : Object, Codable {
dynamic var Id : Int = 0
dynamic var Name : String = 0
dynamic var Price : Double = 0.0
}
and the other model (CustomerModel) that contains the ProductModel is as follow
#objcMembers public class CustomerModel : Object, Codable {
dynamic var Id : Int = 0
dynamic var Name : String = 0
var Product : ProductModel? = nil
}
Now when I save customer with the product inside it, I can see that in Realm it gets saved successfully. But if and only if that object is not in Realm already,
Let suppose this
let customer1 = CustomerModel()
customer1.Id = ...
customer1.Name = .....
customer1.Product = product1
Now this customer data is saved. But I am getting exception if I try to save following data
let customer2 = CustomerModel()
customer2.Id = ...
customer2.Name = .....
customer2.Product = product1
Just notice that customer2 also want to save product info that is already saved in Realm namely "product1".
So how to handle this sitution.
I am trying to save the data with the following generic function for realm objects
func save <T: Object> (_ obj : T){
do {
try realmObj.write{
realm.add(obj)
}
}catch{}
}
Question 2:
Also I want to get All Customer, I know how to do it, but problem is It never retrieves the Product inside the Customer. I can see in Realm DB Browser that the customer that get saved with the product, that customer table contains the reference of Product also. But when I try to get all customer then that customer have only customer details not Product detail. Whereas that must be there.
Just put dynamic keyword before your property
dynamic var Product : ProductModel? = nil

Sometimes Classes treat like structures in swift?

for eg:-
In class DishPostedVC, I have an array of model:-
var finalDatesOfDish : [DishActivationDateTimeModel]?
If i pass this variable (finalDatesOfDish) to class DishActivationVC, and do some deletion operation in class DishActivationVC, and if i go back again to class DishPostedVC, then i am getting data after deletion not the actual data, but i am just coming back not passing any data.
I don't know why but this situation occurred one more time earlier with model array, its so strange, how's it possible?
can u tell me what shld i do?
class DishActivationDateTimeModel {
var dayDate: Date? = nil
var dayDateStr: String = ""
var servingsLeft: String = ""
var firstSlotPostedDishId: String = ""
var secondSlotPostedDishId: String = ""
var startTimeDateForFirstSlot: Date? = nil
var startTimeStringForFirstSlot: String = ""
var endTimeDateForFirstSlot: Date? = nil
var endTimeStringForFirstSlot: String = ""
var startTimeDateForSecondSlot: Date? = nil
var startTimeStringForSecondSlot: String = ""
var endTimeDateForSecondSlot: Date? = nil
var endTimeStringForSecondSlot: String = ""
}
It's my model
class DishActivationDateTimeModel {
var dayDate: Date? = nil
var dayDateStr: String = ""
var servingsLeft: String = ""
var firstSlotPostedDishId: String = ""
var secondSlotPostedDishId: String = ""
var startTimeDateForFirstSlot: Date? = nil
var startTimeStringForFirstSlot: String = ""
var endTimeDateForFirstSlot: Date? = nil
var endTimeStringForFirstSlot: String = ""
var startTimeDateForSecondSlot: Date? = nil
var startTimeStringForSecondSlot: String = ""
var endTimeDateForSecondSlot: Date? = nil
var endTimeStringForSecondSlot: String = ""
init(_ object : DishActivationDateTimeModel) {
self.dayDate = object.dayDate
self.dayDateStr = object.dayDateStr
// ....
// ....
self.endTimeStringForSecondSlot = object.endTimeStringForSecondSlot
}
}
extension Array where Element : DishActivationDateTimeModel {
func copyModelArray() -> [DishActivationDateTimeModel] {
var array : [DishActivationDateTimeModel] = []
for object in self {
array.append(DishActivationDateTimeModel(object))
}
return array
}
}
If you don't want to make changes in your main data then copy your
model array using copyModelArray method. And use your operational
model array. So, its not affect to your main model data array.
In Swift structs and classes give you both value and reference-based constructs for your objects. Structs are preferred for objects designed for data storage like Array. Structs also help remove memory issues when passing objects in a multithreaded environment. Classes, unlike structs, support inheritance and are used more for containing logic like UIViewController. Most standard library data objects in Swift, like String, Array, Dictionary, Int, Float, Boolean, are all structs, therefore value objects. The mutability of var versus let is why in Swift there are no mutable and non-mutable versions of collections like Objective C’s NSArray and NSMutableArray.
when you passed around your structs its copied but when you passed or assigned classes it gets reference to it.This means when you change class object in one location it changes everywhere, when you affect structs it changes individually. if you want more information differences between classes and structs you can check araound my article.
classes versus structs

How to link two Realm objects

I'm new to iOS development and currently using Realm as database. My first tableview display Restaurant object and second table display customer objects. How can i link this two objects?. Means when i click each restaurant it will display different customer.
class Restaurant: Object {
dynamic var restname: String = ""
dynamic var date: String = ""
}
class Customer: Object {
dynamic var id = 0
dynamic var name: String = ""
dynamic var price: Float = 0.0
dynamic var drinks: Float = 0.0
override static func primaryKey() -> String? {
return "id"
}
}
You make references to your models like so
class Customer: Object {
dynamic var restaurant: Restaurant?
}
You also have the possibility to get reverse relationship with LinkingObjects(fromType:, property:)
You can write in your other model
class Restaurant: Object {
let customers = LinkingObjects(fromType: Customer.self, property: "restaurant")
}
That way you don't duplicate relationships.
If I understand, in Restaurant class put this:
dynamic var _customer = Optional(Customer())
or in Customer class put this line:
dynamic var _restaurant = Optional(Restaurant())
NOTE: Name of variable with lower dash, may be any name, my habit is to put lower dash

How to get method for class in Swift

I have a class:
class myObject: NSObject {
dynamic var objectId : String?
dynamic var name : String?
dynamic var lastName : String?
dynamic var age : String?
}
In my other class I am getting the value of this class's property:
self.myArray.append(myObject.name!)
I can get the value of myObject.name by adding .name but what if there will be hundreds of properties in my myObject class? For that I want to create a method which can return the properties of my class using a variable:
let myVar = "name"
self.myArray.append(myObject.myVar)
It should append the values of property name, but I am getting an error:
value of myObject has no member `myVar`
and I know why I am getting the error.
How can I get access to properties of my class using a variable? Something like :getValue(String) should return that property of my class.
You should also have a look at NSMutableDictionary, here's a quick example which shows how it works
// initialise a dictionary
var dict = NSMutableDictionary(objects: ["first", "second", 42], forKeys: ["String1", "String2", "Int1"])
// add a new attribute
dict.addEntriesFromDictionary(NSDictionary(object: "New thing", forKey: "String3") as [NSObject : AnyObject])
// access the data
let firstString = dict.valueForKey("String1")
let firstInt = dict.valueForKey("Int1")
// update the data
dict.setValue(99, forKey: "Int1")
let newValue = dict.valueForKey("Int1")
I can be wrong, but as I've already said in a comment, it would be better to use Dictionary and store values in it. Also if you want to access some values with a dot-notation, but still be able to get them by string, you can just create a property and override setter and getter
class MyClass {
var properties = [String: AnyObject]()
var someProperty: String? {
get {
return properties["someProperty"] as? String
}
set {
properties["someProperty"] = newValue
}
}
This way you are able to access value of someProperty both by object.someProperty and object.properties["someProperty"]
You can do it making array of object like following
var arrayOfObjects = [myObject]
and then set an objects values
var firstObject:myObject
myObject.name = "Your name"
myObject.age = "Your age"
...
then append first object to arrayOfObjects
arrayOfObject.append(firstObject)
and you can access it
print("First Object's name: \(arrayOfObjects[0].name)")

Realm iOS relationship from mysql json results

I want to use Realm to my iOS app but I have a problem with the relationship. What I want to achieve is a relationship between the following two RLMobjects :
class Catalogue: RLMObject {
dynamic var ID = ""
dynamic var greekName = ""
dynamic var deutschName = ""
dynamic var createdAt = NSDate()
dynamic var updatedAt = NSDate()
override class func primaryKey() -> String? {
return "ID"
}
}
class Products: RLMObject {
dynamic var foodName = ""
dynamic var foodDescription = ""
dynamic var foodPrice = ""
dynamic var createdAt = NSDate()
dynamic var updatedAt = NSDate()
dynamic var category: Catalogue?
}
I am retrieving all my data from a server in JSON format and the problem is that
I can not set the category as relationship to Catalogue ID.
In my database the category field is a foreign key to the Catalogue ID.
Does anyone knows how can I do that in Realm?
Thank you in advance.
Rather than storing the Catalogue ID in the dynamic var category: Catalogue? relationship field you will need to find the Catalogue object and just store that directly. This is how you link objects and is an important and powerful part of using NoSQL type DB's like Realm.
I would also add an array of products relationship on Catalogue so that you can link all the products to the Catalogue itself.
You can see more discussion about this here if that wasn't fully clear. Hope this helps

Resources