viewDidLoad() not running after segue - ios

I'm performing a segue from one table view to another.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
NSLog("You selected cell number: \(indexPath.row)!")
self.performSegue(withIdentifier: "types", sender: productList[indexPath.row])
}
It should run the viewDidLoad() of the new TableView described by the custom class of the ViewController (Which I've declared in Storyboard)
func viewDidLoad(parent: String) {
print("This should print")
super.viewDidLoad()
//self.typeTableView.delegate = self
//self.typeTableView.dataSource = self
//Set reference
ref = Database.database().reference()
//Retrieve posts
handle = ref?.child(parent).observe(.childAdded, with: { (snapshot) in
let product = snapshot.key as? String
if let actualProduct = product
{
self.productList.append(actualProduct)
self.typeTableView.reloadData()
}
})
}
Any Idea why this might be happening?

Embed navigation controller to your destination controller
and make a segue from current table views cell to it with identifier types.
Then add below method after your
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "types" {
if let indexPath = tableView.indexPathForSelectedRow {
let object = productList[indexPath.row] as! yourProductType
let controller = (segue.destination as! UINavigationController).topViewController as! YourDestinationViewController
controller.yourProductProperty = object
}
}
}
Make sure to declare yourProductProperty in your Destination controller so that you can access current product object in it.

viewDidLoad has no parameters and needs an override clause:
override func viewDidLoad() {
...
}

Your method signature is
func viewDidLoad(parent: String) {
but it should be
override func viewDidLoad() {
super.viewDidLoad()
// Your code
}

are you using same class to tableviewcell ? if yes then keep different identifier [RESUE IDENTIFIER] for both tableview.

Related

Swift 3: Pass String from TableViewController to another TableViewController [duplicate]

This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 6 years ago.
I have a UITableViewController showing all my users from Firebase in a list. If you tap on one user you see another UITableViewController with a static TableView Layout prepared in the Interface Builder to edit the user properties. I want to pass the UID of the selected user to the DetailTableViewController to load all of the current user data there.
EDIT: This question is not an exact duplicate. I want to pass data from one UITableViewController to another UITableViewController not a normal Detail UIViewController!
This is my current code of the first TableViewController.
Can somebody help me? I don't get it.
UserListTableViewController.swift:
import UIKit
import Firebase
import FirebaseAuth
import FirebaseDatabase
class UserListTableViewController: UITableViewController {
var dbRef:FIRDatabaseReference!
var user = [User]()
var writeSelectedUID:String!
var selectedUID: String = "Mister X"
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.startObservingDB()
}
func startObservingDB () {
dbRef.observe(.value, with: { (snapshot:FIRDataSnapshot) in
var newUser = [User]()
for user in snapshot.children {
let userObject = User(snapshot: user as! FIRDataSnapshot)
newUser.append(userObject)
}
self.user = newUser
self.tableView.reloadData()
}) { (error:Error) in
print(error.localizedDescription)
}
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return user.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "User Cell", for: indexPath) as! CustomUserListTableViewCell
// Configure the cell
let userRow = user[indexPath.row]
cell.userFirstLastNameLabel?.text = "\(userRow.firstName!) \(userRow.lastName!)"
cell.userUsernameLabel?.text = "#\(userRow.username!)"
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//let selectedUID = user[indexPath.row]
let selectedUserRow = user[indexPath.row]
self.writeSelectedUID = "\(selectedUserRow)"
performSegue(withIdentifier: "editUser", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
let viewcontroller = segue.destination as! ManageUserSettingsTableViewController
// Pass the selected object to the new view controller.
if(segue.identifier == "editUser") {
viewcontroller.usernameTextField.text! = "\(self.writeSelectedUID)"
print("Var: \(self.writeSelectedUID)")
}
}
}
In UserListTableViewController.swift :
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
let viewcontroller = segue.destination as! ManageUserSettingsTableViewController
// Pass the selected object to the new view controller.
//let object = self.writeSelectedUID as? String
// let object = self.writeSelectedUID as! String!
if(segue.identifier == "editUser") {
if let object = self.writeSelectedUID {
viewcontroller.detailItem = object as AnyObject?
}
}
}
In your AnotherViewController :
var detailItem: AnyObject?
usernameTextField.text = detailItem?.description

Passing CoreData keys to new ViewController

I am working on one part of my app which will function as a journal for the user, in which they can add an entry, then review or delete them afterwards. I followed a few Swift tutorials for CoreData and I have confirmed that the CoreData setup is working. However, I am having trouble getting values to pass to the UIViewController that will display the journal after already being saved. In one configuration I had tried it displayed no data, in another the data would stay the same no matter what entry selected, and in the setup below, this line journalEntryViewer.journalViewerTextView.text = journalTextToPass returns "found nil when unwrapping optional value."
Here is the code for the UITableViewController that acts as the list:
import UIKit
import CoreData
class JournalCollectionViewer: UITableViewController {
var JournalEntry = [NSManagedObject]()
var journalTextToPass:String!
var journalTitleToPass:String!
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
self.tableView.reloadData()
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "JournalEntry")
do {
let results =
try managedContext.executeFetchRequest(fetchRequest)
JournalEntry = results as! [NSManagedObject]
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
}
// MARK: - Table view data source
#IBOutlet weak internal var journalCollectionTable: UITableView!
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return JournalEntry.count
}
override func tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell =
tableView.dequeueReusableCellWithIdentifier("JournalCell")
let entry = JournalEntry[indexPath.row]
cell!.textLabel!.text =
entry.valueForKey("journalDate") as? String
return cell!
}
func selectedTableCell(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let entry = self.JournalEntry[indexPath.row]
self.performSegueWithIdentifier("ShowEntryViewer", sender: entry)
}
// MARK: - Navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "ShowEntryViewer" {
let journalEntryViewer = segue.destinationViewController as! JournalEntryViewer
journalEntryViewer.self.navigationItem.title = journalTitleToPass
journalEntryViewer.journalViewerTextView.text = journalTextToPass
}
}
}
In the Swift file for the viewer (journalEntryViewer), all I have done is declared the class and the UITextView. Needless to say, I am at a loss. Any help appreciated!
When you assign value to the IBOutlet object in the prepareForSegue method that time it is not initialized, so you need to pass the string object and assign that string object to the journalViewerTextView in the viewDidLoadof JournalEntryViewer.
First declare two instance var in the JournalEntryViewer like this
var journalTitle: String?
var journalText: String?
Now use this var in viewDidload
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.title = journalTitle
self.journalViewerTextView.text = journalTitle
}
Now pass this journalTitle and journalText in the prepareForSegue method of JournalCollectionViewer
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "ShowEntryViewer" {
let journalEntryViewer = segue.destinationViewController as! JournalEntryViewer
journalEntryViewer.journalTitle = journalTitleToPass
journalEntryViewer.journalText = journalTextToPass
}
}
New Edit:
Problem with your code is you have not used delegate method didSelectRowAtIndexPath instead of you are using something else selectedTableCell that is wrong try to implement delegate method of UITableView
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let entry = self.JournalEntry[indexPath.row]
self.performSegueWithIdentifier("ShowEntryViewer", sender: entry)
}
Now you are passing entry object so change your prepareForSegue like this
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "ShowEntryViewer" {
let journalEntryViewer = segue.destinationViewController as! JournalEntryViewer
let entry = sender as! NSManagedObject
journalEntryViewer.journalTitle = entry.valueForKey("journalDate") as? String
journalEntryViewer.journalText = entry.valueForKey("journalEntryText") as? String
}
}

Swift 2.1 - How to pass index path row of collectionView cell to segue

From the main controller that I have integrated collection view, I want to pass selected cell index path to another view controller (detail view)
so I can use it for updating a specific record.
I have the following working prepareForSegue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "RecipeDetailVC" {
let detailVC = segue.destinationViewController as? RecipeDetailVC
if let recipeCell = sender as? Recipe {
detailVC!.recipe = recipeCell
}
}
}
And I've tried including let indexPath = collection.indexPathForCell(sender as! UICollectionViewCell) but I get Could not cast value of type 'xxx.Recipe' (0x7fae7580c950) to 'UICollectionViewCell' at runtime.
I also have performSegueWithIdentifier("RecipeDetailVC", sender: recipeCell) and I wonder if I can use this to pass the selected cell's index path but not sure I can add this index to the sender.
I am not clear about the hierarchy of your collectionViewCell. But I think the sender maybe not a cell. Try to use
let indexPath = collection.indexPathForCell(sender.superView as! UICollectionViewCell)
or
let indexPath = collection.indexPathForCell(sender.superView!.superView as! UICollectionViewCell)
That may work.
I've wrote up a quick example to show you, it uses a tableView but the concept is the same:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var things = [1,2,3,4,5,6,7,8] // These can be anything...
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
let objectForCell = self.things[indexPath.row] // Regular stuff
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let objectAtIndex = self.things[indexPath.row]
let indexOfObject = indexPath.row
self.performSegueWithIdentifier("next", sender: indexOfObject)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "next" {
// On this View Controller make an Index property, like var index
let nextVC = segue.destinationViewController as! UIViewController
nextVC.index = sender as! Int
}
}
}
Here you can see you get the actual object itself and use it as the sender in the perform segue method. You can access it in prepareForSegue and assign it directly to a property on the destination view controller.

didSelectRowAtIndexPath performSegueWithIdentifier = i get nil in target view

i have ThirdView in my "start" view
import Foundation
import UIKit
class ThirdView : UITableViewController {
var jsonz:NSArray = ["Ray Wenderlich"];
var valueToPass : String?;
var programVar : String?;
override func viewDidLoad() {
super.viewDidLoad()
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
var newProgramVar = "lol";
let destinationVC = segue.destinationViewController as! FourthView
destinationVC.programVar = newProgramVar
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1;
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.jsonz.count;
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let myCell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
myCell.textLabel?.text = self.jsonz[indexPath.row] as? String;
return myCell;
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let valueToPass = "asd";
let destinationVC = FourthView()
destinationVC.valuePassed = valueToPass;
self.performSegueWithIdentifier("restDetail", sender: tableView);
}
}
I have a segue identifier: restDetail
When i run a project and click on cell, i cant recieve a variable valuePassed in "second" view, i get nil. Please help, why?
But i normal recieve a variable programVar from function prepareForSegue, it is ok. I have only problem with didSelectRowAtIndexPath segue.
It is my FourthView:
import UIKit
class FourthView: UIViewController {
var valuePassed:String!
var programVar:String!
override func viewDidLoad() {
super.viewDidLoad()
println(valuePassed);
println(programVar);
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
See here what i have in output:
nil
lol
nil
lol
And second question: why in output it shows 4 times?
Sorry for my english.
In didSelectRowAtIndexPath you are not initializing the FourthView instance correctly.
This line:
let destinationVC = FourthView()
Creates a random instance of FourthView, that isn't the one you're using as destination.
If you want to pass a value to the FourthView it's usually best to do that in prepareForSegue.
As you can see in the line below, here you are setting the destinationVC variable to FourthView instance, which is the destination View Controller of your segue.
let destinationVC = segue.destinationViewController as! FourthView
The issue is with the following code:
let valueToPass = "asd";
let destinationVC = FourthView()
destinationVC.valuePassed = valueToPass;
You are allocating a temporary instance of FourthView and passing data to it. And after that you perform a segue. Perform segue initialises your view controller and loads it to the view (different one, not the one you initialised manually in the didSelectRowAtIndexPath). You need to pass the data from the prepareForSegue: method.

Propertylist in array passed with segue

So I am trying to create a app that is more or less a reference with static data and using a plist to store the data
I have two TableViewControllers setup on the storyboard and I wanna pass the selected cells rownumber or its data to the next view?
My initial setup:
import UIKit
var categoryNames:NSArray = []
var categorySelected:String = ""
class ListForbTVC: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
let path = NSBundle.mainBundle().pathForResource("listor", ofType: "plist")
let dict = NSDictionary(contentsOfFile: path!)
categoryNames = dict.objectForKey("Category") as NSArray
println(categoryNames.count)
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
For some reason I cannot figure out how to count the number of rows in the array?
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 13
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel!.text = categoryNames[indexPath.row] as? String
return cell
}
What should I add here to actually pass the value through the segue? Would be neat to know how to both pass the index of the selected row and how to pass the actual value of it.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "listData" {
}
How do I recieve the information in the next view?
I have done this in obj-c and X-Code 5 but I cannot figure out how to do this in Swift.
Thanks in advance
You can simply declare a property in your second view controller - something like this -
class VC2 : UIViewController {
var someString:String?
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if (self.someString != nil) {
println("Some string =\(self.someString)")
}
}
}
Then in your prepareForSegue, simply set it
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "listData" {
let destVC=segue.destinationViewController as VC2
destVC.someString="Some value"
}
}
I have updated my answer as per swift.Please check.
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "segueTest") {
var svc = segue!.destinationViewController as secondViewController;
svc.toPass =data}
}
Please check this http://jamesleist.com/ios-swift-passing-data-between-viewcontrollers/
Let me know if faces issue still.

Resources