Move array through Segue in swift 2 - arrays

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

Related

Passing a Model between View Controllers

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

UIButton to append array of UIViews to UIStackView

I have this code, but it is only appending the first uiview. I also want the label in the uiview to display the string from arrayTwo. It's only printing the count right now.
I have the stackView in storyboard set to fill equally. And only top, trailing and leading constraints.
If I don't care about animation, can I append to a container UIView and the same code should just work? Obviously swapping out the stackView for a uiview
class ViewController: UIViewController {
#IBOutlet weak var arrayButton: UIButton!
#IBOutlet weak var stackView: UIStackView!
var arrayView = MyView() /// lives inside a nib only has one uilabel
var arrayOfView: [MyView] = []
var arrayTwo = ["one", "two", "three", "four", "five"]
var arrayIndex = 0
override func viewDidLoad() {
super.viewDidLoad()
stackView.spacing = 4
}
func appendViews() {
for i in 0...arrayTwo.count - 1 {
arrayOfView.append(arrayView)
//arrayOfView[I].myLabel.text = arrayTwo[i]
arrayOfView[i].myLabel.text = arrayTwo.first
stackView.addSubview(arrayOfView[i])
stackView.addArrangedSubview(arrayOfView[i])
}
}
#IBAction func arrayButton Action(_ sender: Any) {
appendViews()
}
}
This line of code repeatedly adds the same object to the array:
arrayOfView.append(arrayView)
I assume that MyView is a class inherited from UIView, so in Swift in has reference type semantics (read more about value and reference types). When this line gets executed, no new instance of MyView gets created, instead the reference to the same existing object gets added to the array. Later, when you add subviews to the stack view, it just tries adding the same view over and over again.
What you need instead is to create a new instance of MyView for every iteration. That said, you'll no longer need the arrayView property.
There are also a few other issues that can be addressed:
The raw for-loop can be replaced with a much safer for-in statement to avoid operating directly with array indices.
You almost never call the addSubview for UIStackView because it will not automatically arrange the views added that way. Calling just addArrangedSubview is what you always want.
The arrayIndex property seems to be unused and can be deleted.
arrayTwo is not a good name because it doesn't tell anything about the contents and the semantics, try making it more descriptive like labelTexts.
After all you get something like this:
for text in labelTexts {
let myView = MyView()
arrayOfView.append(myView)
myView.myLabel.text = text
stackView.addArrangedSubview(myView)
}

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/

Create a shuffled Array that I can use in all functions thereafter

Hi I'm trying to shuffle an array which I can then use in all my IBAction functions thereafter in the order that I shuffled them. Example of code which is the same idea as what I have...
Class ViewContoller: UIViewContoller
Let numbers = [1,2,3,4,5]
override func viewDidLoad() {
super.viewDidLoad() }
I've tried to write a function here to create an array which has been shuffled so I can use that shuffled array ...
func shuffledArray() -> Array<Int> {
let numbersArray = numbers.shuffled()
return numbersArray }
let myListOfShuffledNumbers = shuffledArray()
Now this works in playground.. but when I try this my viewcontroller.swift I get error 'cannot use instance member 'shuffledArray' within property initializer; property initializers run before self is available.
So I know if I'm in a IBAction func I can run the function let shuffledNumbers = shuffledArray()and get an Array of shuffled numbers to use but my problem is I need to use that same shuffle order in another IBAction function. So how can I make a universal array of shuffled numbers to use anywhere on my view controller.
I've tried lazy var myListOfShuffledNumbers = shuffledArray()
This gets rid of my error but it doesn't help me because I get a 2 different list order when I use 'myListOfShuffledNumbers' in 2 different IBAction functions
What can I do ?? Thanks
You can define a property that you can access from anywhere in your ViewContoller, like this:
class ViewContoller: UIViewContoller {
let unshuffledNumbers = [1,2,3,4,5]
var myListOfShuffledNumbers = [Int]() /// here! it's still empty at first
#IBAction func firstButtonPressed(_ sender: Any) {
myListOfShuffledNumbers = unshuffledNumbers.shuffled()
}
#IBAction func secondButtonPressed(_ sender: Any) {
/// do something with myListOfShuffledNumbers here...
}
}
At first, myListOfShuffledNumbers is still an empty array of Ints. But inside your first IBAction, you can assign that to unshuffledNumbers.shuffled(). Then, you can access it from inside your second IBAction.
Also it might be easier to just write [Int] instead of Array<Int> -- they are the same thing.
func shuffledArray() -> [Int] {
let numbersArray = numbers.shuffled()
return numbersArray
}
If you want an array that is shuffled then just convert it to a set. Sets will not keep the original order of the array.

How to pass array of images to detailView Swift?

Well I have been making a test app to continue my swift learning, today I came across a problem.
Basically I have a tableview and a detailview. For my tableview file I have some data that I am currently passing to the detailview, like the name that goes on the navigation bar, one image and some text, this data is stored in arrays on my tableview file, I use "prepareforsegue" to pass this information:
var names = ["name1","name2","name3"]
detailViewController.detailName = names[indexPath.row]
Then in my detailViewController I have variables set for that:
var detailName: String?
Then I use this for stuff, example: naming my navigation bar or setting an image in detailView:
navigationItem.title = detailName!
Now, what I dont get how to do is pass a whole array of information to a variable in my detailViewController. What I want to do is pass an array of images to use it on my detailView. I want to be able to iterate through the array of images with a button, I know how to set that up but I just need to know how to pass the array, right now I am just passing one of the values(one name, one image etc...)
Thanks for the help in advance.
It's not so different from what you have done.
Just add field for images in detailViewController, and then pass images using it. Images could be represented in [UIImage]. However, [String] can be also used for local filenames, and [NSURL] can be used for remote image urls.
code:
In DetailViewController:
var images: [UIImage]? // or var images: [UIImage] = []
In prepareForSegue:
detailViewController.images = YourImages
You seem to be asking for one of two things:
A UIImage array, which you can declare using var imageArray : [UIImage] = [] and then append whatever images you want to pass.
Alternatively, you can pass in a [AnyObject] array and cast its elements to a UIImage or String by doing
var objectArray : [AnyObject] = []
objectArray.append("test")
objectArray.append(UIImage(named: "test.png")!)
if let s = objectArray[0] as? String {
// Do something with the string
}
if let i = objectArray[1] as? UIImage {
// Do something with the image
}
if let s = objectArray[1] as? String {
// The above cast fails, this code block won't be executed
} else {
// ... but this one will
}
in the table view controller file:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get reference to the destination view controller
var detailVC = segue.destinationViewController as! DetailViewController
var detailImages: Array<UIImage> = []
detailImages.append(UIImage(named: "pup.png")!)
detailImages.append(UIImage(named: "cutepuppy.png")!)
detailVC.detailImages = detailImages;
}
and in the detail file:
var detailImages: Array<UIImage>?

Resources