I am trying to update the UILabel on a previous Table View using an Unwinding Segue. I have everything working except I am bringing back blank text each time I select something on my modal. I am essentially bringing back the "" of the variable I am creating (myName).
However, I thought since I am updating the variable in my didSelectRowAtIndex that I would be bring that back. I did check to see if I am getting a value when selecting on the Modal and I am. So I think this is something as simple as updating the variable myName.
NewTableViewController (Modal):
var myName = ""
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let row = Int(indexPath.row)
var selectedObject = objects[row] as! PFObject
var selectedName = selectedObject["myName"] as! String
myName = selectedName as String
println(myName)
}
TableViewController (Source View Controller):
#IBAction func unwindName(segue: UIStoryboardSegue) {
println("unwind working")
if let svc = segue.sourceViewController as? NewTableViewController {
self.myNameLabel.text = svc.myName
println(myNameLabel)
}
}
When you invoke a segue (unwind or any other kind) from a cell, the segue will be executed before didSelectRowAtIndexPath is called, so you shouldn't set your variable value there (in fact you don't need to implement that method at all). You should implement prepareForSegue in the source view controller, and set the value of your variable there.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let cell = sender as! UITableViewCell
let indexPath = self.tableView.indexPathForCell(cell)
var selectedObject = objects[indexPath.row] as! PFObject
var selectedName = selectedObject["myName"] as! String
myName = selectedName as String
}
Related
I have a tableView with static cells.
What I wan't, is that when the user selects a certain cell, the text from this cell, is passed to the previous viewController. I have never worked with static cells before and I can only seem to find tutorials and other questions regarding activating the cells, so they leed to another viewController.
So how do I pass data (what's written in the cell), when the cell is selected?
Is it a code in didSelectRowAtIndexPath?
Do I use segues? Then there will have to be hundreds of segues, if I have hundreds of cell, that the user can choose, right?
Thanks!
First you are assigning Array of String to DiaryQuestionLabel.text which accepts string only in destinationViewController. Just change the type of chosenQuestion to String in destinationViewController as below.
#IBOutlet weak var DiaryQuestionLabel: UILabel!
var chosenQuestion: String = ""
override func viewDidLoad() {
super.viewDidLoad()
DiaryQuestionLabel.text = chosenQuestion
}
In your tableViewController You need to pass the value of selected index from your datasource array which you have used to set the data in your tableviewcell.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.destination is UpdatingIdentifiers {
let vc = segue.destination as? UpdatingIdentifiers
let selectedRowIndex = self.tableView.indexPathForSelectedRow()
// Get tableviewcell object from indexpath and assign it's value to chosenQuestion of another controller.
let cell = yourtableview.cellForRow(at: selectedRowIndex)
let label = cell.viewWithTag(420) as! UILabel
vc?.chosenQuestion = label.text
}
}
You are attempting to assign the wrong type to your variables. That is the cause of your errors.
For example,
You have defined chosenQuestion as an array of String values, i.e. [String], but you are attempting to assign an IndexPath at the following statement, vc?.chosenQuestion = selectedRowIndex.
To fix your problem,
You need to extract the specific string from your data source by utilising the IndexPath that you have stored into the selectedRowIndex variable.
For example,
If your data source array is called, myArray, you can do the following:
var selectedRowIndex = self.tableView.indexPathForSelectedRow
vc?.chosenQuestion = myArray[selectedRowIndex]
and then change your variable,
var chosenQuestion = ""
Finally, inside viewDidLoad():
DiaryQuestionLabel.text = chosenQuestion
Text label is of type String. You are assigning an array of string to it.
Also the same mistake you are doing with assigning indexPath to an array of Strings.
You are messing around with types.
Change to this:
vc?.chosenQuestion = tableView.cellForRow(at: selectedRowIndex).textLabel?.text
Change your variable to
var chosenQuestion = ""
And in viewDidLoad()
DiaryQuestionLabel.text = chosenQuestion
How about a simple way. This is similar to Ali_Habeeb's answer with more details.
In your didSelectRowAt:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let question = yourDataArray[indexPath.row]
let storyboard = UIStoryboard(name: "StoryboardName", bundle: nil)
let newVC = storyboard.instantiateViewController(withIdentifier: "newVCIdentifier") as! NewViewController
newVC.choosenQuestion = question
self.show(newVC, sender: self)
}
In your newVC:
class NewViewController: UIViewController {
#IBOutlet weak var DiaryQuestionLabel: UILabel!
var choosenQuestion = ""
override func viewDidLoad() {
super.viewDidLoad()
DiaryQuestionLabel.text = choosenQuestion
}
}
This is a very simple format, and should not produce any error and if does, then check your dataArray.
In Swift 3, I'd like to pass the string contained in a cell of a UITableView into the subsequent View Controller.
As a note, I read several answers to this that seem to be specific to earlier versions of Swift, so I wanted to reopen. As an example, the last solution here looked straightforward, but I can't get it to work.
In TableViewController, I create a string of an audio file's name and date posted with this JSON extraction:
if let shows_list = json as? NSArray
{
for i in 0 ..< data_list.count
{
if let shows_obj = shows_list[i] as? NSDictionary
{
let episode_name = shows_obj["episode"] as? String
let episode_date = shows_obj["date"] as? String
TableData.append(episode_date! + " | " + episode_name!)
let testString = TableData.append(episode_date! + " | " + episode_name!)
// the part above runs and will add the string into each cell. now here, I want to pass the value of that string into a UILabel called episodeTitle in the target view controller
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let indexPath = self.tableView.indexPathForSelectedRow {
let destinationVC = segue.cellPasser
EpisodeViewController.text = testString //this is the string in second view controller
}
}
}
}
}
This is throwing two errors:
Value of type 'UIStoryboardSegue' has no member 'cellPasser'
In the Storyboard, I have added an identifier to the Show segue called 'cellPasser.' My belief is I should be able to call that here but it's being flagged.
EpisodeViewController.episodeTitle = testString
I have an outlet in EpisodeViewController that is called episodeTitle, so I am wondering if there is a preferred way other than this to pass strings into an element like that.
I'm new to Swift -- hoping someone sees a better way to do this.
Edit: In case useful, here's the View Controller linked from the segue.
class EpisodeViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBOutlet var episodeTitle: UILabel!
Here are steps to pass value from TableViewController to next ViewController :
in TableViewController You should declare a didSelectRowAt method.
Declare a method prepare for segue
Do not forget to declare a variable in second view Controller.
1.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "Identifier", sender: indexPath)
}
2.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "Identifier" {
let vc = segue.destination as! NameOfYourViewController
vc.variableInSecondVc = variableInTableView
}
}
3.
var variableInSecondVc = ""
i am wondering how I can pass data from a ViewController to a cell?
I am a beginner so I may oversee the obvious :P
I have a home VC and when you press on a commentButton you get to the CommentVC which holds the postId of the post.
As I want to be able to like a comment( which works perfectly) and to notice the user about his comment being liked(which does not work for now) I need to have the postId not only in the commentVC ( which holds the correct one) but also in the cell.
this is the code where I pass data from the HomeVc to the CommentVC
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "CommentSegue" {
let commentVC = segue.destination as! CommentViewController
let commentCell = CommentTableViewCell()
let postId = sender as! String
commentCell.postId = postId
commentVC.postId = postId
}
}
When I print out both variables in CommentVc and CommentCell, only the CommentVc shows the correct one whereas the Cell has "nil" as the print out statement.
Any Idea how I can pass it?
You shouldn't instantiate UITableViewCells yourself by calling your custom classes initialiser, but you should do it in your UITableViewController class (or a class that conforms to UITableViewContollerDataSource protocol).
Pass the data you want to show in your cells to your table view controller and in your data source methods (for example tableView(_:cellForRowAt:)) when creating your cell using dequeueReusableCell(withIdentifier:) assign the data to the specific cell.
You should not pass a table cell. Since you already passed the postId to your comment view controller, you can access to this id from a table view cell in your comment view controller in this way
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "EditorFontCell") as! EditorFontCell
print(self.postId)
//do what you want with postId with the current cell object here
return cell
}
Now remove the cell in segue
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "CommentSegue" {
let commentVC = segue.destination as! CommentViewController
let postId = sender as! String
commentVC.postId = postId
}
}
Where did you perform the print out statement? Typically, it is recommended to pass any data to the cell view in cellForRow of TableView delegate method. Inside the cell class, you can have a configure(_ myId: String) method with the id as one of the parm to be passed in. Then print it inside that method.
//In cell table cell class create a variable to hold the data. Here I made postId as String variable.
class EditorFontCell: UITableViewCell{
var postId: String! // postId may be other type
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
}
// in this method you create an object i.e. cell, of type EditorFontCell
// and you can access that postId by this tableCell object. You can simple assign a value to as shown below.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "EditorFontCell") as! EditorFontCell
cell.postId = "String data"
return cell
}
I want to populate the prototype cells in a table view with information that the user has typed into a text field in a previous view controller. I want to set the title and subtitle of each cell using this data instead of a pre-determined array. How can I pass data from the text field inside a view controller to the title/subtitle section of a table cell view?
Any help is appreciated.
First of all implement this at the point where you want to segue to your TableViewController:
let textFieldString = yourTextField.text ?? ""
performSegueWithIdentifier("exampleID", sender: textFieldString)
Now create the right segue in your StoryBoard!
1) From the whole ViewController to your destination ViewController
2) And don't forget your unique segue-ID
The delegate method prepareForSegue(...) will be called before you perform the segue. In this method you prepare your destination ViewController.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
let targetvc = segue.destinationViewController as? YourTableViewController
if let targetvc = targetvc
{
let yourTextFieldString = sender as? String
if let yourTextFieldString = yourTextFieldString
{
targetvc.yourTextFieldString = yourTextFieldString
}
}
}
When the segue to your destination ViewController is performed, your variable (here in this case "yourTextFieldString") has the previous set data.
class yourTableViewController : UITableViewController
{
var yourTextFieldString = "" // This variable has the previous set data
override func viewDidLoad()
{
super.viewDidLoad()
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("yourCellID", forIndexPath: indexPath)
cell.textLabel.text = yourTextFieldString
return cell
}
}
Now adjust your prototype cell (don't forget the right identifier) and you're done.
I have a tableView displaying all the users on ViewController1(VC1) when the currentUser chooses a cell it segues to ViewController2(VC2) and needs to display all the user information from the cell that was clicked onto labels and a PFImageView. I have all the user info for the last cell displaying. So even though I clicked a different cell the next VC is only displaying the user at the end of the list. So lets say my user cell list display starts with Aisling, roger, dave and john. I click on cell 'Aisling' and segue to VC2, it displays all of Johns profile info.
VC1:
under the class:
var appUsers = [PFUser]()
var userToShow = PFUser()
then:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let singleCell: CustomCell = tableView.dequeueReusableCellWithIdentifier("mySingleCellid") as! CustomCell
let userObject = appUsers[indexPath.row] as PFObject
singleCell.userName.text = userObject["name"] as? String
singleCell.userAge.text = userObject["age"] as? String
singleCell.usersProfileImage.file = userObject["image"] as? PFFile
singleCell.usersProfileImage.loadInBackground()
// when userToShow is here it shows the user detail of the last cell everytime
userToShow = appUsers[indexPath.row]
return singleCell
} // cell for row
// when userToShow is here it crashes the app when the cell is clicked giving the error:unexpectedly found nil while unwrapping an Optional value
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
userToShow = appUsers[indexPath.row]
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "userProfileDetailsSegue" {
if let destinationVC = segue.destinationViewController as? UserProfileDetailsViewController {
destinationVC.userToShowDetail = userToShow
}
}
}
}
On VC2:
below the class:
var userToShowDetail = PFUser()
Then:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
userName.text = userToShowDetail["name"] as? String
userBio.text = userToShowDetail["bio"] as? String
userAge.text = userToShowDetail["age"] as? String
userProfile.file = userToShowDetail["image"] as? PFFile
userProfile.loadInBackground()
}
It only displays in VC2 the user details belonging to the user in the last cell on VC1. Instead of the user details belonging to the user in the cell that was chosen.
Stuck on this for a few weeks now and my deadline is pushing on can't solve it any help would really be appreciated!!! All links and help I could find online is for C# and obj c.
VC1
//PUT THIS IN THE FIRST VC CLASS
var appUserResult: PFUser?
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//TAKE OUT LET - YOU'VE ALREADY DEFINED AS CLASS VAR
appUserResult = appUsers[indexPath.row]
print(appUserResult)
self.performSegueWithIdentifier("openVC2", sender: self)
}
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "openVC2" {
let indexPath = self.resultsPageTableView.indexPathForSelectedRow!
//INDEXPATH ISN'T AVAILABLE IN PREPAREFORSEGUE
//let userToShow = appUsers[indexPath.row]
let newVc = segue.destinationViewController as! UserProfileDetailsViewController
//USE THE CLASS VARIABLE TO PASS
newVc.userToShowDetail = appUserResult
VC2
var userToShowDetail: PFUser?
In storyboard, delete the old segue. Create a new one from VC1 to VC2 (not from the table cells). Give it the identifier "openVC2".