Define object with multidimensional properties [duplicate] - ios

This question already has an answer here:
Table view from array index out of range
(1 answer)
Closed 7 years ago.
PROBLEM:
What I'm looking for is to display this info in a table so I think I need:
MyHouses1[section][row].getAddressDetails()
How do I properly define MyHouses1?
import UIKit
class House {
var address = "Address"
var street = "Street"
var city = "City"
var state = "State"
var zip = "Zip"
func getAddressDetails() -> String {
return "\(address) \(street) \(city) \(state) \(zip)"
//return "\(address) \(street)"
}
func getCityState() -> String {
return "\(city) - \(state)"
}
}
class newhouse: House {
var lighting = "crappy"
var plumbing = "sucks"
var heating = "heats good"
var cooling = "cools good"
var repairs = "needs alot of repairs"
func getFixtureDetails() -> String {
return "\(lighting) \(plumbing) \(heating) \(cooling)"
}
}
// THIS WORKS
var MyHouses: [newhouse] = []
MyHouses.append(newhouse())
MyHouses[0].address = "test"
MyHouses[0].getAddressDetails()
// THIS DOESN'T WORK
var MyHouses1: [[newhouse]] = [] // No Error Yet
MyHouses1.append // Getting an error here, not sure how to append
Details: in order to post the website wants me to add more details.....so here I am adding more details lol

You could do this..
var MyHouses1: [[newhouse]] = []// No Error Yet
var houses = [newhouse]() //Initialize your `newhouse` array here
for i in 0...4 {
houses += [newhouse()]
}
MyHouses1 += [houses]
print("\(MyHouses1[0][0].city)") // will print "City"

Related

Array of objects from multiple loops [duplicate]

This question already has answers here:
How can I run through three separate arrays in the same for loop?
(6 answers)
Closed 4 years ago.
I would like to end up with an array of custom objects. I'm having trouble figuring out a way to go about this when I have multiple arrays to iterate through in order to create the custom objects. I have something like this:
class CustomObject {
var name = ""
var place = ""
var price = ""
}
var nameArray = [“name1”,"name2","name3"]
var placeArray = [“place1”,"place2","place3"]
var priceArray [“price1”,"price2","price3"]
var customArray [CustomObject]()
createObject(name : nameArray, place : placeArray, price : priceArray)
func createObject(name : [String], place : [String], price : [String]) {
let instance = CustomObject()
for names in name {
instance.name = names
}
for places in place {
instance.place = places
}
for prices in price {
instance.price = prices
customArray.append(instance)
}
}
I would like to end up with an array of those custom "instances". Right now my code is giving each attribute the last index of each array.
You can try , also i suppose all the arrays have the same count
var customArray = [CustomObject]()
for i in 0..<nameArray.count {
let instance = CustomObject()
instance.name = nameArray[i]
instance.place = placeArray[i]
instance.price = priceArray[i]
customArray.append(instance)
}

How to reduce an array in swift based on some condition

I need to know a good solution in Swift for the below problem I am facing.
I have an array of models declared as var dataArray = [PlanModel]().
class PlanModel: {
var isPurchased:String?
var planName:String?
}
Now I get data from the server and I fill the dataArray with the models. The dataArray consists of 3 models. The value of models are:
Model 1:
isPurchased = "true"
planName = "Question"
Model 2:
isPurchased = "true"
planName = "Personal"
Model 3:
isPurchased = "false"
planName = "Full"
What I need is to reduce this array by checking if the plan is purchased by checking value of isPurchased. If it's true remove it from array, if its false, then keep that in the array.
Please tell me what would be the simpler and efficient way of doing this in Swift?
You can use the filter function
var reducedArray = dataArray.filter {$0.isPurchased == "false"}
This will check each element of the dataArray and if the elements isPurchased is "false" it will keep it
You can use filter with contains function
Model Class:
class PlanModel {
var isPurchased:String?
var planName:String?
init(isPurchased:String?, planname:String?) {
self.isPurchased = isPurchased
self.planName = planname
}
}
override func viewDidLoad() {
super.viewDidLoad()
var plan = [PlanModel]()
plan.append(PlanModel(isPurchased: "true", planname: "Question"))
plan.append(PlanModel(isPurchased: "true", planname: "Personal"))
plan.append(PlanModel(isPurchased: "false", planname: "Full"))
// Filter function
plan = plan.filter {
($0.isPurchased?.contains("false"))!
}
print(plan.count)
// 1
}
Create a filtering function:
func notPurchased(planModel: PlanModel) -> Bool{
return planModel.isPurchased == "false"
}
and use the Array filter function passing in your function
let filteredArray = dataArray.filter(notPurchased)
After post my solution, let me tell you that it's better change isPurchased type from String to Bool.
And now...
class PlanModel
{
var isPurchased:String?
var planName:String?
}
let p1: PlanModel = PlanModel()
p1.isPurchased = "true"
p1.planName = "Question"
let p2: PlanModel = PlanModel()
p2.isPurchased = "true"
p2.planName = "Personal"
let p3: PlanModel = PlanModel()
p3.isPurchased = "false"
p3.planName = "Full"
var plans: [PlanModel] = [ p1, p2, p3 ]
// Filter elements with `isPurchased` property
// set to `true`. As isPurchased is marked as an
// `Optional` type I check that it's not nil before
// process it
plans = plans.filter()
{
guard let isPurchased = $0.isPurchased else
{
return false
}
return isPurchased == "true"
}
plans.forEach()
{
if let planName = $0.planName
{
print(planName)
}
else
{
print("unnamed")
}
}
Since you're looking for removing the item from array itself if it meets certain condition you can do the following code:
dataArray = dataArray.filter({ $0.isPurchased == "False"})
i find this is one of the best approaches and i was using Swift 3
Now on the side note, i recommend using structs instead of classes for models

Find an item and change value in custom object array - Swift

I have this class
class InboxInterests {
var title = ""
var eventID = 0
var count = ""
var added = 0
init(title : String, eventID : NSInteger, count: String, added : NSInteger) {
self.title = title
self.eventID = eventID
self.count = count
self.added = added
}
}
And i use it like this
var array: [InboxInterests] = [InboxInterests]()
Add item
let post = InboxInterests(title: "test",eventID : 1, count: "test", added: 0)
self.array.append(post)
I want to find the index by eventID key and change the value of added key in the same index
How is that possible?
For me, the above answer did not work. So, what I did was first find the index of the object that I want to replace then using the index replace it with the new value
if let row = self.upcoming.index(where: {$0.eventID == id}) {
array[row] = newValue
}
In Swift 5.0:
if let row = self.upcoming.firstIndex(where: {$0.eventID == id}) {
array[row] = newValue
}
Since you are using a class, use filter and first to find the value:
array.filter({$0.eventID == id}).first?.added = value
In this you:
filter the array down to elements that match the event ID
pick the first result, if any
then set the value
This works since classes are pass by reference. When you edit the return value from array.filter({$0.eventID == id}).first?, you edit the underlying value. You'll need to see the answers below if you are using a struct
EDIT: In Swift 3 you can save yourself a couple of characters
array.first({$0.eventID == id})?.added = value
EDIT: Swift 4.2:
array.first(where: { $0.eventID == id })?.added = value
array.filter {$0.eventID == id}.first?.added = value
The filter operator is not the best in this case, it works for some of you because classes are passed by reference.
Explanation: (You can copy the following code in a playground if you want to verify it).
class Book {
let id: Int
var title = "default"
init (id: Int) {
self.id = id
}
}
var arrayBook = [Book]()
arrayBook.append(Book(id: 0))
arrayBook.append(Book(id:1))
arrayBook.forEach { book in
print(book.title)
}
arrayBook.filter{ $0.id == 1 }.first?.title = "modified"
arrayBook.forEach { book in
print(book.title)
}
Arrays are copied by value not reference, so when you are using filter you are creating a new array (different than the initial), but when you modify the new one, the initial one gets modified too because both are pointing to the same class (classed are passed by reference), so after the filter your array will have changed and the new one gets deallocated. So in this case it will print "default", "default" and then "default, "modified".
What happens if you change class for struct, the value will be passed by value not reference so you will have 2 arrays in memory with different values, so if you go through arrayBooks again it will print before the filter "default","default", and then "default", "default" again. Because when you are using the filter you are creating and modifying a new array that will get deallocated if you do not store it).
The solution is using map, creating a new array with all the values but with the modified items or fields that we want and then replace our array with the new one. This will print "default", "default" before the map, and then "default", "modified"
This will work with structs, classes and everything that you want :).
struct Book {
let id: Int
var title = "default"
init (id: Int) {
self.id = id
}
}
var arrayBook = [Book]()
arrayBook.append(Book(id: 0))
arrayBook.append(Book(id:1))
arrayBook.forEach { book in
print(book.title)
}
arrayBook = arrayBook.map{
var mutableBook = $0
if $0.id == 1 {
mutableBook.title = "modified"
}
return mutableBook
}
arrayBook.forEach { book in
print(book.title)
}
array = array.map { $0.eventID == id ? newValue : $0 }
If you conform your class to Equatable then this would work:
extension Array where Element: Equatable {
#discardableResult
public mutating func replace(_ element: Element, with new: Element) -> Bool {
if let f = self.firstIndex(where: { $0 == element}) {
self[f] = new
return true
}
return false
}
}
Use like this:
array.replace(prev, with: new)

get variable data from a class - swift

So, i have a file data.swift with some informations
class Data {
var agen = [… ]
var tours = [… ]
var marseille = [… ]
……
}
In another viewcontroller, i m trying to get back a value from above with this.
I can get back a particular value with with command with success :
let entry = data.agen[indexPath.row]
It’s working but I would like set a variable in this command, I put this
var passedValue:String!
// passedValue coming from a segue from a previous VC
// passedValue could be "agen", "tours",”marseille” ...
let entry = data.passedValue[indexPath.row]
But it's not working message error told me "data doesn't have a member named "passedValue"
How could i set properly the variable ?
what about a slightly different syntax
class Data {
var agen = ["A","B","C"]
var tours = ["D","E"]
var marseille = ["F","G","H"]
subscript(index: String) -> [String]! {
switch index {
case "agen" : return agen
case "tours" : return tours
case "marseille" : return marseille
default: return []
}
}
}
let key = "agen"
let data = Data()
print(data[key][1])
(maybe make a bit more error prof)
Other solution is to create classes/structs for 'agen','tours', etc.
And set it in the Data object
class Data {
var agen = [Agen(title), Agen(title2)]
var tours = [Tour(title), Tour(title2)]
…… }
Because, probably you want to show some info about the object in tableView later, so you could go like this:
title.text = tour.title
subtitle.text = tour.placeName
imageView.image = tour.photos[1]

get the array index in swift [duplicate]

This question already has answers here:
How to find index of list item in Swift?
(23 answers)
Closed 7 years ago.
Here is my code in Swift for an iOS app.
class Test {
var name: String
var sname: String
init(name: String, sname: String) {
self.name = name
self.sname = sname
}
}
class ArrTest {
var arr = [Test]()
init() {
arr.append(Test(name: "test1", sname: "surname1"))
arr.append(Test(name: "test2", sname: "surname2"))
arr.append(Test(name: "test3", sname: "surname3"))
arr.append(Test(name: "test4", sname: "surname4"))
}
}
var x = ArrTest()
let obj = x.arr.filter { $0.name == "test1" }.first
println(obj?.sname)
I want to get the index and not the object of the first array object (in the array var). The "obj" x.arr.filter... returns the first object. I need the index of the correct object.
Well you can simply use the method find of the array:
// This is pseudocode haven't tried it but should go along those lines.
var x = ArrTest()
var searchMe = Test("test1", "surname1");
let obj = find(x, searchMe);
For this to work you need to implement the Equatable protocol, here you can find a simple tutorial. After that find should work with your test class.
let arr:Array = ["a","b","c"]
find(arr, "c")! // 2
find(arr, "d")

Resources