I cannot seem to save data to realm in Swift!
In one of my classes I have the following:
func getDeviceIdAndPersist(){
print("getDeviceIdAndPersist")
let realm = try! Realm()
let realmWallet = RealmWallet()
let realmResults = realm.objects(RealmWallet.self)
for results in realmResults {
guard results.deviceId != nil else {
realmWallet.deviceId = NSUUID().UUIDString
try! realm.write() {
realm.add(realmWallet, update: true)
}
return
}
}
}
And it does not seem to save the data! I have code similar to this throughout my application and its saving data but this isn't!
Also I'm having trouble trying to persist my data, after i launch the application the data is stored using realm (which i can verify using the realm browser). However, once I re-launch the application the data no longer exists in realm! Does anyone have any suggestions as to why the data would not be persisted?
EDIT 1
Here is my realm class
class RealmWallet: Object {
dynamic var publicKey = NSData()
dynamic var preferredAddress = ""
dynamic var id = 0
let walletAddresses = List<Addresses>()
dynamic var fee: NSNumber = 0.0
dynamic var deviceId: String? = nil
dynamic var tempPreTax: String? = nil
dynamic var portalToken: String? = nil
let walletHasBackup = RealmOptional<Bool>()
let alreadyAskedForBluetooth = RealmOptional<Bool>()
let insecureMailSent = RealmOptional<Bool>()
let cameraAccessGranted = RealmOptional<Bool>()
let idNowSuccess = RealmOptional<Bool>()
dynamic var marketInfos = NSData()
override class func primaryKey() -> String? {
return "id"
}
}
EDIT 2
The NSUUID isn't the only data which I cannot save, the following is another example of data which I cannot seem to save using Realm:
onboardingModal!.bluetoothPressed = {() -> Void in
print("after onboardingModal")
self.cbManager = CBCentralManager(delegate: self, queue: nil)
print("REALM")
let realm = try! Realm()
do {
try! realm.write {
print("IN WRITE")
self.realmWallet.alreadyAskedForBluetooth.value = true
realm.add(self.realmWallet, update: true)
}
}
}
I faced the same problem. In my realm class i was missing #objc dynamic in front of stored properties. So added it like below. Then it worked for me.
#objc dynamic var address: Addres!
#objc dynamic var checklist: Checklist!
If your Results count is 0, it will not enter your for loop.
Try this instead.
func getDeviceIdAndPersist() {
let realm = try! Realm()
let realmResults = realm.objects(RealmWallet.self)
guard results.count > 0 else {
let realmWallet = RealmWallet()
realmWallet.deviceId = NSUUID().UUIDString
try! realm.write() {
realm.add(realmWallet, update: true)
}
return
}
}
Related
I am trying to take all the preloaded data that I entered into Realm Database and use it in my app. The problem I am having is that I am not able to load all the objects into a Results variable of my custom type. I have 530 entries in my preloaded database and none of them are showing up in the View Controller.
This data in stored in /Database/streetListings.realm
import UIKit
import RealmSwift
class StreetListing: Object {
#objc dynamic var houseNumber: String?
#objc dynamic var streetName: String = ""
#objc dynamic var trashDay: String = ""
convenience init(houseNumber: String?, streetName: String, trashDay: String) {
self.init()
self.houseNumber = houseNumber
self.streetName = streetName
self.trashDay = trashDay
}
}
import UIKit
import RealmSwift
class ViewController: UIViewController {
var realm: Realm!
var streetListings: Results<StreetListing>?
override func viewDidLoad() {
super.viewDidLoad()
let realmPath = Bundle.main.url(forResource: "streetListings", withExtension: "realm")!
let realmConfiguration = Realm.Configuration(fileURL: realmPath, readOnly: true)
realm = try! Realm(configuration: realmConfiguration)
streetListings = realm.objects(StreetListing.self)
}
}
(lldb) po realmPath
▿ file:///Users/raz/Library/Developer/CoreSimulator/Devices/3A4F3C1A-9C15-4AF0-B211-5125E3843075/data/Containers/Bundle/Application/B1331B06-EDFE-494C-A170-7FDB1B2CA291/NorthTrash.app/streetListings.realm
- _url : file:///Users/raz/Library/Developer/CoreSimulator/Devices/3A4F3C1A-9C15-4AF0-B211-5125E3843075/data/Containers/Bundle/Application/B1331B06-EDFE-494C-A170-7FDB1B2CA291/NorthTrash.app/streetListings.realm
(lldb) print realmConfiguration
(RealmSwift.Realm.Configuration) $R32 = {
_syncConfiguration = nil
_path = "/Users/raz/Library/Developer/CoreSimulator/Devices/3A4F3C1A-9C15-4AF0-B211-5125E3843075/data/Containers/Bundle/Application/B1331B06-EDFE-494C-A170-7FDB1B2CA291/NorthTrash.app/streetListings.realm"
_inMemoryIdentifier = nil
encryptionKey = nil
readOnly = true
schemaVersion = 0
migrationBlock = nil
deleteRealmIfMigrationNeeded = false
shouldCompactOnLaunch = nil
maximumNumberOfActiveVersions = nil
customSchema = nil
disableFormatUpgrade = false
}
(lldb) po streetListings
▿ Optional<Results<StreetListing>>
▿ some : Results<StreetListing> <0x7fbd2e607140> (
)
- rlmResults : RLMResults<StreetListing> <0x7fbd2e607140> (
)
If anyone can help me out with this that would be great. Thank you!
I have also worked on Realm Project.
Here is simple tip for loading all Object.
let realm = try? Realm()
let personData = realm?.objects(Person.self)
//write code for loading personData
Loading lot of objects can take time. Try accessing streetListings after a delay. Not sure why you need the database to be readOnly. If not, you can use NotificationToken to listen to changes made to the realm database.
I was able to get this to work. I changed my custom class from 'streetListings' to 'StreetListings'. Also created a brand new Xcode project and transferred all the existing files.
I have my class defined as:
class Device: Object {
dynamic public var assetTag = ""
dynamic var location = ""
}
I also have two arrays defined as:
let array = ["12", "42", "52", "876"]
let array2 = ["SC", "EDS", "DS", "EF"]
I would like to loop through the first array and add each value to my realm Device.assetTag object and loop through my second array and add each value to the Device.location object.
I tried using the code from the Realm readme to just add data from the first array but it did not seem to loop:
let realmArray = Device(value: array)
let realm = try! Realm()
try! realm.write {
realm.add(realmArray)
}
You have two arrays one that holds asetTags and Another location so first you have to build the object from those. You can do something like following (probably refactoring needed)
class Device: Object {
dynamic public var assetTag = ""
dynamic var location = ""
}
class Test {
let assetTags = ["12", "42", "52", "876"]
let locations = ["SC", "EDS", "DS", "EF"]
func saveDevice() {
let realm = try! Realm()
try! realm.write {
let allDevices = getDeviceArray()
for device in allDevices {
realm.add(device)
}
}
}
func getDeviceArray() -> [Device] {
let requiredDevices = [Device]()
var index = 0
for tag in assetTags {
let locationForTag = locations[index]
let device = Device()
device.assetTag = tag
device.location = locationForTag
requiredDevices.append(device)
index += 1
}
return requiredDevices
}
}
Remember to put loop within realm.write for batch operation, this ensure the connection to write is made once.
I am using Realm and I have an extension that I use to convert my Realm model into a Dictionary , but I do not know how to convert all my Realm models at once. I want to know how do I convert all the realm Objects at once and in one place, so that I can send that dictionary to a API.
Here are my Realm Object Models and the extension I use:
class OrderItemList: Object {
dynamic var dateCreated = NSDate()
let orderItems = List<OrderItem>()
}
class OrderItem: Object {
dynamic var name = " "
dynamic var amount = 0
dynamic var internalUnique = Int()
dynamic var isCompleted = false
}
Extension:
extension Object {
func toDictionary() -> NSDictionary {
let properties = self.objectSchema.properties.map { $0.name }
let dictionary = self.dictionaryWithValuesForKeys(properties)
let mutabledic = NSMutableDictionary()
mutabledic.setValuesForKeysWithDictionary(dictionary)
for prop in self.objectSchema.properties as [Property]! {
// find lists
if let nestedObject = self[prop.name] as? Object {
mutabledic.setValue(nestedObject.toDictionary(), forKey: prop.name)
} else if let nestedListObject = self[prop.name] as? ListBase {
var objects = [AnyObject]()
for index in 0..<nestedListObject._rlmArray.count {
let object = nestedListObject._rlmArray[index] as AnyObject
objects.append(object.toDictionary())
}
mutabledic.setObject(objects, forKey: prop.name)
}
}
return mutabledic
}
}
Unfortunately, there's no magic bullet for converting a batch of Realm objects to a dictionary. You'll need to query for the objects you want, and then loop through each one to produce a serialized version of it.
let realm = try! Realm()
var objectDictionaries = [NSDictionary]()
let allObjects = realm.objects(OrderItemList.self)
for object in allObjects {
let dictionary = object.toDictionary()
objectDictionaries.append(dictionary)
}
I hope that answered your question!
I have two classes. First looks like that:
class Person: Object {
dynamic var owner: String?
var dogs: List<Dogs>()
}
and second class which looks like that:
class Dogs: Object {
dynamic var name: String?
dynamic var age: String?
}
and now in ViewController in 'viewDidLoad' I create object Person with empty List and save it in Realm
func viewDidLoad(){
let person = Person()
person.name = "Tomas"
try! realm.write {
realm.add(Person.self)
}
}
it works great and I can create Person, problem begins when I try to read this data in SecondViewController in ViewDidLoad doing it:
var persons: Results<Person>?
func viewDidLoad(){
persons = try! realm.allObjects()
}
and try to add new Dog to List doing it in button action:
#IBAction func addDog(){
let newDog = Dogs()
newDog.name = "Rex"
newDog.age = "2"
persons[0].dogs.append(newDog)
// in this place my application crashed
}
Here my app is crashing with an information: Can only add, remove, or create objects in a Realm in a write transaction - call beginWriteTransaction on an RLMRealm instance first. How can I add new Dog to List and how can I update person[0]?
I use SWIFT 3.0
The persons property is of type Results<Person>, which is a collection containing Person objects that are managed by a Realm. In order to modify a property of a managed object, such as appending a new element to a list property, you need to be within a write transaction.
try! realm.write {
persons[0].dogs.append(newDog)
}
Write something like this:
if let person = persons?[0] {
person.dogs.append(newDog)
}
try! realm.write {
realm.add(person, update: true)
}
Please check how are you getting realm. Each time you call defaultRealm, you are getting new realm.
Side Note: Besides adding the code inside the write transaction which solves your issue, you could query Person by name as follow...
#IBAction func addDog(){
let newDog = Dogs()
newDog.name = "Rex"
newDog.age = "2"
let personName = realm.objects(Person.self).filter("name = 'Tomas'").first!
try! realm.write {
personName.dogs.append(newDog)
}
}
Add object for Realm Database
class Task : Object {
#objc dynamic var id : Int = 0
#objc dynamic var name = ""
#objc dynamic var phone = ""
#objc dynamic var address = ""
}
#IBAction func buttonSave(_ sender: Any) {
let realm = try! Realm()
let user = Task()
user.id = 0
user.name = (txtName.text! as NSString) as String
user.phone = (txtPhone.text! as NSString) as String
user.address = (txtAddress.text! as NSString) as String
try! realm.write {
realm.add(user)
print("user:",user.name)
}
}
I'm new in programming and I would like to know how I can store data in a List with RealmSwift.
Considering the following model:
import RealmSwift
class ScanResults: Object{
dynamic var id = 0
dynamic var resource = ""
dynamic var scanDate = ""
let ScanResultsDetail = List<ScanResultsDetails>()
}
class ScanResultsDetails: Object{
dynamic var scanner = ""
dynamic var result = ""
}
This is an example how I store new ScanResults:
let newResults = ScanResults()
newResults.id = newResults.IncrementaID()
newResults.resource = "Test"
newResults.scanDate = "19.01.2016"
do{
try uiRealm.write({ () -> Void in
uiRealm.add(newResults)
})
}
catch{
}
My Question is now, how can I store data in the list? I can't figure it out.. Can you give me an example?
I don't see that you append any object to ScanResultsDetail in your example
Here is quick example based on swift source code (docs):
class Dog: Object {
dynamic var name = ""
dynamic var age = 0
}
class Person: Object {
dynamic var name = ""
let dogs = List<Dog>()
}
let realm = try! Realm() // Create realm pointing to default file
// Link objects
let person = Person()
person.name = "Tim"
person.dogs.append(mydog)
try! realm.write {
realm.add(person)
}