How to encode Realm's List type
To make a Realm object model class with a property of type List
conform to Encodable
, you can simply convert the List
to an Array
in the encode(to:)
method, which can be encoded automatically.
extension User: Encodable {
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.username, forKey: .username)
let dogsArray = Array(self.dogs)
try container.encode(dogsArray, forKey: .dogs)
}
}
Test classes I used (slightly different from the ones in your question, but I already had these on hand and the methods in question will be almost identical regardless of the variable names):
class Dog: Object,Codable {
@objc dynamic var id:Int = 0
@objc dynamic var name:String = ""
}
class User: Object, Decodable {
@objc dynamic var id:Int = 0
@objc dynamic var username:String = ""
@objc dynamic var email:String = ""
let dogs = List<Dog>()
private enum CodingKeys: String, CodingKey {
case id, username, email, dogs
}
required convenience init(from decoder: Decoder) throws {
self.init()
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(Int.self, forKey: .id)
username = try container.decode(String.self, forKey: .username)
email = try container.decode(String.self, forKey: .email)
let dogsArray = try container.decode([Dog].self, forKey: .dogs)
dogs.append(objectsIn: dogsArray)
}
}
Test the encoding/decoding:
let userJSON = """
{
"id":1,
"username":"John",
"email":"example@ex.com",
"dogs":[
{"id":2,"name":"King"},
{"id":3,"name":"Kong"}
]
}
"""
do {
let decodedUser = try JSONDecoder().decode(User.self, from: userJSON.data(using: .utf8)!)
let encodedUser = try JSONEncoder().encode(decodedUser)
print(String(data: encodedUser, encoding: .utf8)!)
} catch {
print(error)
}
Output:
{"username":"John","dogs":[{"id":2,"name":"King"},{"id":3,"name":"Kong"}]}
How to use List type with Codable? (RealmSwift)
You are almost there. Inside the initializer, you can initialize the list using the decoded array. Basically, change
tags = try container.decode(List<Tag>.self, forKey: .tags) // this is problem.
to
let tagsArray = try container.decode([Tag].self, forKey: .tags)
tags = List(tagsArray) // Now you are good
As pointed out in the comments the List
constructor no longer works like this
You now want:
tags.append(objectsIn: tagsArray)
How to convert an array to List in Realm?
Note that your problem is not about converting List
to array, but rather converting an array to List
. You already know how to do the former: Array(someList)
, but since you are assigning an array (movie.genreIDs ?? []
) to a List
property (movieRealm.genreIDs
), you need to convert an array to a List
.
But wait! movieRealm.genreIDs
is a let
constant, so you can't assign to it anyway. Your real problem is that you haven't declared the genreIDs
property correctly.
If you follow the docs on how to declare a property of a List
type:
class CachedMovies: Object {
// genreIDs should not be optional
let genreIDs = List<Int>()
}
You'll see that you don't need to convert arrays to List
. You can just add the contents of the array to the List
, since the list is not nil:
movieRealm.genreIDs.append(objectsIn: move.genreIDs ?? [])
Note that if you actually want an optional list property (a property which can be nil, empty, or have elements), Realm doesn't support that.
Realm Swift - Convert an array of results into an array of Ints
You can simply use Array(realm.objects(RealmType.self))
, which will convert the Results<RealmType>
instance into an Array<RealmType>
.
However, there are other serious flaws with your code. First of all, neither of the last two lines will compile, since firstly realm.objects()
accepts a generic input argument of type Object.Type
and Data
doesn't inherit from Object
. You can't directly store Data
objects in Realm
, you can only store Data
as a property of a Realm Object
subclass.
Secondly, myArray[results]
is simply wrong, since results
is supposed to be of type Results<RealmType>
, which is a collection, so using it to index an Array
cannot work (especially whose Element
type is different).
Realm: Results T als List T
We can use extensions to make life easier :
extension Realm {
func list<T: Object>(_ type: T.Type) -> List<T> {
let objects = self.objects(type)
let list = objects.reduce(List<T>()) { list, element -> List<T> in
list.append(element)
return list
}
return list
}
}
Usage:
let objects = realm.list(YourObject.self)
How to convert RealmResults Object to List Object
To eagerly read every element from the Realm (and therefore make all elements in the list become unmanaged, you can do):
List<StepEntry> arrayListOfUnmanagedObjects = realm.copyFromRealm(realmResults);
But you generally have absolutely no reason to do that unless you want to serialize the objects with GSON (specifically, because it reads field data with reflection rather than with getters), because Realm was designed in such a way that the list exposes a change listener, allowing you to keep your UI up to date just by observing changes made to the database.
how to convert RealmSwift List to Results?
Both List
and Results
(as well as LinkingObjects
) can be converted into an AnyRealmCollection
type. I think this is probably the best way to standardize all of Realm's array-type types:
var dataSource:AnyRealmCollection!
let aRealmObject = realm.objectForPrimaryKey(SomeObject.self, key: objectId)
dataSource = AnyRealmCollection(aRealmObject.someList)
RealmSwift: Convert Results to Swift Array
I found a solution. Created extension on Results.
extension Results {
func toArray<T>(ofType: T.Type) -> [T] {
var array = [T]()
for i in 0 ..< count {
if let result = self[i] as? T {
array.append(result)
}
}
return array
}
}
and using like
class func getSomeObject() -> [SomeObject]? {
let objects = Realm().objects(SomeObject).toArray(SomeObject) as [SomeObject]
return objects.count > 0 ? objects : nil
}
Related Topics
Asyncdetached Falling Back into Main Thread After Mainactor Call
Difference Between? and ! in Swift Language
How to Work with Bindings When Using a View Model VS Using @Binding in the View Itself
Using Os_Log to Log Function Arguments, or Other Dynamic Data
How to Bind a Variable to Multiple Alternatives in a Switch Statement
What's the Difference Between Class Methods and Instance Methods in Swift
How to Set Uisegmentedcontrol Tint Color for Individual Segment
Swiftui Swizzling Disabled by Default, Phone Auth Not Working
Aws S3 Transfer Manager ${Cognito-Identity.Amazonaws.Com:Sub} Policy Variable Access Denied
How to Use Storyboards with Spritekit Using Swift
Swift: Extract Float from Byte Data
Storyboard Tableview with Segues to Multiple Views
How Do Closures Capture Values from Previous Calls
Why Does an @Objc Enum Have a Different Description Than a Pure Swift Enum