Swift: Realm error at init "NULL is not supported as an RLMObject property". But I don't have a NULL - swift

It seems most people with this error are trying to create null strings. I just have three properties
dynamic var babyEvent: Int
dynamic var eventDate: NSDate
dynamic var timeSpent: Int
which are initialized in init() to
override init()
{
self.babyEvent = BabyWet
self.eventDate = NSDate()
self.timeSpent = 5
super.init()
}
but by the time super.init() is called I get
'(null)' is not supported as an RLMObject property.
There are two Ints and one NSDate, all of which are valid Realm property types. So why am I getting this error?

Realm doesn't support Swift enum's with no raw value. But adding a raw type to the BabyEvent enum and assigning the raw value to your realm objects works:
enum BabyEvent: Int {
case BabyWet, case BabyDry
}
class MyRealmObject: RLMObject {
dynamic var babyEvent = BabyEvent.BabyWet.rawValue
dynamic var eventDate = NSDate()
dynamic var timeSpent = 0
}

In Swift Enums have a specific type. So while you think you are passing an Int for BabyWet you are actually passing something of that specific type.
It seems that you have an Enum for the BabyEvent, so you should really have a look at the rawValue property:
self.babyEvent = BabyWet.rawValue

As I wrote, you can just set the starting values in the model definitions:
class TestClass: RLMObject {
dynamic var babyEvent: Int = 1
dynamic var eventDate: NSDate = NSDate()
dynamic var timeSpent: Int = 5
}
but this also works for me:
class TestClass: RLMObject {
dynamic var babyEvent: Int
dynamic var eventDate: NSDate
dynamic var timeSpent: Int
override init() {
babyEvent = 1
eventDate = NSDate()
timeSpent = 5
super.init()
}
}
In both cases I simply use
let realm = RLMRealm.defaultRealm()
var myTestObject = TestClass()
realm.beginWriteTransaction()
realm.addObject(myTestObject)
realm.commitWriteTransaction()
to create and add the object to the Realm.

Related

Why not use a struct-based singleton in Swift

Why not use a struct-based singleton?
I created decodable struct-based singleton.
struct Person: Decodable {
static var shared = Person()
private(set) var name: String?
var age: Int?
private init() {
}
mutating func initData(from data: Data) {
if let person = try? JSONDecoder().decode(Person.self, from: data) {
self = person
}
}
}
init from other class like this:
Person.shared.initData(from: data)
and use parameters:
let name = Person.shared.name
Person.shared.name = "MyName" //error
Person.shared.age = 20
Is this the wrong way?
You can't use a struct fora singleton because struct is a value type so when you assign it to a variable you get a copy. This can be easily shown
struct Singleton {
static var shared = Singleton()
var value: Int
private init() {
value = 0
}
}
Singleton.shared.value = 1
var otherSingleton = Singleton.shared
otherSingleton.value = 2
Now if we print the value of both
print(Singleton.shared.value, otherSingleton.value)
we get
1 2
So otherSingleton is clearly a separate instance so now we have 2 singletons :)
But if we simply change the type of Singleton to class that is a reference type and then run the same code the result of the print is
2 2
since it is the same instance we have changed the value property for.

Swift property wrappers. Assign by reference

I would like to share a string between classes, and keep modifications made on that string synchronised.
I thought of doing a property wrapper like:
#propertyWrapper class StringHolder {
var wrappedValue: String?
init(wrappedValue: String?) {
self.wrappedValue = wrappedValue
}
}
and then use it:
#StringHolder var sharedString: String = "testString"
let anotherClass = AnotherClass()
anotherClass.sharedString = sharedString
anotherClass.sharedString = "modified"
//sharedString is still "testString"
The problem is that when assigning the sharedString, only the wrapped value is re-set.
Is it possible to have the same wrapper assigned by reference to two properties?

Get associated object value from filter query using Realm swift

So Im pretty new to realm and i feel my question is very basic but i cant find the answer to it.
Basically I'm trying to query Realm for all playerName associated with a specific TeamID (ie. TeamID is not the primary key), however Im having trouble finding the solution. I keep getting a Value of type 'Results<playerInfoTable>' has no member 'playerName' error.
Below is my Realm class:
`class playerInfoTable: Object {
#objc dynamic var playerID: Int = 0
#objc dynamic var playerName: String = ""
#objc dynamic var jerseyNum: Int = 0
#objc dynamic var TeamID: String = ""
#objc dynamic var goalCount: Int = 0
#objc dynamic var shotCount: Int = 0
override class func primaryKey() -> String {
return "playerID"
}
}`
And the Code I'm using the query Realm:
let mainPlayerFilter = NSPredicate(format: "teamID == %#", "1")
let mainPlayerStrings = realm.objects(playerInfoTable.self).filter(mainPlayerFilter)
let mainPlayerTeamName = mainPlayerStrings.playerName
Solution!
let mainPlayerFilter = NSPredicate(format: "TeamID == %#", String(homeTeam!))
let mainPlayerStrings = realm.objects(playerInfoTable.self).filter(mainPlayerFilter)
let mainPlayerTeamName = mainPlayerStrings.value(forKeyPath: "playerName") as! [String]
I suppose you get the error when you declare the mainPlayerTeamName constant. Try the following:
let mainPlayerTeamName = mainPlayerStrings.first?.playerName
And I noticed that in your playerInfoTable class you declare "teamID" as "TeamID", while in your predicate you refer to it as "teamID". Decide which one you want because NSPredicate is case sensitive by default.

Swift 4 Realm Swift object

I'm trying to use realmSwift in my application in Swift 4 but i have an error.
public class Test : Object {
#objc dynamic var id: Int = 0
#objc dynamic var long: Double? = 0
convenience init(id: Int, long:Double?) {
self.init()
self.id = id
self.long = long
}
override public class func primaryKey() -> String {
return "id"
}
}
Error for line with long variable.
Property cannot be marked #objc because its type cannot be represented in Objective-C
Thx for help
As the docs clearly state, numeric types cannot simply be marked Optional, because Optional numeric types cannot be represented in Objective-C. You need to use RealmOptional to store Optional numeric types in Realm classes.
public class Test : Object {
#objc dynamic var id: Int = 0
let long = RealmOptional<Double>()
}
You have provided Int value to the double, so it's throw error. Use following code for double;
#objc dynamic var value: Double = 0.0
I hope this will fix your issue.
For more info: https://realm.io/docs/swift/latest#property-attributes

How to change Realm singleton attribute value

I have a Realm object:
class TransactionDB: Object {
dynamic var transactionID : Int = -1
dynamic var registrationPlate : String = ""
dynamic var locationID : Int = 0
dynamic var time : String = ""
dynamic var subscription : String = ""
dynamic var startTime : NSDate = NSDate()
dynamic var endTime : NSDate = NSDate()
dynamic var status : Int = -2
dynamic var requestType : Int = -1
var extensions : List<ExtensionDB> = List<ExtensionDB>()
dynamic var price : Double = 0
dynamic var currency : String = ""
private dynamic var test : Int = 10
override static func primaryKey() -> String? {
return "transactionID"
}
class var sharedInstance : TransactionDB {
struct Singleton {
static let instance = TransactionDB()
}
return Singleton.instance
}
static func saveOrUpdate {
// ......
}
and a singleton version for it. So I have one object over many controllers when screens change.
A few days back I was using some older Objective-C version of Realm but now I changed to the Swift-only version 1.0.2 and I'm trying to fix all the problems.
So now it came to part that when I try to call stuff like:
TransactionDB.sharedInstance.time = ""
I get an exception. However, after I do the following, it works:
let realm = try! Realm()
try! realm.write {
TransactionDB.sharedInstance.time = ""
}
So am I creating the singleton wrong or is this just the way it has to be done? Because, for me, it is a little annoying that I would always have to use a try block when I want to change the value of some attribute.
Take a look at the first line of the Realm docs for the write section.
It states:
All changes to an object (addition, modification and deletion) must be done within a write transaction.
So yea, it's just how you have to do it.