How can I use pushViewController inside a cell Swift - ios

I have a viewController where I have a tableview and inside every cell I have a collectionView.
I want to go to another view (where I will have a back button) so I tried to use my code which is working for the other views:
let vc = self.storyboard?.instantiateViewController(withIdentifier: "detail") as! DetailView
vc.name = beachesNames[indexPath.row]
vc.imagak = imagesNames[indexPath.row]
self.navigationController?.pushViewController(vc, animated: true)
But because this code is inside the TableViewCell I have an error that says:
Value of type 'HomeViewCell' has no member 'storyboard'
Is there any alternative parameter that I can use or something else it could do my task?
Thanks in advance.

- swift 3
let detailOrderVC = UIViewController()
self.viewController()?.navigationController?.pushViewController(detailOrderVC, animated: true)
- swift 4
in swift 4, you need to pass the viewcontroller to the cell like below
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! CustomTableViewCell
// some your logic
cell.viewController = self // CustomTableViewCell needs to have viewController member variable
return cell
}
let detailOrderVC = UIViewController()
self.viewController?.navigationController?.pushViewController(detailOrderVC, animated: true)

If you are pushing to a view class that requires layout you must call layout at the same time.
ex.
let layout = UICollectionViewFlowLayout()
let nextViewclass = NextClass(collectionViewLayout: layout)
self.navigationController?.pushViewController(nextViewclass, animated: true)

If you have a collection view inside of every cell, then I would recommend having each cell hold a container view. The view controller associated with the container view will have a storyboard.
The code for the push would look a bit ugly:
self.parent?.navigationController?.pushViewController(vc, animated: true)
The parent?. goes from the contained view controller to the parent view controller.

What you're missing is instantiating the storyboard:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
storyboard.instantiateViewControllerWithIdentifier("myNavigationController") as! UINavigationController
But as this stackoverflow answer says, this generally isn't a good MVC design.
You might want to look into delegate patterns or using NotificationCenter. Both these ways essentially trigger a call to the parent view which will then handle the corresponding action.

Related

I'm trying to create UIStoryboard but on error occurs in my code

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
{
let vc = storyboard?.instantiateViewController(withIdentifier: "vc1")as? DetailViewController
//vc?.image = img[indexPath.row]!
//vc?.name = imageArray[indexPath.row] storyboard
self.navigationController?.pushViewController(vc!, animated: true)
}
Error is:
Use of unresolved identifier 'storyboard'
Look into this:
// Case: When the next ViewController is existed in the same Storyboard.
let controller = self.storyboard?.instantiateViewController(withIdentifier: "ControllerIdentifier") as! YourViewController
// pass data here to the next controller.
self.navigationController?.pushViewController(controller, animated: true)
// Case: When the next ViewController is exists in other Storyboard.
let storyboard = UIStoryboard(name: "StoryboardName", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "ControllerIdentifier") as! YourViewController
// pass data here to the next controller.
self.navigationController?.pushViewController(controller, animated: true)
Note: As you are using this line 'withIdentifier: "vc1"', I would like to suggest you that always assign the Storyboard ID for a ViewController same as ViewController's class name. Make it as a habit, it will be helpful because you don't need to remember the Storyboard Id what you set. So keep the thing simple.
Check in the properties of DetailViewController in Main.storyboard and see if the storyboard id is set properly. According to your code it should be vc1

What should I use to make this kind of cell, so I can get each of them to segue to different ViewController?

Here is what I want to do (UI is showing down below), I want to perform different segue when I taped different cell in it. But I don't know what component I should use to get this done
I think to use the Collection View Controller, but it seems doest support static cells, I want to use Customized UIVIew to do this, but it couldn't be dragged to another VC in StoryBoard, should I adopt some sort of Protocols of something to do this?
Please answer in Swift
After been helped
Turns out I just need to show the ViewController and haven't need segue yet, so here is the code.
let categories: [(name: String, pic: String, identifier: String)] = [
("人物", "Wilson_head", "CharactersVC"),
("动物", "Pig", "MobsVC"),
("植物", "Bamboo_Patch", "PlantsVC"),
("食谱", "Crock_Pot_Build", "RecipesVC")
]
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let currentCategory = categories[indexPath.row]
let destVC: UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: currentCategory.identifier)
navigationController!.pushViewController(destVC, animated: true)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
{
if(indexPath.row == 0)
{
let objstory = self.storyboard?.instantiateViewController(withIdentifier: “your Story bord identifier”) as! Your View_ViewController
self.navigationController?.pushViewController(objstory, animated: true)
}
}
Collection View Controller doesn't support static cell.
But you can add static cell programmatically.
set your cell data and target(segue id) for each cell.
ex:
cellData[0].segue = "segueToHuman"
cellData[1].segue = "segueToAnimal"
add segues depend on your view controller(not on cell) like below:
create segue
segue setting
perform particular segue in didSelectItemAt indexPath
let segueID = cellData[indexPath.row].segue
performSegue(withIdentifier: segueID, sender: nil)

Pass data from Modal Viewcontroller to rootController with Swift 3 (don`t Segue)

I have a problem.
I need help. I have been looking for a solution for about 5 hours. Unfortunately without success.
My problem is that I have several storyboards and created without Segue.
I would love the selected Tableviewcell title pass to rootViewController.
Here is my code in my ModalViewTable:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
let indexNumber = "\(indexPath.row)"
let indexPath = tableView.indexPathForSelectedRow
let currentCell = tableView.cellForRow(at: indexPath!) as UITableViewCell!
let storyboard = UIStoryboard(name: "addTime", bundle: nil)
var viewController = storyboard.instantiateViewController(withIdentifier: "addTimeVC") as! addTimeViewController
viewController.test = "TESTABCDEF"
passedValue = ("\(indexNumber)")
dismiss(animated: true, completion: nil)
}
I have a property test in my firstViewController. What is here wrong?
I've also tried with delegates and closures but without success. Please help me.
Try this instead:
let indexNumber = "\(indexPath.row)"
let indexPath = tableView.indexPathForSelectedRow
let currentCell = tableView.cellForRow(at: indexPath!) as UITableViewCell!
let viewController = navigationController!.presentingViewController as! addTimeViewController
viewController.test = "TESTABCDEF"
passedValue = ("\(indexNumber)")
navigationController!.dismiss(animated: true, completion: nil)
When you present a view controller modally using the present(_:animated) method, the view controller that was presented has the presentingViewController property set to the view controller that presented it. In other words, this property contains a reference to the previous view controller.

Passing data from a tableview to webview

I am new of the swift3. So, please forgive me if you think it is easy question. Do not have a clear idea when searching internet or stack overflow with my situation, so I ask this question.
Goal: Passing data from a tableview to webview
Example: data 1,2,3... in the table, press 1, then jump into webview with value 1
Information:
In main.storyboard, looks like:
class oneViewController for a view controller with tableview
class twoViewController for a view controller with webview
In oneViewController, things are well set and select row at:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//Array[indexPath.row] //This value expected to pass
//some code to execute passing data...
//Also, jump into another view controller with webview
}
In twoViewController, everything got ready:
//let passData = some code to get the data....
let URL = NSURL(string: "https://www.example.com?data=\(passData)")
webView.loadRequest(NSURLRequest(url: URL! as URL) as URLRequest)
Finally, PHP can get the value
echo $_GET["data"];
Questions:
How to set the relationship between tableview and webview in main.storyblard?
Connect view controller to anther view controller? Or connect Table view Cell to view controller? Or something else.....
How to implement passing data in class oneViewController and twoViewController?
Follow the below steps:-
Step 1: Below code will launch and pass the data in your TwoViewController. Please note that in your Main.Storyboard->TwoViewContoller, give the identifier as TwoViewController
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let storyBoard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let twoVC:TwoViewController = storyBoard.instantiateViewController(withIdentifier: "TwoViewController") as! TwoViewController
twoVC.passData = Array[indexPath.row]
self.present(twoVC, animated: true, completion: nil)
}
Step 2: In your TwoViewController class define a variable as below
var passData: String = ""
you can do three solutions :
1- send data in segue
2- forget the segue relation and call the new controller in didSelectRowAt, and set data like this :
let vc = UIStoryboard(name: "BarcodeScanner", bundle: nil).instantiateInitialViewController()! as! BarcodeScannerViewController
vc.passData = valueWantToSend
self.presentViewController(vc, animated: true, completion: nil)
3- use struct like this and you be able to use your data from any place in your project :
struct Variables
{
static var value = false
static var passData = ""
}
for exemple : Variables.passData=#"new value"

Create and perform segue without storyboards

i got an app without storyboards, all UI creation is made in code and I got a splitView which I would make it usable on iPhone, because as the app as been first designed for iPad only, so that when you select a row in the list in the Master view it does nothing on iPhone but is working fine on iPad.
So my question is can I create and perform the segue that allows to show the Detail View on the didSelectRowAtIndexPath method ?
Here's what i've done so far :
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let segue = UIStoryboardSegue(identifier: "test", source: self, destination: detailViewController!)
performSegueWithIdentifier("test", sender: self)
}
but when running and selecting a row the app was crashing telling it needed a performhandler so i added this :
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let segue = UIStoryboardSegue(identifier: "test", source: self, destination: detailViewController!, performHandler: { () -> Void in
let object = self.fetchedResultsController.objectAtIndexPath(indexPath)
let controller = self.detailViewController!
controller.detailItem = object
controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem()
controller.navigationItem.leftItemsSupplementBackButton = true
})
performSegueWithIdentifier("test", sender: self)
}
and now when selecting a row xcode says that there is no segue with such identifier "test".
I also tried to call it by segue.perform() and add the performHandler content into the prepareForSegueMethod :
if segue.identifier == "test" {
if let indexPath = self.tableView.indexPathForSelectedRow {
let object = self.fetchedResultsController.objectAtIndexPath(indexPath)
let controller = (segue.destinationViewController as! UINavigationController).topViewController as! DetailViewController
controller.detailItem = object
controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem()
controller.navigationItem.leftItemsSupplementBackButton = true
}
}
and it does just nothing, doesn't crash, just highlight the row i selected and that's all
Can you guys help me ?
EDIT : As Oleg Gordiichuk said, it's not possible to do what I want to do without Storyboards, so thanks for his help :)
Segue it is component of the storyboard interaction it is possible to understand from name of the class UIStoryboardSegue. It is bad idea to create segues programmatically. If i am not making mistake storyboard creates them for you.
For solving of you're issue try to use some common ways like simply present ViewController.
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("id") as! MyController
self.presentViewController(vc, animated: true, completion: nil)
As i understand from our conversation in comments. You would like to create navigation for tableview to details view using segues without storyboard. For now it is impossible to do this without storyboard.
For future learning try to investigate this information.
One way is to use the didSelectRow method for tableView
Swift 3.x
// MARK: - Navigation & Pass Data
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Selected Row \(indexPath.row)")
let nextVC = YourNextViewController()
nextVC.YourLabel.text = "Passed Text"
nextVC.YourLabel.text = YourArray[indexPath.row]
// Push to next view
navigationController?.pushViewController(nextVC, animated: true)
}

Resources