i'm new in using realm, i'm trying to save my api response in realm database. For that i read out there documents and started my work, I have created class of Objects in which a have my variables in which i want to save data now when i add data in realm app crashes with error, Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value. This is my class of Objects,
class SingleChatRealm: Object {
var actualNameFor_1_2_1_chat = ""
var isGroup : Bool = true
var isNewGroup : Bool = false
var lastMessage = ""
var lastMsgRead : Bool = false
var lastMsgTime = ""
var lastMsgTimeActual = ""
var name = ""
var profilePic = ""
var roomSID = ""
var unReadMsgsCount = 0
var twChannelObj : TCHChannel?
var members = [TCHMember]()
var messages = [TCHMessage]()
// #objc dynamic var group_info : [String:JSON]?
}
and this is how i'm storing data in realm,
let realm = try! Realm()
try! realm.write {
let newListing = SingleChatRealm()
for items in dateWiseSortedSingleRooms
{
newListing.actualNameFor_1_2_1_chat = items.actualNameFor_1_2_1_chat
newListing.isGroup = items.isGroup
newListing.isNewGroup = items.isNewGroup
newListing.lastMessage = items.lastMessage
newListing.lastMsgRead = items.lastMsgRead
newListing.lastMsgTime = items.lastMsgTime
newListing.lastMsgTimeActual = items.lastMsgTimeActual
newListing.members = items.members
newListing.messages = items.messages
newListing.name = items.name
newListing.profilePic = items.profilePic!
newListing.roomSID = items.roomSID
newListing.twChannelObj = items.twChannelObj
newListing.unReadMsgsCount = items.unReadMsgsCount
print(newListing)
self.realm.add(newListing)
}
}
My app crashes on this line self.realm.add(newListing) with above given error, why is it so? what's i'm missing in this?
There may be several reasons for that,
Make all the variables #objc dynamic var.
Make sure your realm object is global within the class, otherwise remove self from self.realm.add(newListing).
Make sure all the values you are assigning to the variables of newListing are not nil(Those variables which you have already initiated with some default values).
What are the actual data type of TCHChannel, TCHMember and TCHMessage? These type may not be supported by Realm.
Make sure you did not modify the SingleChatRealm class structure after adding an entry to realm. In that case you have to delete the old .realm file and have to create a new one.
You just created a new instance of Realm, but self.realm is still nil, you should add line:
self.realm = realm
to your code:
let realm = try! Realm()
self.realm = realm
try! realm.write {
let newListing = SingleChatRealm()
for items in dateWiseSortedSingleRooms
{
newListing.actualNameFor_1_2_1_chat = items.actualNameFor_1_2_1_chat
newListing.isGroup = items.isGroup
newListing.isNewGroup = items.isNewGroup
newListing.lastMessage = items.lastMessage
newListing.lastMsgRead = items.lastMsgRead
newListing.lastMsgTime = items.lastMsgTime
newListing.lastMsgTimeActual = items.lastMsgTimeActual
newListing.members = items.members
newListing.messages = items.messages
newListing.name = items.name
newListing.profilePic = items.profilePic!
newListing.roomSID = items.roomSID
newListing.twChannelObj = items.twChannelObj
newListing.unReadMsgsCount = items.unReadMsgsCount
print(newListing)
self.realm.add(newListing)
}
}
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'm working on a Swift 3 Realm app and I have this Realm model class:
class User: Object {
dynamic var userName = ""
dynamic var userURL = ""
dynamic var userThumbnailURL = ""
dynamic var isRegistered = false
var userID = RealmOptional<Int>()
override class func primaryKey() -> String? {
return "userID"
}
}
Then I'm adding values as follows. I'm getting them from my server and saving them in the local database:
Query 1
let user = User()
user.userName = fields["userName"] as! String
user.userURL = fields["userURL"] as! String
user.userThumbnailURL = fields["userThumbnailURL"] as! String
user.userID.value = fields["userID"] as? Int
try! uiRealm.write {
uiRealm.add(user, update: true)
}
Then when the user finishes the registration I'm updating the specific user in the local Realm database as being a registered user (isRegistered = true). This value is only saved in the local Realm database:
uiRealm.beginWrite()
let updatingUser = uiRealm.objects(User).filter("userID = %d", self.userId)
let user = updatingUser.first
book?.isRegistered = true
try! uiRealm.commitWrite()
But my problem is that when the new server response is received and I re-run Query 1 the isRegistered property becomes false. How can I avoid this?
The short answer is that partial updates of an object cannot be performed by passing an instance of an Object subclass to Realm.add(_:update:). The reason for this is that there's no way to represent don't update this property for a property on your Object subclass. You'll instead want to pass a dictionary to Realm.create(_:value:update:), where the absence of a given key represents don't update this property.
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
}
}
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)
}