Converting Array of Objects into Object of arrays - ios

I have a class with some arrays of different types and let's say they're all filled with the same amount.
public class CoreLocationMap {
var type: [String] = []
var location: [Int] = []
var groupName: [NSString] = []
var x: [Float] = []
init() {}
}
I want something like a JSON Object:
var jsonObject = ({type = myString; location = 123; groupName = anotherString; x = 0.123}, {type = myString; location = 123; groupName = anotherString; x = 0.123}, ...)
It's not necessarily to have a jsonObject, but i want to capsule my variables in logical groups, so
type
location
groupName
x
should make a struct/object/whateever^^.
If I use later for example a certain location i want to reference to the other variables in this group.
I'm also pleased about other solutions. If you need more details please tell me.
Thanks!

as you suggested you can use a struct to encapsulate your data:
struct LocationData {
var type: String
var location: Int
var groupName: String
var x: Float
}
and declare an array in your class :
var locationsData = Array<LocationData>()
add a function for adding elements :
func addLocationData(type: String, location: Int, groupName: String, x:Float) {
// Add additional safety/limitation checks
locationsData.append(LocationData(type: type, location: location, groupName: groupName, x: x) // structs have an implicit init method
}

you can create model calss lets say locationModel
like
calss locationModel{
var type:String
var location : Int
var groupName : String
var x: Float
// you can create Init method to init() model properties
// you can create custom method to fill values of model calss
/* you create custom method that accept array as argument create
this class (locationModel) type of object in function load data
from array to modelobject add modelobject in array and return
this array.*/
}
now you can create this model class object where you want to use and fill them with model class methods.
like if you want to use this in CoreLocationMap create location model and init it in your class and fill value.
and add this model objects in newly created array if you want array of object. hope this help you.

This library does the same thing for you JSONModel https://github.com/icanzilb/JSONModel
This library has the following method
NSArray* jsonObjects = [YourModelClass arrayOfDictionariesFromModels: modelObjects];
this method returns the Array of Dictionaries from Array of Objects.
Now , you can use
NSJSONSerialization

Related

How to iterate two arrays both containing custom classes simultaneously

lets say you have the classes:
class Artwork {
var title = ""
var location =""
var author = ""
}
class GroupedArtworks {
var location = ""
var artworks = [Artworks]()
}
then you have an variable that contains several objects of the class "Artwork":
var arts = [artwork1, artwork2...]
How would I group the objects of the class "Artwork" by "location"?
I would like to end up with another variable containing objects of the class "GroupedArtworks"
and for each object, in the attribute "artworks" have all the objects that have the same "location"
so something like:
var orderedArtworks = [groupedartworks1, groupedartworks2...]
No doubt for loops are involved here.
The solution is super easy with Swift's Dictionary init(grouping:by:)
let artworks: [Artwork] = []
// dictionary type will be [String: [Artwork]]
let dictionary = Dictionary(grouping: artworks, by: \.location)
// now we can easy iterate over (key: String, value: [Artwork]) pairs
let groups: [GroupedArtworks] = dictionary.map { location, artworks in
GroupedArtworks(location: location, artworks: artworks)
}
// or simply
let groups = dictionary.map(GroupedArtworks.init)
// Swift will infer the types of dictionary and the init
but you will need to add this init to your GroupedArtworks
class GroupedArtworks {
let location: String
let artworks: [Artwork]
init(location: String, artworks: [Artwork]) {
self.location = location
self.artworks = artworks
}
}
Documentation
As someone correctly pointed out in the comments, since dicts are unordered collections, your array of GroupedArtworks will be unordered one as-well. But this should not be a problem since you can easily sort it by lets say location.
let groups = dictionary.map(GroupedArtworks.init).sorted(by: \.location)

Array of object have further inner array of object

My class
class ScoreModel {
var playerId: Int?
var holeScores: [HoleScore]?
}
Other Class
class HoleScore {
var holeScore: Int?
}
I have these classes one is ScoreModel class which can have Array of objects of HoleScore
let scoreList = [ScoreModel]()
scoreList[0].holeScores![0].holeScore = 3
When i update or change holeScore for scoreList[0].holeScores[0] it changes it for all the scoreList[forAllIndexes].holeScores[0]. I just want to change the inner array prams for given index of outer array but it changes all the holeScore values when ever update.
This appends the same object , so change in one reflects to others
var item = HoleScore()
for i in 0...5
{
item. holeScore = i
scoreList[0].holeScores.append(item)
}
//
This appends different objects , so change in one doesn't reflects to others
for i in 0...5
{
var item = HoleScore()
item. holeScore = i
scoreList[0].holeScores.append(item)
}
Just solved my problem converting my classes to struct .I just did not know how to deal with this reference types in a nested sub arrays .So I used struct
struct ScoreModel {
var playerId: Int?
var holeScores: [HoleScore]?
}
struct HoleScore {
var holeScore: Int?
}
Now setting value for a specific inner index will not effect others
let scoreList = [ScoreModel]()
scoreList[0].holeScores![0].holeScore = 3

How can I find the type of a property dynamically in swift (Reflection/Mirror)?

So let's say I have a class like this:
class Employee: NSObject {
var id: String?
var someArray: [Employee]?
}
I use reflection to get the property names:
let employee = Employee()
let mirror = Mirror(reflecting: employee)
propertyNames = mirror.children.flatMap { $0.label }
// ["businessUnitId", "someArray"]
so far so good! Now i need to be able to figure out the type of each of these properties, so if I do the employee.valueForKey("someArray"), it won't work because it only gives me the AnyObject type. What would be the best way to do this? Specially for the array, I need to be able to dynamically tell that the array contains type of Employee.
You don't need to inherit from NSObject (unless you have a good reason to).
class Employee {
var id: String?
var someArray: [Employee]?
}
let employee = Employee()
for property in Mirror(reflecting: employee).children {
print("name: \(property.label) type: \(type(of: property.value))")
}
Output
name: Optional("id") type: Optional<String>
name: Optional("someArray") type: Optional<Array<Employee>>
This also works with Structs
If you are inheriting from NSObject, you can use some of the methods provided by NSCoding and the Objective-C runtime:
let employee = Employee()
employee.someArray = []
employee.valueForKey("someArray")?.classForCoder // NSArray.Type
employee.valueForKey("someArray")?.classForKeyedArchiver // NSArray.Type
employee.valueForKey("someArray")?.superclass // _SwiftNativeNSArrayWithContiguousStorage.Type
employee.valueForKey("someArray")!.dynamicType

how to print value of object in an array in swift, not its location

I have a class that contains data on certain entrepreneurs in a separate swift file that is within the same project.
It looks like this:
class Entrepreneur:NSObject {
var name:String?
var netWorth = (0.0, "")
var company:String?
var summary: [String]
var age: Int?
override init() {
name = ""
company = ""
summary = [""]
age = 1;
}
In the same file I have a function that returns an NSMutableArray which contain the instances of the entrepreneur class like this:
func populateArray() -> NSMutableArray {
var entreprenuersArray: NSMutableArray = []
//Mark Zuckerberg
let markZuckerBerg = Entrepreneur()
markZuckerBerg.name = "Mark Zuckerberg"
markZuckerBerg.age = 19
markZuckerBerg.company = "Facebook"
markZuckerBerg.netWorth = (35.7, "Billion")
// add mark zuckerberg object to array
entreprenuersArray.addObject(markZuckerBerg)
print (entreprenuersArray)
in my ViewController.swift file I create a constant called entrepreneurss and give it a type of the class "Entrepreneur" created above and initialize it like so:
let entrepreneuerss:Entrepreneur = Entrepreneur()
I then access one the class methods, the "populateArray" function and try to print the entrepreneurss array like so:
entrepreneuerss.populateArray()
print (entrepreneuerss)
The issue is the print function is printing the location of the object and not the value...something like this: .Entrepreneur: 0x7f88d0e3ecc0>"
What do I need to do so that I can return an array of the object values and not the location. I want to be able to access the array of object from my ViewController.swift file and randomly select an object and access its properties.
First, you have a instance method which returns an array of Entrepreneur objects (by the way, I don't see a return, maybe you forgot to copy it).
This method should be a class method, because you don't use any property of the Entrepreneur object which returns it :
class func populateArray() -> [Entrepreneur] {
var entreprenuersArray:[Entrepreneur] = []
//Mark Zuckerberg
let markZuckerBerg = Entrepreneur()
markZuckerBerg.name = "Mark Zuckerberg"
markZuckerBerg.age = 19
markZuckerBerg.company = "Facebook"
markZuckerBerg.netWorth = (35.7, "Billion")
// add mark zuckerberg object to array
entreprenuersArray.append(markZuckerBerg)
print (entreprenuersArray)
return entreprenuersArray
}
Then you can have your array by calling :
let array = Entrepreneur.populateArray()
Secondly, in this method, you create an array of Entrepreneur object and returns it, but in your example code, you never use this array :
// Creates a Entrepreneur object with default values
let entrepreneuerss:Entrepreneur = Entrepreneur()
// create an array of entrepreneurs objects, returns it, but never use it
entrepreneuerss.populateArray()
// print some information about the object with default values
print (entrepreneurs)
Instead, you should use the class method and try:
// create an array of entrepreneurs objects, returns it,
let arrayEntrepreneurs = Entrepreneur.populateArray()
// print some information about the array of Entrepreneurs objects
print (arrayEntrepreneurs)
In order to have a detailed description of your object, since it inherits from NSObject, just override the description read-only property in order to customize the text when you log your object :
override var description : String {
get {
return "Entrepreneur : name : `\(name) - company : `\(company)` - summary : `\(summary)` - age : `\(age)`"
}
}
Thus your print function will return :
[Entrepreneur : name : `Optional("Mark Zuckerberg") - company : `Optional("Facebook")` - summary : `[""]` - age : `Optional(19)`]
Maybe I am missing something here, but you can just use...
dump(arrayEntrepreneurs)
for Cocco
Swift.dump(arrayEntrepreneurs)
try
for element in array {
print(element)
}
What do I need to do so that I can return an array of the object values and not the location. I want to be able to access the array of object from my ViewController.swift file and randomly select an object and access its properties.
You already have the all the objects of entrepreneuers which are populated from your another swift file. you may use any object from the array and print it's any property.
Still you want to print the value of all the objects or all the properties of a object then you need to override the property called "description" into your model class.
add below code to your Entrepreneur class
override var description:String {
return "name :\(self.name) \n company \(self.company)"
}
The above code will print the name and company of any object of Entrepreneur

Sorting array of custom objects by its variable

I've created a custom class to hold image and its string(its name)
class Countries: NSObject {
var countryName : String
var countryFlag : UIImage
init(countryName: String, countryFlag: UIImage) {
self.countryName = countryName
self.countryFlag = countryFlag
super.init()
}
}
I declared the class
var myList: Array<Countries> = []
And add each country info to the array
let image = UIImage(data:imageData!)
let dd = Countries(countryName: object["CountryName"] as! String, countryFlag: image!)
self.myList.append(dd)
I tried below code to sort the array but doesn't work;
self.myList.sortInPlace({ $0.countryName < $1.countryName })
Does anybody has idea how can I sort my array according to above code?
You can sort an array like this using -sortUsingComparator:, which you pass a block into. The block takes the two objects you want to compare and returns a NSComparisonResult which is your comparison of the two. You could provide a block that uses countryName.
You could alternatively use -sortUsingDescriptors: and pass in a NSSortDescriptor that looks at the countryName field.

Resources