Closed bipinvaylu closed 9 years ago
I don't think that the specific model and the crash are directly related. From the stack trace, I'm pretty sure It's caused by initializing your first model instance, which triggers the lazy-loading of the schema.
It seems like you defined a property as Swift array e.g. linkedObjects = [Foo]()
, which doesn't work for several reasons. Instead you've to define your to-many relationships with the provided List
-type e.g. linkedObjects = List<Foo>()
.
Is my assumption correct and does that help?
Thanks @mrackwitz i am having 2 main models ServerTrack and ServerTrackMetadata. ServerTrack is having array of ServerTrackMetadata objects. Currently i am trying to create single object of ServerTrackMetadata but it's still giving same error. I checked stuff with sample app that's working fine. Realm Sample app: https://github.com/bipinvaylu/RealmDemo.
@mrackwitz i copied models and it's stuff from RealmDemo project to main project, it's also creating issue in main project. Looks like something in settings. Please let me know if you need any other details. Does it something related to build settings? I already did Install Objective-C Compatibility Header = No
.
Model: https://github.com/bipinvaylu/RealmDemo/blob/master/RealmDemo/Model.swift
FYI: i am using Swift and Objective-C for my project. Imported Realm.h in main-Bridging-Header.h
Here is my actual model structure:
/Users/Krunal/Library/Developer/Xcode/DerivedData/ottodj-asziciqqpxunbeazllcntqycmszd/Build/Products/Debug/ottodj.app/Contents
public class ServerTrack: RLMObject {
dynamic var id = 0
dynamic var traktorAudioId = ""
dynamic var bpm = 0.0
dynamic var metadata = RLMArray(objectClassName: ServerTrackMetadata.className())
dynamic var createdAt = 0
dynamic var updatedAt = 0
public convenience init(traktorAudioId: String, bpm: Double, metadata: [ServerTrackMetadata]) {
self.init()
self.traktorAudioId = traktorAudioId
self.bpm = bpm
self.metadata.addObjects(metadata)
}
public convenience init(track: JSON) {
self.init()
if let id = track["id"].int,
let traktorAudioId = track["traktorAudioId"].string,
let bpm = track["bpm"].double,
let createdAt = track["createdAt"].int,
let updatedAt = track["updatedAt"].int,
let metadataJSONArray = track["metadata"].array {
self.id = id
self.traktorAudioId = traktorAudioId;
self.bpm = bpm
self.createdAt = createdAt
self.updatedAt = updatedAt
for metadataJSON in metadataJSONArray {
let metadata: ServerTrackMetadata = ServerTrackMetadata(metadata: metadataJSON) as RLMObject
self.metadata.addObject(metadata)
}
}
}
}
public class ServerTrackMetadata: RLMObject {
dynamic var id = 0
dynamic var cueType = ""
dynamic var cueTime = 0.0
dynamic var createdBy = 0
dynamic var hotcue = -1
dynamic var apiVersion = 0
dynamic var createdAt = 0
dynamic var updatedAt = 0
public convenience init(cueType: String, cueTime: Double, createdBy: Int, apiVersion: Int, hotcue:Int) {
self.init()
self.cueType = cueType
self.cueTime = cueTime
self.createdBy = createdBy
self.apiVersion = apiVersion
self.hotcue = hotcue
}
public convenience init(metadata: JSON) {
self.init()
if let id = metadata["id"].int,
let cueType = metadata["cueType"].string,
let cueTime = metadata["cueTime"].double,
let createdBy = metadata["createdBy"].int,
let apiVersion = metadata["apiVersion"].int,
let createdAt = metadata["createdAt"].int,
let updatedAt = metadata["updatedAt"].int {
self.id = id
self.cueType = cueType
self.cueTime = cueTime
self.createdBy = createdBy
self.apiVersion = apiVersion
self.createdAt = createdAt
self.updatedAt = updatedAt
}
}
}
Can you please help me figure out this issue.
I am getting this error because of this code: https://github.com/bipinvaylu/RealmDemo/blob/master/RealmDemo/ServerTrack.swift #178, Can anyone please help me figure out this issue.
@mrackwitz @jpsim @realm-ci I figured this issue, it's because of i am having function named getMetadata()
in ServerTrackMetadata
. One thing i want to tell you guys is that error message is too much weird, No one can predict this can be issue. I spent around 3-4 days to figure out this weird stuff. :disappointed:
Sorry @bipinvaylu for causing you additional inconvenience in the last day, I totally own this. I'm currently abroad and had thus restricted internet access due to travel the last day. I missed to handover your issue to one of my team mates.
The sample project you provided was actually a pretty great way to reproduce this issue, but before that it was really cryptic and I don't think anyone of us has came across such an edge case yet and would have been able to recognize just from the exception message or the limited model you shared first with us what is going on here.
You're right that exception thrown here is not helpful at all, but that's just because that wasn't really handled yet at all.
Let me explain what is happening here: Realm's RLMObject
uses the Objective-C runtime to define dynamic accessors for your model properties to provide own getter and setter implementation. As Swift doesn't allow it to declare a type which is conforming to a protocol as Objective-C does it with RLMArray<Foo>
, we've to rely there on a property objectClassName
, which you correctly initialized. On runtime when you're initializing the first RLMRealm
instance, the schema is loaded by inspecting your classes via the reflection APIs. Because objectClassName
is a field of the RLMArray
property, classes with to-many relations which are defined from Swift have to be initialized at runtime to be able to inspect them. Realm Objective-C is accessing the value for the property via valueForKey:
. KVC is accessing values by first looking for an accessor method which matches the pattern -get<Key>
. This is the one you have overwritten here. By returning a standalone array instead of the RLMArray
, you are accidentally breaching the class contract for RLMObject
. The schema inspection code is trying to figure out the element type by calling objectClassName
on the returned value which is in that case the toll-free bridged _SwiftDeferredNSArray
. This doesn't know anything about Realm, so it comes to the failure.
Great thanks @mrackwitz for explanation. I got it now.
Exception logs:
Model code is like:
Just initialising model