Passing a Model between View Controllers - arrays

I am struggling to pass a model of data from one controller to the next. I am sure I am just missing something very simple but hoping I can get some help.
Below I create the code to select all the data from the row that was selected:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
print(indexPath.row)
let passingData = arrivals[indexPath.row]
print(passingData)
let controller = storyboard?.instantiateViewController(withIdentifier: "FlightInfoVC") as! FlightInfoViewController
controller.flightDataPassedIn = passingData
//Code incomplete - Will add execution to show VC
}
That print statement is reflected below:
Now where I am struggling is to get that data to go to my next view controller. Setting the array of data in my new VC doesn't seem to work because it is expecting a type of 'FlightModel' but I cannot seem to figure out how to declare that. I have tried this but I cannot convert type [Any] to 'FlightModel'
var flightDataPassedIn: FlightModel = []
Appreciate any help you can give!

It sounds like the issue is that you're trying to initialize flightDataPassedIn with a value of [], which is of incompatible type [Any].
If you're okay with the flightDataPassedIn property on FlightInfoViewController being optional, that might be the most straightforward solution. It would automatically be initialized to nil, so would not require you to set an initial value - just declare it like this:
var flightDataPassedIn: FlightModel?
If you don't want it to be optional, initialize it to a default value of type FlightModel (add an initializer to FlightModel if necessary) and overwrite it with passingData from the parent ViewController.
Hope this helps!

The issue was that I was not passing the data via the main required function that everyone uses Prepare for segue
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "TrackingToInfo" {
if let destinationVC = segue.destination as? FlightInfoViewController {
destinationVC.flightDataPassedIn = readyToPass
}
}
}
Within the tableview I had to set the data to a var in my currentVC of type FlightModel? then the data passed

Related

What is the best way to approach a 'How many items do you have selected' type counter?

What I'm meaning is: I have a Table View and Populated Cells, I want each cell, when selected, to link to its on or off state that is represented in its bool value. When it's in an 'On' State, it adds +1 to a counter, when it's clicked to it's 'Off' state it takes back that count (so subtracting). I have the bool within the class that populates the table view so that it doesn’t mix up selections when filtering data via search bar
Imagine a 'How many items do you have selected' type of counter.
What I'm unsure about is how to connect the bool to the selection itself so it’s not ‘mixed up’. Examples are welcome!
Thankyou
Propably easiest solution is using simple variable "counter" and count your selections in UITableViewDelegate method didSelectRowAt (counting up) and method didDeselectRowAt (counting down)
Here are some steps and example code:
create UITableview and conform your UIViewController to UITableViewDelegate protocol . Then add methods to your UIViewController and conform yourTableView.delegate = yourViewController (propably just self).
Adding delegate methods:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.counter += 1
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
self.counter -= 1
}
To approach this question, I would have a custom table view cell. A great tutorial on this is here: https://www.youtube.com/watch?v=OQYqGM5_wVY&list=LL&index=16&t=752s
It actually shows the use of a switch in a tableview.
To have a counter, I would use UINotification Center. In the custom tableview cell swift file, I would add something like the code below to the action for your switch:
if switch.isOn{
NotificationCenter.default.post(Notification(name: Notification.Name("tableSwitchClicked"), object: nil, userInfo: ["isOn":true]))
} else {
NotificationCenter.default.post(Notification(name: Notification.Name("tableSwitchClicked"), object: nil, userInfo: ["isOn":false]))
}
"switch" is whatever the outlet name of your switch is.
Then add this to your viewcontroller swift file in the viewDidLoad:
NotificationCenter.default.addObserver(self, selector: #selector(changeSwitchCounter(_:)), name: Notification.Name("tableSwitchClicked"), object: nil)
and finally, this in your code after viewDidLoad in the main view controller:
#objc func changeSwitchCounter(_ notification: Notification){
let positiveChange = notification.userInfo!["isOn"] as! Bool
if positiveChange == true {
switchOnCount += 1
} else if positiveChange == false {
switchOnCount -= 1
}
}
where switchOnCount is the variable you use to track the amount of switches on. I hope this helps you! Please comment if you have any questions.

SWIFT : Update an Array in one controller but use the updated array in another controller

I am quite new to IOS programming and swift and I could use some help.
What I am trying to do is the following :
I am having three Controllers A,B & C .
C is the Controller that holds an empty array of UIimages
class DataController {
var imagesTaken = [UIImage]()
}
I call an instance of my Controller C in my Controller A and I append the array by adding photos.
This works fine.
How I could call the updated array in Controller B ? So far when I call controller C array it just makes a new instance with 0 elements...(makes sense I guess..)
I am quite new at this , so be patient :)
Ok a solution was found.
As Kudos proposed,
I created a new object/instance "array A" of Controller C in Controller A and updated the array within Controller A.
In controller B I created an empty array, "array B"
Using prepare for segue, I set the "array B" = "array A"
I attach the code as reference :
#IBAction func tableViewButton(_ sender: UIButton) {
self.performSegue(withIdentifier: "tableView", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "tableView" {
let destinationVC = segue.destination as! TableViewController
destinationVC.dataArray = dataControllerPhoto.imagesTaken
}
}
Finally I found the below site that includes six ways to pass data from one class to another :
https://learnappmaking.com/pass-data-between-view-controllers-swift-how-to/

An array of user id's that you want to display information of; how do you filter for those elsewhere in the code?

Say you have a subset of users in an array via their uid. You want to display the information of these users in your application. So how do you use this array elsewhere in the code to only display for those uids.
There are 2 pages where I have to do this, and on one I managed to fix it with if self.array1.contains(people.key) However on the second page (I assume because it is structured differently), that does not work.
//Part 1: The array and current attempt
var array1 = [String]() ///this is at top of code before viewDidLoad
///In view did load
if let unwrappedName = name {
self.array1.append(unwrappedName)
}
}
print(self.array1, "ahah")
///Also in view did load, in a dataSnapshot, above the array definition
refArtists = Database.database().reference().child("people");
refArtists.observe(DataEventType.value, with: {snapshot in
for people in snapshot.children.allObjects as! [DataSnapshot] {
if people.key != thisUsersUid {
**if Calendar.current.isDateInToday(date) && countb >= 1 && self.array1.contains(people.key) {**
}
...
self.people.append(peopl)
...
self.people.sort(by: { $0.TodayLikeCount ?? 0 > $1.TodayLikeCount ?? 0 })
print("aaaaaaaa", self.people.map {$0.TodayLikeCount})
self.table.reloadData()
///How is this page structured:
1)class ranking: UITableViewController, CLLocationManagerDelegate{
2) All the definitions like var = this, let this = that etc
3)public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
4)public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell ///Return cell is made here
5)override func viewDidLoad(), super.viewDidLoad(), table.dataSource = self, table.delegate = self
6) **The refArtist.obeseve snapshot posted above**
7)**The defining of the array**
8)Other code
For filtering an array and show it, you have to create another array and store the sorted results in that array, and use that array to reload the tableView. Also initially keep that array same as peopleArray by default. Then you can pass around this array to other pages as well.
var filteredArray = [String]() // declare at the top
Inside the viewDidLoad
filteredArray = self.people.sort(by: { $0.TodayLikeCount ?? 0 > $1.TodayLikeCount ?? 0 })
self.table.reloadData()
Hope you are clear.

Optional array is empty after appending elements inside it in Swift

My context is as follows: I have a view controller that draws different room shapes. Each wall is a subclass of UIView. The model for the walls is as follows:
struct Wall {
let name: String
let number: Int
var length: CGFloat?
var attachedObjects: [WallObject]?
var isSelected: Bool
}
So each wall has a property that gets assigned one of the above ones.
When a tap happens on one wall the sender gets stored into an optional variable:
#objc fileprivate func changeWallProperties(sender: UITapGestureRecognizer) {
guard let tappedWall = sender.view as? RoomShapeDrawingV else {print("could not get wall"); return}
tappedWall.wallModel?.isSelected = true
selectedWallModel = tappedWall.wallModel
I have a collection view that displays objects that can go on the wall. When a cell is selected I get a WallObject type that is another struct for the contents of the collection view, the selection needs to be placed into the model for the selected wall:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let aWallHasBeenSelected = isWallSelected else {print("could not get the selected wall"); return}
if aWallHasBeenSelected {
print("a wall has been selected")
let wallObject = wallObjects[indexPath.item]
selectedWallModel?.attachedObjects?.append(wallObject)
The last line does nothing, [attachedObjects] is nil inside the model for that selected wall. I have found a solution on this post: Adding elements to optional arrays in Swift
But I want to know why this happens, if there is a logical error on my behalf or what. Is it because I use structs and I make copies of them, or there is something else happening?

Move array through Segue in swift 2

I want to pass an array of strings through segue, but my app crashes. Here is what I have in the starting ViewController:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "sendToOther") {
let svc = segue.destinationViewController as! OtherMinerals;
svc.toPass1 = String(DataSet[0])
svc.toPass2 = String(DataSet[1])
and this is what I have in the receiving ViewController
var toPass:String!
var toPass2:String!
so, I am passing every item separately through segue, but that's not elegant. I'd like to pass the whole array through, but for some reason I can't get the code right. Any genius out there to assist??
Just create a [DataSet] variable in your second ViewController and pass your whole DataSet array to your second ViewController instead of the two strings:
//second viewcontroller:
var dataSetArray:[DataSet]
//first viewcontroller:
svc.dataSetArray = yourDataSet
Change the type of the variable "toPass" to be [String]. If your DataSet is of the same type you can pass the array like so
svc.toPass = DataSet

Resources