Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trial
Chris Howie
13,216 PointsPass a list of Usernames from an array to another View
I created an array of users in a Table View, I am trying to pass that data over to a View Controller So I can reference it when a user checks out a device. I am able to choose the first item, however I am not able to figure out how to transition the users selected name.
In my prepareForSegue Method I have the following
// Segue to pass the selected username
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "username" {
let controller = segue.destinationViewController as! DeviceViewController
controller.userNameID = self.myUserArray[0]
}
The useNameID is the value that I am passing to the other view. However, how do I set that do the selected Array Item that was selected from the TableView instead of just an indexed value?
3 Answers
Chris Howie
13,216 PointsHere is what I ended up doing that got it to work:
if segue.identifier == "username" {
if let indexPath = tableView.indexPathForCell(sender as! UITableViewCell) {
let deviceVC = segue.destinationViewController as! DeviceViewController
print(myUserArray[indexPath.row])
print(indexPath.row)
deviceVC.userNameID = myUserArray[indexPath.row]
}
Keli'i Martin
8,227 PointsYou should be able to get the correct index using the indexPath. Something like
if let indexPath = tableView.indexPathForSelectedRow
{
// use the indexPath.row to index your array here
}
Keli'i Martin
8,227 PointsHave you tried this:
// Segue to pass the selected username
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "username" {
let controller = segue.destinationViewController as! DeviceViewController
if let indexPath = tableView.indexPathForSelectedRow {
controller.userNameID = self.myUserArray[indexPath.row]
}
}
}
Or something to that effect?
Chris Howie
13,216 PointsYeah I have that a shot, however I am still returning a nil value. It seems like it is not referencing the array items.
Keli'i Martin
8,227 PointsHmm... that is strange... Question: what is controller.userNameID supposed to be representing? I see in your full TableViewController code below that it is being initialized as an Int. But, at least in your first code snippet, you appear to be trying to assign it a String value (since myUserArray is array of Strings).
Chris Howie
13,216 PointsSo I am trying to get the username cells over to the other view controller as a String, so that way I can reference it out as a message. So I could send a message that says "Chris has checked out the iPhone 6"
Here is my Code for the ViewController I want to pass data to:
class DeviceViewController: UIViewController {
var userNameID: String!
var selectedArrayItem: String!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
Client.sharedInstance.setAuthToken("Omitted Token")
Client.sharedInstance.connect()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func connectApp(sender: AnyObject) {
let channelID = Client.sharedInstance.channels.filter({$0.1.name == "qa-device-checkout"}).first
// Client.sharedInstance.sendMessage("\(userNameID) Checked Out the iPad Pro", channelID: channelID!.0)
Client.sharedInstance.sendMessage("\(selectedArrayItem) Checked Out the iPad Pro", channelID: channelID!.0)
}
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
}
Keli'i Martin
8,227 PointsOK, so it definitely looks like you're expecting a String. In which case, you seem to be initializing that variable as an Int, which would cause problems. Better to initialize it with an empty String, or at the very least explicitly declare userNameID as a String.
Michael Reining
10,101 PointsHi Chris,
No idea if it is the best way but I would create a property in the VC with the table and call it something like
var selectedArrayItem: Int?
in the didSelectRowAtIndexPath, I would then update this item.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let selectedArrayItem = indexPath.row
}
So now you can access it in the prepare for segue method.
controller.userNameID = self.myUserArray[selectedArrayItem]
I hope that helps,
Mike
PS: If you found the above helpful, be sure to check out my app which breaks code challenges down and really explains things so you can learn faster.
Code! Learn how to program with Swift
https://itunes.apple.com/app/code!-learn-how-to-program/id1032546737?mt=8
PPS: I could not have developed the above app without going through the awesome resources on Team Treehouse. Stick with it. It is so worth it!
Chris Howie
13,216 PointsWith this I am just returning a Nil Value instead of a username from my array. The didSelectRowAtIndexPath states that I never initialized selectedArrayItem.
class TableViewController: UITableViewController {
// User list array
var myUserArray = ["Chris", "Matt", "Daniel", "James", "Pedro"]
var userNameID = 0
var selectedArrayItem = 0
override func viewDidLoad() {
super.viewDidLoad()
// Stored value to pass to Device View
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Returns the number of sections in my Table View
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
// Takes the number of items in my array and returns it
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myUserArray.count
}
// Method to overide each cell instead of user name takes an item from my array
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("username", forIndexPath: indexPath)
cell.textLabel?.text = myUserArray[indexPath.item]
return cell
}
override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
var selectedArrayItem = myUserArray[indexPath.item]
//Initalization of variable 'selectedArray item was never used
}
// Segue to pass the selected username
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "username" {
let controller = segue.destinationViewController as! DeviceViewController
//controller.userNameID = self.myUserArray[0]
controller.userNameID = self.myUserArray[selectedArrayItem]
}
}
}
Above is my full tableview controller.
Keli'i Martin
8,227 PointsThere is at least one issue that would definitely break your code that I see in your snippet (pasting it again below to put comments inline):
class TableViewController: UITableViewController {
// User list array
var myUserArray = ["Chris", "Matt", "Daniel", "James", "Pedro"]
var userNameID = 0
var selectedArrayItem = 0
override func viewDidLoad() {
super.viewDidLoad()
// Stored value to pass to Device View
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Returns the number of sections in my Table View
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
// Takes the number of items in my array and returns it
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myUserArray.count
}
// Method to overide each cell instead of user name takes an item from my array
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("username", forIndexPath: indexPath)
cell.textLabel?.text = myUserArray[indexPath.item]
return cell
}
override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
// You are declaring a local variable named selectedArrayItem here,
// which will lose its scope once this function ends.
var selectedArrayItem = myUserArray[indexPath.item]
//Initalization of variable 'selectedArray item was never used
}
// Segue to pass the selected username
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "username" {
let controller = segue.destinationViewController as! DeviceViewController
//controller.userNameID = self.myUserArray[0]
// If you hadn't redeclared selectedArrayItem locally in the function above, you would be
// attempting to index into your array with a String
controller.userNameID = self.myUserArray[selectedArrayItem]
}
}
}
Those two issues would definitely cause, at best, unexpected behavior, and at worse, a crash.
Michael Reining
10,101 PointsYou need to change this
override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
selectedArrayItem = myUserArray[indexPath.item]
//remove the var. Otherwise you are creating a local instant that is only available within the function. Instead, update the property selectedArrayItem
}
I hope that helps,
Mike