-
-
Save Gujci/8307ab63bec7143486cab8dfa258acfd to your computer and use it in GitHub Desktop.
import RealmSwift | |
typealias Model = Object & Identifiable | |
struct ListKey<T: Model>: Identifiable { | |
let id: T.ID | |
} | |
extension Results where Element: Model { | |
subscript(key: ListKey<Element>) -> Element? { | |
Element.primaryKey().flatMap { self.filter("\($0) = %@", key.id).first } | |
} | |
var keyedEnumeration: [ListKey<Element>] { | |
guard let key = Element.primaryKey() else { return [] } | |
let keys = value(forKey: key) as! [Element.ID] | |
return keys.enumerated().map { ListKey(id: $0.1) } | |
} | |
} |
@tigerraj32 the given Stackoverflow article should explain. When you use a Realm
Results
collection, the difference in SwiftUIs value based concept interferes with the reference based database magic that Realm does, which leads to crashes.
So, let's say we have a someCollection
, which is a Realm results collection. Listing them safely should be like:
ForEach(someCollection.keyedEnumeration) { key in
let value = self.someCollection[key]
// ... render item with the value
}
@Gujci when I tried to get value
let value = self.someCollection[key]
I got the following error which prevents me to do that.
Type '()' cannot conform to 'View'; only struct/enum/class types can conform to protocols
First of all there was an extra )
in the example. Second, have you tried returning any View
in the place of the // ... render item with the value
comment?
Hi, I am getting the following errors. Note that StoreR is the Realm object.
Cannot convert value of type "[ListKey\<StoreR\>]" to expected argument type "Range\<Int\>"
Property 'keyedEnumeration' requires that 'StoreR' conform to 'Identifiable'
Closure containing a declaration cannot be used with function builder 'ViewBuilder'
To fix this be sure to return View()
in the ForEach
closure.
The error states that StoreR
is not Identifiable
.
Ah - forgot to add Identifiable
protocol to the StoreR
class. It already had a var id: UUID()
.
@Gujci can you create an extension for RealmSwift.List - my attempt fails with en error on "value(forKey: key)" - ambiguous use but I don't really understand why.
extension RealmSwift.List where Element: Model {
subscript(key: ListKey<Element>) -> Element? {
Element.primaryKey().flatMap { self.filter("\($0) = %@", key.id).first }
}
var keyedEnumeration: [ListKey<Element>] {
guard let key = Element.primaryKey() else { return [] }
let keys = value(forKey: key) as! [Element.ID]
return keys.enumerated().map { ListKey(id: $0.1) }
}
}
@duncangroenewald that is because RealmSwift.List
s value(forKey: key)
is different from the Results
s. It returns [AnyObject]
instead of Any
.
let keys: [AnyObject] = value(forKey: key)
compiles but it requires a cast to occur later in return keys.enumerated().map { ListKey(id: $0.1) }
like
return keys.enumerated().map { ListKey(id: $0.1 as! Element.ID) }
I have not tried whether it works or not. I suppose the key is usually a String
or Int
, and none of them conforms to AnyObject
so this might crash.
An other hacky solution, to convert the List
to Results
with a simple filtering. As far as I know realm handles this very well, so not much performance is lost.
var keyedEnumeration: [ListKey<Element>] {
guard let key = Element.primaryKey() else { return [] }
let keys = filter("TRUEPREDICATE").value(forKey: key) as! [Element.ID]
return keys.enumerated().map { ListKey(id: $0.1) }
}
Hi, can you please send a full demo code for this. I could not figure out where to use this extension