How to save an array to a Realm Object - arrays

I am new to using Realm. Is there an easy way to save an array to a realm object? I am receiving my data from a JSON REST call:
class SomeClass: RLMObject {
dynamic var id = 0
dynamic var name = ""
dynamic var array: NSArray
func checkForUpdates() {
// Download JSON data here... The results have an array inside of them.
SomeClass.createOrUpdateInDefaultRealmWithObject(SomeNSDictionary)
}
override class func primaryKey() -> String! {
return "id"
}
}
Is it possible to save the array in the JSON results in Realm?
Thanks.

Realm has a special RLMArray type, which allows storing a collection of RLMObject's tied to a parent RLMObject. For example, say you had the following JSON:
{
"name": "John Doe",
"aliases": [
{"alias": "John"},
{"alias": "JD"}
]
}
You could model this with the following classes:
class Alias: RLMObject {
dynamic var alias = ""
}
class Person: RLMObject {
dynamic var name = ""
dynamic var aliases = RLMArray(objectClassName: "Alias")
}
So you could simply create a Person object with the following API call:
Person.createInRealm(realm, withObject: jsonObject)
You can learn more about how RLMArrays work from Realm's reference documentation: http://realm.io/docs/cocoa/0.80.0/api/Classes/RLMArray.html

Related

Create an object array from another object array and reconstruct the original object array later using map

Consider the following classes
class Category {
var tag: String?
var itemList: [Item]?
}
class Item {
var id: Int?
var type: String?
var itemDetails: ItemDetails?
}
class ItemDetails {
var description: String?
var name: String?
var price: Float?
}
Given an array of Category objects.
var categoryList: [Category]
I want to create a new object array by extracting only the name in ItemDetails(inorder to apply a filter) and an id inorder to reconstruct back array of Category objects.
Hence, I have to reconstruct the array of Category objects
from new object array.
How to do both extraction and reconstruction using the map feature?
Below are the examples of other data sources:
Datasource 1 :
var categoryList: [Category], where name need to be extracted
Datasource 2 :
var searchList = [SearchItem], where title to be extracted.
Class SearchItem {
var id: Int?
var details: SearchItemDetails?
var type: String?
}
Class SearchItemDetails {
var description: String?
var title: String?
}
DataSource 3
var products: [Products], where title to be extracted.
Class Products {
var id: Int?
var details: ProductDetails?
var type: String?
}
class ProductDetails {
var description: String?
var title: String?
}
To get an array of just the names, you do the map like you mentioned:
let categories: [Category] = ... // this already exists
let itemNames = categories.map { $0.itemList?.map({ $0.itemDetails?.name }) }
But this will preserve optionals. If you don't want optionals, then use compactMap instead.
Reconstructing, however, doesn't really make any sense. Are you using the ID to hit a database or network service? That's the only possible way you'd be able to reconstruct the original array of Categorys. Why not just hold onto the original array?

Trying to convert object mapper model to array

I'm new to Swift and have asked a few questions that I was somewhat confused about how to get the correct type for my object, but I believe I've figured it out.
I have a User object that is an Object Mapper model.
I am trying to convert this Object Mapper model to an Array.
https://github.com/Hearst-DD/ObjectMapper
However I am getting the error Cannot specialize a non-generic definition
Here is the variable I am trying to cast:
fileprivate var userDataSource = Mapper<User>().Array<Any>(User)
And an extension for its definition:
extension AccountViewController: GetUserDelegate {
func getUserSuccess(user: User) {
self.userDataSource = User
}
}
The original mapping to a model is done here:
guard let user = Mapper<User>().map(JSONObject: value)
The user class looks like this:
class User: Mappable {
required init?(map: Map) {
}
init() {}
var id: Int?
var firstName: String?
var lastName: String?
var displayName: String?
var image: URL?
var about: String?
var email: String?
var password: String?
var authToken: String?
I can include more if desired.
What am I misunderstanding here? None of the examples I'm seeing for this error really seem to apply to my situation.
Desired ultimate output:
["Name", "Bob Jim"],
["MC #", "1234567"],
["Company Name", "Bob's Truckin"],
["Truck Type", "Flat Bed"],
["Cell", "(555) 555-5555"],
["Dispatch", "(999) 999-9999"],
["Favorite Destinations", "Los Angeles"]
I gather you want an array of Users as the datasource,
I'd declare it like any other array:
var userDataSource = [User]()
or
var userDataSource = Array<User>()
And to update the datasource,
extension AccountViewController: GetUserDelegate {
func getUserSuccess(user: User) {
self.userDataSource.append(user)
}
}

Swift Realm [[String]] object

I'm new to Realm and have been through the documentation a few times. I need to persist a [[String]] and have not found a way to do it yet
var tableViewArray = [[String]]()
I see the documentation pointing to Lists but I've been unsuccessful at implementing them. I'm showing my whole process here but just need help persisting my var tableViewArray = [[String]]()in Realm
This is my class
class TableViewArrays {
var tableViewArray = [[String]]() // populates the Main Tableview
/// add picker selection to tableview array
func appendTableViewArray(title: String, detail: String, icon: String ) {
var newRow = [String]()
newRow.append(title)
newRow.append(detail)
newRow.append(icon)
tableViewArray.append(newRow)
}
In the View Controller I instantiate the object
var tableViewArrays = TableViewArrays()
Then call the class function to populate the object
var tableViewArrays.appendTableViewArray(title: String, detail: String, icon: String )
Thank you for taking a look
I would make two Realm objects to be persisted, then nest them. Here's an example:
class RealmString: Object {
dynamic var value = ""
}
class RealmStringArray: Object {
let strings = List<RealmString>()
}
class TableViewArray{
let stringArrays = List<RealmStringArray>()
}
I can't say much about the efficiency of this method, but I suppose it should work for your purpose. Also, if you have a large amount of data, it may become a pain to persist each individual string, then string collection, the string collection collection.
create the classes
class TableViewRow: Object {
dynamic var icon = ""
dynamic var title = ""
dynamic var detail = ""
override var description: String {
return "TableViewRow {\(icon), \(title), \(detail)}" }
}
class EventTableView: Object {
let rows = List<TableViewRow>()
}
then instantiate the objects and append
let defaultTableview = EventTableView()
let rowOne = TableViewRow()
rowOne.icon = "man icon" ; rowOne.title = "War Hans D.O.P." ; rowOne.detail = "Camera Order Nike 2/11/17"
defaultTableview.rows.append(objectsIn: [rowOne])

Auto add a class instance to an array in Swift

How can I auto add a new class instance to an array?
Example:
class Product {
var name: String?
}
var products = [Product]()
How can I add a new instance of a Product class to the products Array? How can I append to the array?
I tried some code but I don't know how to reference the class in own class.
I tried something like this:
class Product {
var name: String?
init() {
products.append(Produt)
}
var products = [Product]()
Thanks!
If you want your newly created object stored in products array then you need to declare it as static property so that it is shared by all instance otherwise it will just add first object for your every instance.
class Product {
var name: String?
static var products = [Product]()
init() {
Product.products.append(self)
}
init(name: String) {
self.name = name
Product.products.append(self)
}
}
Now use this products array using Product.products.
_ = Product(name: "One")
_ = Product(name: "two")
print(Product.products)
I dont't know why you need it, but you can use
class Product {
static var products: [Product] = []
var name: String?
init() {
products.append(self)
}
}
Have you tried products.append(self) ?

Objectmapper get array of one item within JSON

So I have the following JSON, which I am using together with ObjectMapper and Realm.
{
"result": [
{
"id": 20,
"types": [
"now"
],
"url": "/nl/whereto/ezrhgerigerg",
"categories": [
{
"id": 39,
"name": "Food "
},
{
"id": 21,
"name": "Varia"
}
]
},
My problem is getting the data from "types", which for some items in the array says "now" or "later", and is empty for other items (hence, no types item is given).
I tried to do the following in my mapping:
class Publication: Object, Mappable {
dynamic var id:Int = 0
var typez = List<getType>()
dynamic var url:String?
required convenience init?(_ map: Map) {
self.init()
}
override static func primaryKey() -> String? {
return "id"
}
func mapping(map: Map) {
id <- map["id"]
typez <- map["types"]
url <- map["url"]
}
}
class getType: Object, Mappable {
dynamic var text: String = ""
required convenience init?(_ map: Map) {
self.init()
}
func mapping(map: Map) {
text <- map[""]
}
}
When I check the Realm database, you can see that typez, an array of [getType] was made, but it's empty for all items (even the ones where types is "now"). The other two items (id and url) are filled in in the database.
What am I doing wrong that it won't save to the database?
Because Realm cannot detect assigning List properties since List property is not Objective-C type. So List properties should be declared as let, and should not be nil. You should use append/remove.../insert...method to modifying theList`.
So your code
typez <- map["types"]
doesn't work, since you assign values to the typez property directly.
The workaround is like the following:
func mapping(map: Map) {
...
var typez: [String]? = nil
typez <- map["types"]
typez?.forEach { t in
let obj = getType()
obj.text = t
self.typez.append(obj)
}
...
First, store the mapped value to the local variable (it is string array). Then convert the string array to objects. Then append the objects to the List property.

Resources