realm-swift
realm-swift copied to clipboard
Can't set object of type 'Skin' to property of type 'Skin'
How frequently does the bug occur?
Seen once
Description
I have some realm model which has another realm object as a property and i am getting the crash report from firebase , when i am trying to set the value of that property , with this error message "Can't set object of type 'Skin' to property of type 'Skin'"
Stacktrace & log output
No response
Can you reproduce the bug?
Not yet
Reproduction Steps
No response
Version
10.7.2
What SDK flavour are you using?
Local Database only
Are you using encryption?
No, not using encryption
Platform OS and version(s)
iOS 14.7.1
Build environment
Xcode version: ... Dependency manager and version: ...
Can you provide us a code sample and stack trace please?
HI @jsflax, thank you for your quick response. Here is the log from firebase
Fatal Exception: RLMException
0 CoreFoundation 0x1a480a708 __exceptionPreprocess
1 libobjc.A.dylib 0x1b93147a8 objc_exception_throw
2 Realm 0x103e3d00c invocation function for block in objc_object* (anonymous namespace)::makeSetter<RLMObjectBase* __strong, RLMObjectBase* __strong>(RLMProperty*) + 145 (RLMAccessor.mm:145)
3 madrid 0x1009aa8f4 VideoSettings.setSkin(:) + 82 (VideoSettings.swift:82)
4 madrid 0x100b5b5c0 specialized VideoSettingsSetScheme.pull(:) (VideoSettingsScheme.swift)
5 madrid 0x100a4a014 ProjectSettings.setDisplaySettings(:) + 127 (ProjectSettings.swift:127)
6 madrid 0x100b59d90 Project.setSettings(:) (Project.swift)
7 madrid 0x1008b0d98 specialized ProjectSetScheme.pull(:) (ProjectScheme.swift)
8 madrid 0x1008af3e8 (Missing)
9 madrid 0x1009dcea8 closure #1 in Realm.updateProperty(completion:) + 25 (RealmExtension.swift:25)
10 madrid 0x100adee84 thunk for @callee_guaranteed () -> (@error @owned Error) (
here is my class where i got the crash, it is in the setSkin function
class VideoSettings: BaseRealmObject, VideoSettingsScheme {
@objc dynamic private var showSkin: Bool = true
@objc dynamic private var showTagInformation: Bool = true
@objc dynamic private var showTagComments: Bool = true
@objc dynamic private var showAnimation: Bool = true
@objc dynamic private var skinSize: Int = 3
@objc dynamic private var skinPosition: Int = 2
@objc dynamic private var skin: Skin?
@objc dynamic private var tagCommentTiming: Int = 2
private let animations = List<Animation>()
func setShowSkin(_ showSkin: Bool) {
self.showSkin = showSkin
}
func getShowSkin() -> Bool {
return showSkin
}
func setShowTagInformation(_ showTagInformation: Bool) {
self.showTagInformation = showTagInformation
}
func getShowTagInformation() -> Bool {
return showTagInformation
}
func setShowTagComments(_ showTagComments: Bool) {
self.showTagComments = showTagComments
}
func getShowTagComments() -> Bool {
return showTagComments
}
func setShowAnimation(_ showAnimation: Bool) {
self.showAnimation = showAnimation
}
func getShowAnimation() -> Bool {
return showAnimation
}
func setSkinSize(_ skinSize: Int) {
self.skinSize = skinSize
}
func getSkinSize() -> Int {
return skinSize
}
func setSkinPosition(_ skinPosition: Int) {
self.skinPosition = skinPosition
}
func getSkinPosition() -> Int {
return skinPosition
}
func setSkin(_ skin: SkinUi) {
let newSkin = Skin(skin.getId()).pull(skin)
let realm = LocalDatabaseManager.instance.getSafeRealm()
if realm.isInWriteTransaction {
realm.add(newSkin, update: .modified)
} else {
realm.updateProperty {
realm.add(newSkin, update: .modified)
}
}
self.skin = newSkin
}
func getSkin() -> SkinUi {
if let skin = skin {
return SkinUi(skin.getId()).pull(skin)
} else {
return SkinUi()
}
}
func setAnimations(_ animations: [AnimationUi]) {
self.animations.removeAll()
let realm = LocalDatabaseManager.instance.getSafeRealm()
let newAnimations = animations.map({ Animation($0.getId()).pull($0) })
if realm.isInWriteTransaction {
realm.add(newAnimations, update: .modified)
} else {
realm.updateProperty {
realm.add(newAnimations, update: .modified)
}
}
self.animations.append(objectsIn: newAnimations)
}
func getAnimations() -> [AnimationUi] {
return animations.map({ AnimationUi($0.getId()).pull($0) })
}
func setTagCommentTiming(_ tagCommentTiming: Int) {
self.tagCommentTiming = tagCommentTiming
}
func getTagCommentTiming() -> Int {
return tagCommentTiming
}
}
@HovhannesPoghosyan it would be worth changing the logic inside of setSkin to not check if the realm is already in a write transaction. What does realm.updateProperty look like? unless you are facing issues with multithreading or you are calling beginWrite manually you should never need to implement this logic.
@leemaguire here is my update property, and don't get what logic should i change
import RealmSwift
extension Realm { func updateProperty(completion: () -> Void) { try! write { completion() } } }
Could you try:
func setSkin(_ skin: SkinUi) {
let newSkin = Skin(skin.getId()).pull(skin)
// If VideoSettings is already managed you will have access to the realm.
try! realm.write {
self.skin = newSkin
}
}
sorry @leemaguire i don't think that this is the thread issue and realm.write will fix everything
Hi @HovhannesPoghosyan did you manage to solve your issue?
no @leemaguire unfortunately i have not fixed this issue yet
I also encountered this problem. I found that this problem is due to the use of objects managed by Realm to set thet property. If the setting is a newly created object that is not managed by Realm, setting the property is successful.
@leemaguire @HovhannesPoghosyan
my log: 2021-12-02 13:53:08.304851+0800 HikIMSdk[4555:6334909] *** Terminating app due to uncaught exception 'RLMException', reason: 'Can't set object of type 'HikMessageRecord' to property of type 'HikMessageRecord'' *** First throw call stack: (0x1807e90fc 0x199015d64 0x102fd7a80 0x102fb3638 0x102fce8a4 0x100864854 0x1009da514 0x1032148f8 0x103214790 0x103214700 0x1009da3f0 0x100b0d2e4 0x100b0e720 0x18077af88 0x180816c3c 0x1807e9ff4 0x180790df4 0x181f8df68 0x10080d444 0x1008f35cc 0x100905854 0x1008d3740 0x100860a64 0x10205c6d4 0x10205e3b4 0x102060f2c 0x102072500 0x102072f0c 0x1f1a0e0b8 0x1f1a0de94) libc++abi: terminating with uncaught exception of type NSException dyld4 config: DYLD_LIBRARY_PATH=/usr/lib/system/introspection DYLD_INSERT_LIBRARIES=/Developer/usr/lib/libBacktraceRecording.dylib:/Developer/usr/lib/libMainThreadChecker.dylib:/Developer/Library/PrivateFrameworks/DTDDISupport.framework/libViewDebuggerSupport.dylib *** Terminating app due to uncaught exception 'RLMException', reason: 'Can't set object of type 'HikMessageRecord' to property of type 'HikMessageRecord'' terminating with uncaught exception of type NSException
The point of collapse is here:

The type is correct, but the check fails,why ?
I have same problem. I simplified code for example. Model:
` class Order: Object, ObjectKeyIdentifiable { @objc dynamic var orderID : String = NSUUID().uuidString @objc dynamic var client : Client? = nil @objc dynamic var name : String = "No Name"
override static func primaryKey() -> String? {
return "orderID"
}
}`
' class Client: Object, ObjectKeyIdentifiable {
@objc dynamic var account : String = ""
@objc dynamic var name : String = "No Name"
}'
When trying this,
try! realm.write{ currentOrder!.client = client }
This is the error:
*** Terminating app due to uncaught exception 'RLMException', reason: 'Can't set object of type 'Client' to property of type 'Client''
Just ran into the same issue. For me, this had to do with frozen realms. I was trying to use a frozen realm object as a backlink to another object. In order to resolve the issue, I had to thaw() the object first so that it was a live instance.
Any updates on this? Running into the same issue
Me too, any updates?
The same issue
The problem is solved Do not set objects already managed by Realm
I'm encountering the same issue but when using @ObservedRealmObject with SwiftUI's Picker.
Here is my code to help reproduce this issue:
import SwiftUI
import RealmSwift
final class Item: Object, ObjectKeyIdentifiable {
@Persisted(primaryKey: true) var _id: ObjectId
@Persisted var title: String
@Persisted var ownerId: String
@Persisted var category: ItemCategory?
}
final class ItemCategory: Object, ObjectKeyIdentifiable {
@Persisted(primaryKey: true) var _id: ObjectId
@Persisted var name: String
@Persisted var ownerId: String
}
struct ItemDetailsView: View {
@ObservedRealmObject var item: Item
@ObservedResults(ItemCategory.self) var categories
var body: some View {
Picker("Category", selection: $item.category) {
Text("None").tag(nil as ItemCategory?)
ForEach(categories, id: \.self) { category in
Text(category.name)
.tag(Optional(category))
}
}
}
}
I've tried using _id but that means the Picker doesn't set new values, it only displays the categories correctly, and when I use Category object to set as Item.category, it throws the following exception:
*** Terminating app due to uncaught exception 'RLMException', reason: 'Can't set object of type 'ItemCategory' to property of type 'ItemCategory''
Am I using the SwiftUI Picker with Realm wrong?
Hi @matthewmorek, Thanks for the reproduction case, the usage of the picker looks correct. I'm investigating what the issue is on our end.
@matthewmorek can you try:
var body: some View {
Picker("Category", selection: $item.category) {
Text("None").tag(nil as ItemCategory?)
ForEach(categories, id: \.self) { category in
Text(category.name)
.tag(category.thaw())
}
}
}
as a workaround for now? What's happening is that a frozen Realm object (ItemCategory) is trying to be set to a non-frozen version of Item, and we are not handling that on our end. Doing .tag(category.thaw()) is a temporary workaround which works for me.
@leemaguire Hey, thanks for this workaround. It works well and I'm happy to use it until this is sorted out at your end! 👍🏻
@leemaguire a big thanks from me too, ran into exactly the same issue
@leemaguire a big thanks from me too - I have been struggling with this issue for a whole day, before I came across your workaround.
I have just met this issue and got resolved myself. My use case is that I want to assign an existing object A to a related property of another existing object B.
try! realm.write {
existingObjectB.relatedProperty = relatedObjectA
}
Both of them are coming from the database directly, which means that none of them is new.
The solution: thaw both of them before any assignment, and then assign the thawed object A to the thawed object B.
Hope it helps.
@matthewmorek can you try:
var body: some View { Picker("Category", selection: $item.category) { Text("None").tag(nil as ItemCategory?) ForEach(categories, id: \.self) { category in Text(category.name) .tag(category.thaw()) } } }as a workaround for now? What's happening is that a frozen Realm object (
ItemCategory) is trying to be set to a non-frozen version ofItem, and we are not handling that on our end. Doing.tag(category.thaw())is a temporary workaround which works for me.
@leemaguire Based on the above message, it sounds like this is a bug in the Realm client code (since you're talking about workarounds). Does MongoDB plan on fixing this soon? Like many others, I got bit by this recently and lost many hours trying to track down a solution. Thanks.
I too experienced this and thanks the workout. Does the job
I had the same issue !
Would it not help if the error was more descriptive, like "Can't set frozen object of type"X" to property of type "X".
Leemaguire, thanks for posting a solution!
Just ran into the same issue. For me, this had to do with frozen realms. I trying to use a frozen realm object as a backlink to another. In order to resolve the issue, I had to thaw() the object first so that it was a live instance.
@sipersso This comment is a hidden gem 💎! My issue was resolved once I thawed both objects in question. Thank you so much!
@matthewmorek can you try:
var body: some View { Picker("Category", selection: $item.category) { Text("None").tag(nil as ItemCategory?) ForEach(categories, id: \.self) { category in Text(category.name) .tag(category.thaw()) } } }as a workaround for now? What's happening is that a frozen Realm object (
ItemCategory) is trying to be set to a non-frozen version ofItem, and we are not handling that on our end. Doing.tag(category.thaw())is a temporary workaround which works for me.@leemaguire Based on the above message, it sounds like this is a bug in the Realm client code (since you're talking about workarounds). Does MongoDB plan on fixing this soon? Like many others, I got bit by this recently and lost many hours trying to track down a solution. Thanks.
@leemaguire I am using the workaround in a macOS app, but with many pickers the multiple thaw() turns into a serious performance issue. Any plans to fix this on the Realm side soon?
This is very, very annoying, and the error message couldn't be more confusing as to what the issue actually is.