-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support custom RLMObject initializers in Swift #1101
Comments
We currently require default initializers for Swift classes due to limitations with Swift introspection. |
@maciejtrybilo If all of the properties have default values, you can define an |
@mrh-is I tried defining the default constructor as you mention, I'm getting
3 months passed since you commented it, so maybe it's not working anymore since new Xcode version? Is there a workaround ? |
@Pintouch Yep, it's a change sometime between 0.87.4 and 0.90.0. Still investigating... Edit: It's between 0.89.2 and 0.89.0. Still investigating even more. |
OK, I'm not totally certain, because I (sadly!) can't spend the whole work day on debugging this so I didn't test with this commit, but I think it's commit 94c2dee. My suspicion (again, untested, sorry) is that there's some issue with But definitely a breaking change for the Swift side of things. (Or is there a better way to set up Swift classes with custom initializers?) |
This change happened in #1284 and lays the groundwork for a super awesome new Swift API, but makes using Realm in Swift a bit more cumbersome in the meantime 😢. Until our super awesome new Swift API is released, you'll unfortunately have to implement the following initializers if you want to use custom initializers: init() {
super.init()
}
init(object:) {
super.init(object:object)
}
init(object:schema:) {
super.init(object: object, schema: schema)
}
init(objectSchema:) {
super.init(objectSchema: objectSchema)
} |
I understand this is suuuuper awkward, but as I said, this lays an important foundation. |
Ah, that's ok! As long as there are clear directions. 👍 Thanks @jpsim! (YEAH SWIFT API) |
Thanks! Overriding those constructors works! |
|
Just in case anyone else comes here that is beginning Realm for the first time and doesn't know the argument types, here's a drop in solution for RLMObjects with custom initializers. Just add this to your class // MARK: RLMSupport
/*
Initializers required for RLM Support -- https://github.com/realm/realm-cocoa/issues/1101
*/
override init(object: AnyObject?) {
super.init(object:object)
};
override init(object value: AnyObject!, schema: RLMSchema!) {
super.init(object: value, schema: schema)
}
override init(objectSchema: RLMObjectSchema) {
super.init(objectSchema: objectSchema)
} |
Will we know when the new Swift API hits? I assume it hasn't yet |
It's now merged to master if you want to play around with it. We'll make an official announcement once it's included in a release. |
Nice! when is the anticipated release? Roughly within 2 weeks? |
It would be awesome if the podspec could be updated to include the Swift release. Makes it a lot easier to test it out :) One of the things I really don't like is specifying default values for my properties because some of them are required and now this isn't enforced at compile-time. Also, adding the initializers mentioned here will not work when you work with non-optional properties without a default value. |
@depl0y we'll be writing a new podspec for RealmSwift. Subscribe to #1705 to know when that's done.
Default values aren't strictly necessary, although calling |
@jpsim yup, but you can't create a custom init, if there are required properties. For example:
This throws an error without a initialiser called
Of course you get a compile error here, because you are calling
Finally you end up with a bunch of initialisers ( I created an example:
Now, what should be the appropriate way to init a DemoObject2, init a DemoObject1 and commit them to the database? I tried:
But this results in 2 DemoObject2 objects being stored, one with a I tried splitting it up in multiple transactions, but this ends in the same problem. (This might even be a separate thread, sorry about that). Convenience initialisers do work for me, without problems, but this has the need that all properties are either optional or filled with a default value. |
@yoshyosh are you sure |
They're needed for the default property values to work when the other initializers are called from obj-c. It's (probably) a swift bug. |
We have run in to similar problems, but it seems to be gone in 0.91.3 and Swift 1.2. In fact the build failed when we had the override init() methods. |
We'll be releasing a Swift-specific optimized API in the very near future, which will make using custom initializers in Swift much friendlier. |
If this is required, why is it not mentioned in the swift docs located here: https://realm.io/docs/swift/latest/#models It seems to me that the models section needs a init subsection with a copy of the latest / working examples listed here . . . . |
@acoleman-apc this issue was last active over 4 months ago and is no longer relevant. To override an public class MyModel: Object {
required public init() {
// custom initialization logic
super.init()
}
} |
@jpsim Thanks but I have already added similar code to my project. The point was that this isn't mentioned in the current documentation but is instead in an issue that has been open since November of 2014. At this point, doesn't it deserve a mention in the official documentation? |
This issue is actually not open, but rather has been closed for over 4 months. However, as with anything you may be struggling with in Realm, we're open to updating our docs in order to clarify. But we generally avoid documenting standard language behavior like overriding parent class methods or adding custom methods, as seems to be the case here. |
@jpsim I'm kind of a newbie with Swift (hey, aren't we all?). Documentation in the main website stating that you have to implement the following would be very helpful in getting started with Realm (aka "the happy path" 😀). To create a custom constructor:
|
+1 to @frankradocaj |
+1 on including this in the docs. Especially an example with relations. |
+1 for adding this into the "happy path" reference part. -3 hours. |
+1 @frankradocaj for the example, that should be on the main documentation 😫 |
@ed-mejia we have a section in our docs on this: https://realm.io/docs/swift/latest/#adding-custom-initializers-to-object-subclasses |
Hey @jpsim thanks for your comment. In my case it did't work just with that, maybe because I need other init since Im using a parsing Json library, look at my actual model:
In my case the compiler requires me to implement _required public init()_ _public init(realm: RLMRealm, schema: RLMObjectSchema)_ is not required by the compiler but the App crash when I try to do this after a query:
And the crash indicates that I haven't implemented _public init(realm: RLMRealm, schema: RLMObjectSchema)_ |
@ed-mejia It is more simple to use Like the following (Change public final class RoleModel: Object, Decodable {
dynamic var roleId = 0
dynamic var title = ""
dynamic var updatedAt: NSDate? = NSDate()
override public static func primaryKey() -> String? {
return "roleId"
}
public convenience init?(json: JSON) {
self.init()
// check for required values in order to return a valid object
guard let roleId: Int = "role_id" <~~ json, let title: String = "title" <~~ json else {
return nil
}
self.roleId = roleId
self.title = title
self.updatedAt = Decoder.decodeDate("updated_at")(json)
}
} |
@kishikawakatsumi You are totally right 👍 thanks for that clarification 😄 |
Hey guys have the same issue but not able to resolve it by following the above steps. Can you help me with it?? |
@rameez-leftshift Please explain your case, attach examples and maybe we could help you .. |
Here is my class which is causing the crash public class StoryBoard: Object, Deserializable {
public dynamic var status: Status?
required public init() {
status = Status()
super.init()
}
required public init(data: [String: AnyObject]) {
let new_id: Int = data["id"]! as! Int
id = "\(new_id)"
super.init()
}
public class func fromJSON(data: [String : AnyObject]) -> StoryBoard? {
return StoryBoard(data: data)
}
} let me know if you need anything else |
Without knowing what's your crash about. could you please try this first, replace your init this way:
|
This is the error which i get : Your mentioned solution doesn't work. Thank you for the help though. Also i'm using swift 2.1.1 and realm version 0.97.4. |
Weird, that's the same error I got previously and it's working fine with the provided solution, try to put this in your class:
And let's see if you can avoid the crash... this should not be the final solution though. |
i already have the at the start of the code snippet, its immediately after my declarations. |
Have created a new question for my problem (#3185). |
I'm noticing the docs on custom initializers aren't working for me. import Foundation
import RealmSwift
class Session: Object {
dynamic var uuid: String = NSUUID().UUIDString
dynamic var startTime: NSTimeInterval
dynamic var endTime: NSTimeInterval
convenience init(startDate:NSDate) {
self.init()
self.startTime = startDate.timeIntervalSince1970
}
func spanString() -> String {
var returnString = ""
return returnString
}
override class func primaryKey() -> String {
return "uuid"
}
} The compile error is : Missing argument for parameter 'startDate' |
Try setting initial values for both startTime and endTime. On Mar 12, 2016, 8:40 PM -0800, Jimmy Hough Jr.notifications@github.com, wrote:
|
So from reading this and the linked issue, I infer that Realm simply cannot support optionals and convenience initializers. Is that the case? |
That's not the case, see Realm's documentation on custom initializers: https://realm.io/docs/swift/latest#adding-custom-initializers-to-object-subclasses |
I realize this is an old thread, but it would be REALLY handy if stuff like this were documented right up front for Realm. Important details like, "You have to use the default Edit: It's also complicated because there are SO MANY different docs for Realm. There's the legacy stuff, the new MongoDB stuff, the individual SDK docs, etc. Googling for help with Realm leads to outdated sources and incorrect information. |
It's mid-2023, and Realm 10.33 still has the same issue. |
The last line results in
fatal error: use of unimplemented initializer 'init()' for class 'moduleName.Foo'
. Somehow Realm seems to want to call the default initializer, but ideally I wouldn't want to implement it because I don't necessarily have reasonable default values and would rather avoid optionals.The text was updated successfully, but these errors were encountered: