Sorting array of custom objects by its variable - ios

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.

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)

How to get method for class in Swift

I have a class:
class myObject: NSObject {
dynamic var objectId : String?
dynamic var name : String?
dynamic var lastName : String?
dynamic var age : String?
}
In my other class I am getting the value of this class's property:
self.myArray.append(myObject.name!)
I can get the value of myObject.name by adding .name but what if there will be hundreds of properties in my myObject class? For that I want to create a method which can return the properties of my class using a variable:
let myVar = "name"
self.myArray.append(myObject.myVar)
It should append the values of property name, but I am getting an error:
value of myObject has no member `myVar`
and I know why I am getting the error.
How can I get access to properties of my class using a variable? Something like :getValue(String) should return that property of my class.
You should also have a look at NSMutableDictionary, here's a quick example which shows how it works
// initialise a dictionary
var dict = NSMutableDictionary(objects: ["first", "second", 42], forKeys: ["String1", "String2", "Int1"])
// add a new attribute
dict.addEntriesFromDictionary(NSDictionary(object: "New thing", forKey: "String3") as [NSObject : AnyObject])
// access the data
let firstString = dict.valueForKey("String1")
let firstInt = dict.valueForKey("Int1")
// update the data
dict.setValue(99, forKey: "Int1")
let newValue = dict.valueForKey("Int1")
I can be wrong, but as I've already said in a comment, it would be better to use Dictionary and store values in it. Also if you want to access some values with a dot-notation, but still be able to get them by string, you can just create a property and override setter and getter
class MyClass {
var properties = [String: AnyObject]()
var someProperty: String? {
get {
return properties["someProperty"] as? String
}
set {
properties["someProperty"] = newValue
}
}
This way you are able to access value of someProperty both by object.someProperty and object.properties["someProperty"]
You can do it making array of object like following
var arrayOfObjects = [myObject]
and then set an objects values
var firstObject:myObject
myObject.name = "Your name"
myObject.age = "Your age"
...
then append first object to arrayOfObjects
arrayOfObject.append(firstObject)
and you can access it
print("First Object's name: \(arrayOfObjects[0].name)")

calling an array of dictionaries initialised in a class

what am i doing wrong in swift?
class ActivityDetailsModel {
var ActivityProfile: [[String]]
init(ActivityProfile: [[String]]){
self.ActivityProfile = ActivityProfile
}
}
var act = ActivityDetailsModel(ActivityProfile: ["cell2"+"firName": "two"])
gives Cannot invoke initializer for type 'ActivityDetailsModel' with argument of type (ActivityProfile: [String: String])
The type signature of the variable ActivityProfile is an Array of Array rather than the expected Array of Dictionary.
This uses the alternative syntax to make it clear
class ActivityDetailsModel : Printable {
var activityProfile : [[String:String]]
init(activityProfile: [[String:String]]) {
self.activityProfile = activityProfile
}
var description : String {
return activityProfile.description
}
}
var act = ActivityDetailsModel(activityProfile: [["cell2"+"firName": "two"]])
println(act)
PS: it's easier to read to start variable names with a lowercase letter

Converting Array of Objects into Object of arrays

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

How to use Swift specific containers in containers?

I have a Dictionary that holds another Dictionary that holds an Array which holds another Array of a custom class. I'm having a lot of trouble working with these can someone who this comes easy to tell me the ways I can define, initialize, and access and assign to either part specifically.
Dic = [String: [String: [[MyClass]]]]
Sorry if it's confusing.
This code shows you how to do what you asked, but the data structure you requested is quiet cumbersome to use. I'll recommend to think again about what you want to accomplish and review this data structure.
class MyClass {
var name : String
init(name: String) {
self.name = name
}
}
// Create your dictionary
var dic : [String: [String: [[MyClass]]]] = [:]
// Create a list of MyClass object
var list = [MyClass(name: "first"), MyClass(name: "second"), MyClass(name: "third")]
// Create a dictionary with string key and array of array of type MyList
var myClassDic = ["test": [list]]
// update or add new value via the updateValue method
dic.updateValue(myClassDic, forKey: "index1")
// update or add new value via the subscript
dic["index2"] = ["test2": [[MyClass(name: "forth"), MyClass(name: "fith")]]]
// Iterate over your outer dictionairy
for key in dic.keys {
// retrieve an entry from your outer dictionary
var tempDic = dic[key]
// Iterate over your inner dictionary
for sKey in tempDic!.keys {
// retrieve an array of array of MyList Object
var containerList = tempDic![sKey]
// iterate over the outer array
for listVal in containerList! {
//Iterate over the inner array
for sListVal in listVal {
print("\(sListVal.name) ")
}
println()
}
}
}

Resources