Add Data in multiple classes Realm swift - swift

I'm new to swift. I'm working with realm in swift. I've a realm database which have following classes.
I'm inserting same data in each class from application as:
for item in myarray {
print(item)
let realm = try! Realm(fileURL: db_path!)
try! realm.write({
let obj = English()
obj.rowid = ((item["rowid"] as? NSString)?.integerValue)!
obj.words = (item["word"] as? NSString)! as String
obj.frequency = ((item["frequency"] as? NSString)?.integerValue)!
realm.add(obj)
print("successfully added to database")
})
}
class English : Object {
#objc dynamic var rowid = 0
#objc dynamic var words = ""
#objc dynamic var frequency = 0
}
This is saving data in English class. Now I want to save same object in other realm class like Arabic, languages, test.
Should I've to make separate object type class for each class?

No ,you can create object of each class and assign English class object to other like this
let obj1 = Arabic()
obj1 = obj//English Class Object
And append like this
realm.add(obj1)

Related

Realm Migration: Migrating objects to another

I've added a new Model object to my realm objects and I am trying to move data from my old realm object properties to this new object.
In the old Schema, I have the following:
class Item: Object {
#objc dynamic var image = ""
#objc dynamic var coverImage = ""
#objc dynamic var video = ""
}
In the new schema, I've added a new property called media
so now it's looking this this
class Item: Object {
#objc dynamic var image = ""
#objc dynamic var coverImage = ""
#objc dynamic var video = ""
#objc dynamic var media: Media?
}
I've also added this new Model object:
class Media: Object {
#objc dynamic var fullImage = ""
#objc dynamic var thumbnailImage = ""
#objc dynamic var video = ""
var item = LinkingObjects(fromType: Item.self, property: "media")
}
My goal is to move the data from the old Item objects to the new Media objects.
I was trying to do something like this, but I don't know how to migrate that linking object, any help in the right direction would be appreciated.
Realm.Configuration.defaultConfiguration = Realm.Configuration(
schemaVersion: 1,
migrationBlock: { migration, oldSchemaVersion in
if (oldSchemaVersion < 1) {
// enumerate first object
migration.enumerateObjects(ofType: Item.className()) { oldItem, newItem in
let image = oldItem?["image"] as! String
let coverImage = oldItem?["coverImage"] as! String
let video = oldItem?["video"] as! String
//migrate second object
migration.enumerateObjects(ofType: Media.className(), { (oldMedia, newMedia) in
})
}
}
})
You don't need to do anything with LinkingObjects, realm calculates those automatically when you query them.
All you'll need to do in your migration is set media to be a new Media object with the values you already have.
Other notes:
The second enumerateObjects isn't needed.
You can remove image, coverImage, and video from Item since you're moving those value to Media
Edit: This is what you would need to have in your migration.
let media = Media()
media.fullImage = oldItem?["image"] as! String
media.thumbnailImage = oldItem?["coverImage"] as! String
media.video = oldItem?["video"] as! String
newItem?["media"] = media
When adding objects to a project, the migration is super simple. In this case you're not changing or adding data to existing or new properties so it's even easier.
All that needs to be done is to increment the schemaVersion and implement your migration block. Suppose the prior version was 1, increment that to 2.
let config = Realm.Configuration (
schemaVersion: 2,
migrationBlock: { migration, oldSchemaVersion in
//nothing to do here since we not altering any data
})
Realm already knows your Object has data and that data will persist as it's not being altered. All of the Item objects will have the new media property added and linked to the new Media object.
See Local Migrations for more examples. The Updating values section is when you want to actually manipulate the existing data
Edit:
We now have a bit more information and what the OP is trying to do is to copy data from an existing object to a new object and then create a relationship between the objects. Here's the code that would do that.
The initial object is Item and the new object is Media. For this example I am copying the data in a Item property image to the Media property fullImage
let config = Realm.Configuration (
schemaVersion: 1,
migrationBlock: { migration, oldSchemaVersion in
migration.enumerateObjects(ofType: Item.className() ) { oldObject, newObject in
let image = oldObject!["image"] as! String
let media = Media()
media.fullImage = image
newObject!["media"] = media
}
})

How to retrieve the ‘List<myObject>' realm array to array from realm model class?

My realm model class look like
class RoomRealmModel : Object {
dynamic var id: String = ""
var details = List<RoomDetailRealmModel>()
func saveItem() {
do {
let realm = try Realm()
realm.beginWrite()
realm.add(self, update: true)
try realm.commitWrite()
} catch{}
}
}
class RoomDetailRealmModel : Object{
dynamic var detailId: String = ""
dynamic var displayText: String = ""
}
I want to retrieve 'details' from the following.
details = RLMArray<RoomDetailRealmModel> <0x600000114f40> (
[0] RoomDetailRealmModel {
text = hello;
Counters = 9;
ParentID = ;
detailId = 33;
displayText = hello ;
}
);
I always get empty like in my console
(lldb) po (destinationData?[index]?.details)!
List<RoomDetailRealmModel> <0x600000853620> (
)
I am updating ‘details’ list via realm update command. I always get realm array.But I want to retrieve array type from realm array.Please help me, how to solve this issue
If you want to obtain [myObject] instead of List you can do something like this:
var array: [myObject] = [myObject]()
for object in myObjectList {
array.append(object)
}
Where myObjectList is List.
You can simply create a regular Swift Array from a Realm List by calling the initializer of Array accepting a Sequence, since List conforms to the sequence protocol.
So you can simply do
let room = RoomRealmModel()
let roomDetailsArray = Array(room.details)

Generic Type array with UITableView and Realm

I am using realm for database. I have Favourite Object and History Object.
I want to show in TableViewController. However, I don't want to do duplicated code. For now, in FavouriteViewController , it has var favs: Results<OGFav>? and HistoryViewController, it has var history: Results<OGHistory>?
Most of the code are the same and different is data type.
Example: it only different like following
if let object:OGFav = self.favs?[indexPath.row] {
In some place , I use like
let fav:OGFav = favs[indexPath.row]
For History
if let object:OGHistory = self.history?[indexPath.row] {
History also use like below
let history:OGHistory = self.history[indexPath.row]
How can I clean the code ? I am using two viewcontroller and code are the same excepted OGFav and OGHistory.
Update:
OGFav and OGHistory have the same data.
class OGFav: Object {
dynamic var word = ""
dynamic var def = ""
}
class OGHistory: Object {
dynamic var word = ""
dynamic var def = ""
dynamic var updatedAt = NSDate()
}

Realm + swift sorting

Wondering if anyone have faced & solved this issue:
Description
I have 2 Classes called Person & Dog where a person can have more than one dog.
class Dog: Object {
dynamic var name = ""
dynamic var age = 0
}
class Person: Object {
dynamic var name = ""
dynamic var picture: NSData? = nil // optionals supported
let dogs = List<Dog>()
}
According to my requirement, I need to fetch all objects from person.name == "ABC" & apply sort all dogs by Name.
Snippet:
let realm = try! Realm()
let result = realm.objects(Person.self).filter("name == %#","ABC").sorted(property : "name")
From the above snippet, sorting is done based on the person Name not on the dog's Name.
How to create a filter & sort the list by dog name?
realm.objects(Person.self) returns Results<Person>. Calling sorted() to Results<Person> means sort Person. If you'd like to sort dogs, you can retrieve element of person first, (e.g. let person = result[0]), then retrieve dogs property, call sorted() method to it.
let people = realm.objects(Person.self).filter("name == %#","ABC")
let person = people.first!
let sortedDogs = person.dogs.sorted(property : "name")

Filtering Realm objects with Swift

I always get the following error when trying to filter my Realm database using NSPredicate:
Property 'text' is not a link in object of type 'getType'
I want to filter my Realm database to show only the items that have some specific text in them. This is what I've tried:
let realm = try! Realm()
let predicate = NSPredicate(format: "typez.text.filter = 'special'")
let filterThis = realm.objects(Publication).filter(predicate)
print(filterThis)
The relevant portion of my model classes is:
class Publication: Object, Mappable {
dynamic var id: Int = 0
var typez = List<getType>()
dynamic var url: String?
}
class getType: Object, Mappable {
dynamic var text: String = ""
}
You mentioned that the relevant portions of you model classes look like so:
class Publication: Object, Mappable {
dynamic var id: Int = 0
var typez = List<getType>()
dynamic var url: String?
}
class getType: Object, Mappable {
dynamic var text: String = ""
}
If I understand you correctly, you want to find Publication instances that have an entry in their typez list with text equal to special. You can express that as:
let realm = try! Realm()
let result = realm.objects(Publication).filter("ANY typez.text = 'special'")
print(result)
I was not liking the accepted answer here because it doesn't actually answer the question... but then it helped me more than I realized. I will now be using closures instead of NSPredicates whenever possible. The actual answer to this question should be a slightly modified version of #NSGangster's answer:
let realm = try! Realm()
//Array of publications
let realmObjects = realm.objects(Publication)
//any publication where .text property == special will be filtered. and filter out empty array
let filterThis = realmObjects.filter({ $0.typez.filter({ $0.text == "special" } != [] ) })
print(filterThis)
.. or something close to that.
But what I was looking for was a bit different. I needed a way to filter on exact words of a multi-word string, and using an NSPredicate with "CONTAINS" would match any containing substring, e.g. a search for "red" would match "fred". Realm doesn't support "LIKE" or regex yet, so using a closure was the only thing I could get to work:
//I was going for a "related terms" result for a dictionary app
let theResults = terms.filter(
{
//Looking for other terms in my collection that contained the
//title of the current term in their definition or more_info strings
$0.definition.components(separatedBy: " ").contains(term.title) ||
$0.more_info.components(separatedBy: " ").contains(term.title)
}
)
With as much of the day as I spent searching, hopefully this helps someone else with a similar issue.
I don't usually use NSPredicate's directly, instead I do an inline predicate closure within the filter paramter.
let realm = try! Realm()
//Array of publications
let realmObjects = realm.objects(Publication)
//any publication where .text property == special will be filtered. and filter out empty array
let filterThis = realmObjects.filter({ $0.getType.filter({ $0.text == "special" } != [] ) })
print(filterThis)