class CMSimpleRealmModel: Object {
dynamic var myKey: String? = NSUUID().UUIDString
dynamic var name: String? = ""
override init() {
self.myKey = NSUUID().UUIDString
self.name = ""
super.init()
}
override class func primaryKey() -> String {
return "myKey"
}
}
let aDefaultRealm = Realm()
var anObject = CMSimpleRealmModel()
aDefaultRealm.write {
aDefaultRealm.add(anObject)
}
causes the following error to be generated,
/Users/marcvano/dev/cameo/Cameo2/Cameo/CMSoundtrack.swift: 14: 7: fatal error: use of unimplemented initializer 'init(realm:schema:)' for class 'Cameo.CMSimpleRealmModel'
but reading through the doc it says this is the public one and init(realm:schema:) is the private one.
Experiencing the same error here, trying to find a workaround (Realm 0.92.0)
Overriding init() isn't quite supported just yet. I'll rename the issue accordingly.
Meanwhile, you can create and use convenience initializers like this:
class CMSimpleRealmModel: Object {
dynamic var myKey: String = NSUUID().UUIDString
dynamic var name: String = ""
convenience init(myKey: String, name: String) {
self.init()
self.myKey = myKey
self.name = name
}
override class func primaryKey() -> String {
return "myKey"
}
}
let aDefaultRealm = Realm()
var anObject = CMSimpleRealmModel(myKey: "0", name: "John")
aDefaultRealm.write {
aDefaultRealm.add(anObject)
}
Keep in mind that you can set default property values inline with the property declaration rather than in init().
Anyone having issues with custom initializers and/or coming from issue https://github.com/realm/realm-cocoa/issues/1101, the @jpsim comment above - https://github.com/realm/realm-cocoa/issues/1849#issuecomment-99547742 - worked for me!
Just to be clear, that means we can only use var properties, and not let properties with RealmSwift until proper custom init support is implemented?
Any timeline for when that might be? #1101 seemed to suggest this was being actively worked on.
You should only be using dynamic var properties if you want them backed and stored by Realm (except List properties, which should be let). More information is available in the Models section of our Swift docs.
Custom initializers _are_ supported (see my earlier comment: https://github.com/realm/realm-cocoa/issues/1849#issuecomment-99547742), but this issue is tracking adding the ability to override init() itself.
@jpsim thanks for the clarification regarding vars.
Regarding initialization - I should have been more specific, I meant support for a custom _designated_ init rather than for a _convenience_ init.
Is this still being worked on?
This is important because in Swift convenience initializers can't be called by subclasses' initializers.
This makes subclassing a stored Realm object and calling its super.init(...) infeasible (e.g. Vehicle: Object, Bicycle: Vehicle).
I don't know how the Realm implementation works, but it seems that the problem can be solved on Realm's end by marking all initializers besides the empty init() as convenience initializers.
If the underlying 'problematic' initializers are written in Obj-C, this may be of help:
For consistency and simplicity, Objective-C factory methods get mapped as convenience initializers in Swift. This mapping allows them to be used with the same concise, clear syntax as initializers.
Thanks for the tips, @ataibarkai, we'll take those into consideration when looking for options to make overriding Object.init() possible.
Thanks for the quick reply @jpsim.
Any idea regarding the timeline for implementing this? Is it being actively worked on yet?
I've actually come up with a hack around this that you guys might also find useful in allowing designated initializes (including overriding init() ).
It compiles fine but I haven't been able to test it yet, since I need to have objects of type RLMRealm, RLMObjectSchema, and RLMSchema.
Any idea how to get this work with RealmSwift?
I've tried simply having import Realm / import Realm.Private but while this compiles fine, it crashes during runtime with dyld: Library not loaded: @rpath/Realm.framework/Realm.
I've also tried to directly add the compiled Realm framework onto the project the same way I added the RealmSwift framework (I'm using Carthage) but I got tons of errors due to ambiguity in which kind of a class to use (the Realm version or the RealmSwift version).
Any pointers would be much appreciated.
To be honest, this isn't our highest priority at the moment (just see the list of GH issues marked P1 and you'll understand). Also, there's a fairly simple workaround for your situation (inability to override convenience initializers): use a configuration method:
class MyModel: Object {
func configure(param1:param2:...) {
// configure self
}
}
You can override this method for subclasses.
Gotcha, completely understandable.
I'm actually doing exactly what you suggested now in my code, though I was hoping for a more elegant solution.
But this is far from a pressing issue, so as I said, completely understandable.
Hi, I encountered the same error with unsupported overriding init() method in Object subclass. Are you going to add ability to override init()?
Actually I am forced to use Realm (instead RealmSwift) in my Swift project.
This was actually fixed in the months since this issue was last active and we neglected to update it.
Overriding Object.init() is now supported:
public class MyModel: Object {
required public init() {
super.init()
// Perform further initialization
}
}
Note that Object.init() is a _required_ initializer, and thus must be implemented in order to provide convenience initializers (see #1928).
@jpsim this is an old thread, but still relevant to me now.
Given the following file:
import Foundation
import RealmSwift
@objc class TestObject: Object {
dynamic var testProperty: String
public required init() {
super.init()
}
convenience init(testProperty: String) {
self.testProperty = testProperty
self.init()
}
}
I get errors at line super.init() that testProperty is not properly initialized yet, which makes sense. Typically in this case I would just make init(testProperty:) a designated initializer, but because I'm required to implement an init() with no arguments if I want and custom initializer, I'm unsure how to properly initialize my stored properties with values from the caller of the init.
In this case something like a func configure(testProperty:) also doesn't work, as I get an error that TestObject has no initializers because no initializer is setting testProperty's value.
Does this mean I'm not allowed to have stored properties without default values in an Object subclass? I don't want to make every stored property optional, should I simply set dummy values like dynamic var testProperty: String = ""? This feels kinda gross and un-swifty
Does this mean I'm not allowed to have stored properties without default values in an Object subclass? I don't want to make every stored property optional, should I simply set dummy values like dynamic var testProperty: String = ""? This feels kinda gross and un-swifty
Yes, non-optional properties on RealmSwift.Object _must_ have a default property value due to limitations in Swift's runtime type reflection mechanism. We agree that this is gross and not switfty, but Swift lacks the capabilities for us to avoid this.
I believe we've filed bugs towards bugs.swift.org to this regard, and likely have GitHub issues on this repo tracking making improvements to this, but I can't find them at the moment. I encourage you to file a radar or Swift bug to request a richer reflection mechanism that could allow us to make this nicer.
Thanks for the clarification. This is helpful. Perhaps adding this more explicitly to the docs could clear up some confusion here.
@jpsim have you guys made a pull-request with a proposal on swift-evolution? That seems like the best way to get officially enrolled in apple's swift feature pipeline, although I don't know a ton about the internal process.
A simple search for reflection on swift-evolution indicates that this is not on their current to-do list.
Reflection improvements was explicitly listed under non-goals for Swift 3, which meant that it was counter-productive to bring it up through the Swift Evolution process at that time. Now that Swift 3 is officially out, Swift Evolution will start considering reflection-related suggestions, so moving forward if someone had the time and motivation to do so, a proposal could be submitted.
Nice. I'd be interested in spending some time looking at this. Any other internal Realm discussions I could start with?
There's this really scary and likely-unfit-for-production-use proof of concept implementation that @JadenGeller did a few weeks ago here: https://gist.github.com/JadenGeller/61178fac92ffe595a5a2243e3996400c
There's another discussion about this in #1615.
The code in ObjectUtil, RLMObjectSchema and RLMSchema will also likely be useful to read through and understand. git blame through the code I've highlighted will show you its evolution and different commits and PRs discussing the mechanisms at play.
Thanks
@jpsim Reflection is listed as a possible Swift 4 Stage 2 effort, so I imagine it could be worthwhile to participate this upcoming Spring.
Indeed, that's what I was trying to say in https://github.com/realm/realm-cocoa/issues/1849#issuecomment-247429878
How would we initialize a List property using default property values inline with the property declaration (rather than having to override init)?
In the example below, I want anytime I create a new CMSimpleRealmModel, that myValues is a list of 10 blank strings. How do I do that?
class CMSimpleRealmModel: Object {
dynamic var myKey: String = NSUUID().UUIDString
dynamic var name: String = ""
dynamic var myValues = List<String>()
}
Most helpful comment
Overriding
init()isn't quite supported just yet. I'll rename the issue accordingly.Meanwhile, you can create and use convenience initializers like this:
Keep in mind that you can set default property values inline with the property declaration rather than in
init().