Error when accessing a member of a globally defined array - ios

I am quite new to swift. I am attempting to define a global array of type [String] and then access the array for navigation through subscripts via UISwipeGestureRecognizer, which are then fed into loadedContentForAsset(name: String) to display a .scn model. I have included the code for the global definition; I am getting a Thread 1: EXC_BREAKPOINT (code=1, subcode=0x1049d69c8) signal when executing the code.. on the last line of the included.
Here is my global definition:
import Foundation
class Main {
let faceOverlayArray: [String]
init(faceOverlayArray:[String]) {
self.faceOverlayArray = ["overlayModelBlack", "overlayModelBlue", "overlayModelRed", "overlayModelGreen", "overlayModelWhite"]
}
}
let faceOverlayArray1 = (faceOverlayArray: ["overlayModelBlack", "overlayModelBlue", "overlayModelRed", "overlayModelGreen", "overlayModelWhite"]) as! [String]
Any suggestions or pointers are greatly appreciated!
Here modified code that works:
`class Main {
let faceOverlayArray: [String]
var faceOverlayContent: SCNNode
init(faceOverlayArray:[String],faceOverlayContent:SCNNode) {
self.faceOverlayArray = ["overlayModelBlack", "overlayModelBlue", "overlayModelRed", "overlayModelGreen", "overlayModelWhite"]
self.faceOverlayContent = loadedContentForAsset(named: faceOverlayArray1[0])
}
}
let faceOverlayArray1 = ["overlayModelBlack", "overlayModelBlue", "overlayModelRed", "overlayModelGreen", "overlayModelWhite"]`
This is the didSwipe() method that I am attempting to use to cycle through the array (it continues to return the same index)
public func didSwipeRight() -> String {
let arrayLength = faceOverlayArray1.count
var index = 0
index = (index < arrayLength) ? index+1 : 0
print(index)
var faceOverlayContent = faceOverlayArray1[index]
return faceOverlayContent
}

Related

create a dictonary with for loop in swift

I just want to create a dictionary with the help of for loop
sample code :
var counter: Int = 1;
var pageCountDict = [String:Any]();
for filterCount in counter..<6
{
if let count = "page_\(filterCount)_vtime" as? String
{
pageCountDict = [count: timeInterval_Int];
}
}
print(pageCountDict);
This print command give me only last value of forloop
I just want all the value of this variable pageCountDict in a dictonary
The way to assign to a dictionary is first use the subscript and assign the value to it:
pageCountDict[YourKey] = YourValue
Also, you can see many examples and explanations in Apple documentation regarding dictionaries.
With each loop, you are replacing the dictionary with one that contains only one element. What you want to do is this :
pageCountDict[count] = timeInterval_Int
Also, you shouldn't need the as? String part. This should be sufficient :
for filterCount in counter..<6
{
pageCountDict[count] = "page_\(filterCount)_vtime"
}
var pageCountDict = [String:Any]()
You can add values to this dictionary by merging previous contents and new data as follows...
let counter: Int = 1
var pageCountDict = [String:Any]()
for filterCount in counter..<6
{
let value = 9
let count = "page_\(filterCount)_vtime" //'if' is not needed as it is always true
pageCountDict.merge([count: timeInterval_Int], uniquingKeysWith:{ (key, value) -> Any in
//assign value for similar key
timeInterval_Int
})
}
print(pageCountDict)`

Objects of same class have the same properties even though declared differently when pushing segue

I've been stuck trying to fix an issue in my application that prevents me from getting my desired result.
When pushing segue to the next view controller, I passed two objects of the same class to var original:[Person] = [] and var edited:[Person] = []
if (segue.identifier == "showSummary") {
let vc = segue.destination as! SummaryViewController
vc.original = myObject
vc.edited = Bill.calculateBill(myObject, switchServiceCharge.isOn, switchGST.isOn)
vc.gst = (switchServiceCharge.isOn, switchGST.isOn)
}
Before calculateBill, the original value of a property inside is 11.
The calculateBill is a class function in another class Bill:
class func calculateBill(_ bill: [Person],_ svcCharge: Bool,_ GST: Bool) -> [Person] {
var mutableBill = bill
for i in 0 ..< mutableBill.count {
for j in 0 ..< mutableBill[i].items.count {
let tax = Bill.getGSTForIndividual(mutableBill[i].items[j].itemPrice, svcCharge, GST)
mutableBill[i].items[j].itemPrice += tax
}
}
return mutableBill
}
class func getGSTForIndividual(_ individualAmt: Decimal,_ svcCharge: Bool,_ GST: Bool) -> Decimal {
var taxCost : Decimal = 0.00
let SERVICE_CHARGE = Bill.getServiceCharge() //0.10
let GOODS_SERVICE_TAX = Bill.getGST() //0.07
if (svcCharge && GST) {
taxCost = individualAmt * SERVICE_CHARGE
taxCost = taxCost + ((individualAmt + taxCost) * GOODS_SERVICE_TAX)
}
else if (!svcCharge && GST) {
taxCost = individualAmt * GOODS_SERVICE_TAX
}
else if (svcCharge && !GST) {
taxCost = individualAmt * SERVICE_CHARGE
}
else {
taxCost = 0.00
}
return taxCost
}
When I did a print() to test whether the properties inside are different, they both yield the same results somehow...
print(original[0].items[0].itemPrice) //12.947000000000000123904, originally 11
print(edited[0].items[0].itemPrice) //12.947000000000000123904
What exactly is going on and why do both the objects have the same properties even though I have declared them differently?
I'm guessing that Person is probably declared as a class, not a struct. This means that it's a reference type, and when you:
var mutableBill = bill
you're not actually making a copy of bill, but rather another reference to the same object. So, when you change the properties on mutableBill, you also change the properties on bill, since they both point to the same object.
The solution is to make an actual copy of bill. The two options are either to declare Person as a struct, in which case you will always get a copy, or else to make an initializer on Person that takes another Person and initializes itself using the passed-in Person's properties:
init(person: Person) { ... }

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)

Calling and printing object inside object in swift 2

I have 2 classes, I have cats object in the AnimalClass and I am parsing jSON and I want to initialize the cats name from the jSON
class AnimalClass: NSObject {
var cats = [catClass]()
.....
}
And
class catClass: NSObject {
var name : String = ""
init(data : NSDictionary)
{
if let add = data["name"] as? String
{
self.name = add
}
Here I am trying to initialize it in the ViewController.swift
var animals = [AnimalClass]()
for(var i = 0; i < data_array.count; i++)
{
if let add = data_array[i] as? NSDictionary
{
self.animals.append(AnimalClass(data: add)) // this works
self.animals.cats.append(AnimalClass(data: add)) // this doesn't work
}
}
My question is for this line self.animals.cats.append(AnimalClass(data: add)) how can append to cats object which is in the AnimalClass.
You are not able to append AnimalClass to cats because cats is an array of catClass objects. You declared it like this:
var cats = [catClass]()
That's why the code below won't work.
self.animals.cats.append(AnimalClass(data: add))
So you should change it to:
self.animals.cats.append(catClass(data: add))
Moreover, class names in Swift should start with capital letter and I recommend you rename catClass to Cat (also dropping the Class suffix)
You will need to make use the init for your cat class.
change the line:
self.animals.cats.append(AnimalClass(data: add))
to:
self.animals.cats.append(CatClass(data: add))

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]

Resources