Goto ViewController From UICollectionViewCell Class Swift - swift

How can I go to a UIViewController from my UICollectionViewCell Class?
Here is my UICollectionViewCell Class :
class GalleryItemCollectionViewCell: UICollectionViewCell,UIAlertViewDelegate
{
#IBAction func gotoView(sender: AnyObject)
{
//I Want To Do It HERE...
}
}

self..window.rootViewController.performSegueWithIdentifier("nameOfSegueInStoryboard", sender: self)
This will transition to a view controller of your choice. To change variables in that view controller, you can use the prepareForSegue method under the view controller that contains the collection view:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "nameOfSegueInStoryboard" {
let controller = segue.destinationViewController as! NameOfYourViewController
controller.variable_name = new_value
}
}
This all relies on you adding a segue from your first view controller to the other and giving it an identifier in your storyboard.

You will need to add a seguey to the storyboard then trigger it programmatically:
self.window.rootViewController.performSegueWithIdentifier("goToViewSeguey", sender: self)

Related

Segueing from Child ViewController

I have a situation where I am presenting a child view controller "B" onto another view controller "A". View controller "B" has 5 buttons which segue(push) to a third view controller, "C". The problem is once I'm at view controller "C", I want to be able to use an unwind segue to go from C-->A without B showing up in the middle.
// view controller A class
class AViewController: UIViewController {
#IBAction func goToViewControllerB(_ sender: UIButton) {
let viewControllerB = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "viewControllerB_ID") as! BViewController
self.addChild(viewControllerB)
viewControllerB.view.frame = self.view.frame
self.view.addSubview(viewControllerB.view)
viewControllerB.didMove(toParent: self)
}
#IBAction func unwindToStart(segue: UIStoryboardSegue) {
print("back from view controller C!")
}
}
//view controller B class
class BViewController: UIViewController {
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let identifier = segue.identifier {
switch identifier {
case "segueFromBToC_1":
if let destVC = segue.destination as? CViewController {
//pass data
}
// ... cases 2-4
case "segueFromBToC_5":
if let destVC = segue.destination as? CViewController {
//pass data
}
default: break
}
}
}
}
// empty CViewController class
I know that putting the following code in my view controller B class will remove it from the parent view controller, "A", but then I can't segue from "B" to "C" anymore as "B" doesn't exist.
self.view.removeFromSuperview()
self.removeFromParent()
self.willMove(toParent: nil)
I was wondering where I should put the above code or if I should segue from a child view controller at all? I also haven't used navigation controllers as I don't know how to implement them with a child view controller. Should I have #IBAction outlets for each of the 5 buttons and put the above code in there?
UPDATE: I was able to fix it by detaching the 5 push segues from the buttons and have each of the 5 push segues go directly from view controller B to view controller C . I then had an #IBAction for each button where I had the following code in view controller B:
class BViewController: UIViewController {
#IBAction func button1ToVC3(_ sender: UIButton) {
segueAndRemoveSelf(segueName: "segueFromBToC_1")
}
#IBAction func button2ToVC3(_ sender: UIButton) {
segueAndRemoveSelf(segueName: "segueFromBToC_2")
}
#IBAction func button3ToVC3(_ sender: UIButton) {
segueAndRemoveSelf(segueName: "segueFromBToC_3")
}
#IBAction func button4ToVC3(_ sender: UIButton) {
segueAndRemoveSelf(segueName: "segueFromBToC_4")
}
#IBAction func button5ToVC3(_ sender: UIButton) {
segueAndRemoveSelf(segueName: "segueFromBToC_5")
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let identifier = segue.identifier {
switch identifier {
case "segueFromBToC_1":
if let destVC = segue.destination as? CViewController {
//pass data
}
// ... cases 2-4
case "segueFromBToC_5":
if let destVC = segue.destination as? CViewController {
//pass data
}
default: break
}
}
}
}
extension BViewController {
func segueAndRemoveSelf(segueName: String) {
self.performSegue(withIdentifier: segueName, sender: self)
self.view.removeFromSuperview()
self.removeFromParent()
self.willMove(toParent: nil)
}
}
Not sure if this is best practice though.

Passing variable in swift with segue

I'm using segue to open a new window in a xcode app.
The segue is correct, when I tap on the button the new window is shown.
I want to pass a string variable from FirstViewController to DetailViewController but I can't set the variable in the DetailViewController.
This is the code in FirstViewController:
if control == view.rightCalloutAccessoryView {
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let controller = segue.destination as! DetailViewController
controller.Name = "test"
}
performSegue(withIdentifier: "showdetail", sender: self)
}
And this the DetailViewController code
class DetailViewController: UIViewController, WKNavigationDelegate {
var Name: String = ""
override func viewDidLoad() {
super.viewDidLoad()
print(Name)
}
}
Where am I doing wrong?
The method prepare(for must be on the top level of the class.
And please name variables according to the guidelines with starting lowercase letter
func someMethod()
{
if control == view.rightCalloutAccessoryView {
performSegue(withIdentifier: "showdetail", sender: self)
}
}
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let controller = segue.destination as! DetailViewController
controller.name = "test"
}
}

Value not passing between viewControllers

Struggling to get my viewControllers to send value from the main viewController to a second. I want it to happen on a button click, I'm going to get the value from the button and pass it to the new form. But it just isn't working.
Code for main ViewController
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func butClick(_ sender: UIButton) {
NSLog("Button Pressed : %#",[sender .currentTitle])
//var tt = [sender .currentTitle]
// Create the view controller
let vc = TimesTablesViewController(nibName: "TimesTablesViewController", bundle: nil)
vc.passedValue = "xx"
self.performSegue(withIdentifier: "pushSegue", sender: nil)
}
}
Code for second viewController called TimesTablesViewController:
class TimesTablesViewController: UIViewController {
#IBOutlet weak var titleLabel: UILabel!
var passedValue:String = ""
override func viewDidLoad() {
super.viewDidLoad()
titleLabel?.text = "\(passedValue) Times Table"
}
}
I've followed tutorials but can't seem to solve the problem! Thanks for any help!
Replace
self.performSegue(withIdentifier: "pushSegue", sender: nil)
with
self.present(vc,animated:true,completion:nil)
or ( if the current vc is inside a naigation )
self.navigationController?.pushViewController(vc,animated:true)
Using
self.performSegue(withIdentifier: "pushSegue", sender: nil)
is fit with storyboards not xibs and if this your case then you need to use the above line only inside the button action with implementing this method inside the source vc
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "pushSegue" {
if let nextViewController = segue.destination as? TimesTablesViewController{
nextViewController.passedValue = "xx"
}
}
}
I’m assuming that the new view controller is appearing, but you’re simply not seeing the data. If so, you’re evidently using storyboards. The TimesTablesViewController(nibName:bundle:) only works if you’re using XIB/NIBs and manually presenting new view controller.
If you’re really using storyboards, simplify your butClick method:
#IBAction func butClick(_ sender: UIButton) {
NSLog("Button Pressed")
performSegue(withIdentifier: "pushSegue", sender: self)
}
But implement prepare(for:sender:):
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? TimesTablesViewController {
destination.passedValue = "xx"
}
}
Assuming the above fixes your problem, I might suggest a further simplification. Notably, if your butClick(_:) method is really only calling performSegue, you can segue to this next scene without any #IBAction method at all:
remove butClick(_:) entirely;
remove the connection between the button and the butClick method in IB, on the “Connections Inspector” tab in the right panel; and
control-drag from the button previously hooked up to butClick(_:) to the scene for TimesTablesViewController.
That will simplify your code further.

Accessing methods, actions and/or outlets from other controllers with swift

I'm working on a macOS project where I have a split view containing 2 other ViewControllers and I can't figure out how to access the ViewControllers from my primary window's ViewController.
this is the setup:
Basically what I'm trying to do is use the Button in my ViewController on the top-left to access the Label in my SectionController on the right, which is embedded in my split view.
Since I can't create an IBAction or IBOutlet for a control in a different ViewController, I can't figure out how to get these to be connected. My current workaround has been to have a property on my AppDelegate and then access the main shared application delegate, but that feels hacky and won't scale. I'm completely lost as to how to proceed. I'm ok with using a function to pass data or whatever to the other ViewController(s).
I'm using Swift 4 with Xcode 9 (beta).
Any ideas?
Of course you can't create IBAction or IBOutlet for a control in a different ViewController!!
But simply each view controller in the hierarchy has a reference for its child view controllers.
Method 1:
#IBAction func buttonTapped(_ sender: Any) {
let splitViewController = self.childViewControllers[0] as! YourSplitViewController
let targetViewController = splitViewController.childViewControllers[0] as! YourTargetViewController
targetViewController.label.text = "Whatever!"
}
Method 2:
It may be better if you took a reference for each child controller in your "prepare for segue" method
ContainerViewController:
var mySplitViewController: YourSplitViewController?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "splitViewSegue" {
self.mySplitViewController = segue.destination as! YourSplitViewController
}
}
YourSplitViewController:
var aViewController: YourFirstViewController?
var bViewController: YourSecondViewController?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "aViewSegue" {
self.aViewController = segue.destination as! YourFirstViewController
} else if segue.identifier == "bViewSegue" {
self.bViewController = segue.destination as! YourSecondViewController
}
}
So you can access it like that in your container view controller:
#IBAction func buttonTapped(_ sender: Any) {
self.mySplitViewController.firstViewController.label.text = "Whatever!"
}

Delegate using Container View in Swift

I'm developing an app for iPad Pro. In this app, containerView use to add additional views and interact with them.
First, I created a protocol:
protocol DataViewDelegate {
func setTouch(touch: Bool)
}
Then, I created my first view controller
import UIKit
class ViewController: UIViewController, DataViewDelegate {
#IBOutlet var container: UIView!
#IBOutlet var labelText: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
func setTouch(touch: Bool) {
if touch == true {
labelText.text = "Touch!"
}
}
}
And finally, I created a view that will be embedded in containerView.
import UIKit
class ContainerViewController: UIViewController {
var dataViewDelegate: DataViewDelegate?
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func touchMe(sender: AnyObject) {
dataViewDelegate?. setTouch(true)
}
}
But for some reason, nothing happened, the first view controller receives nothing in setTouch function.
My question is: In this case, using container, how can I make the communication between two ViewsControllers?
Like #nwales said you haven't yet set the delegate. You should do set the delegate in prepareForSegue function on your first viewController (who contain the viewContainer)
First select the embed segue and set an identifier in the attributes inspector.
Then in the parentViewController implement the func prepareForSegue like this:
Swift 4+:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "the identifier") {
let embedVC = segue.destination as! ViewController
embedVC.delegate = self
}
}
Below:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
if (segue.identifier == "the identifier") {
let embedVC = segue.destinationViewController as! ContainerViewController
embedVC.dataViewDelegate = self
}
}
Looks like you defined the delegate, but have not set the delegate. This happens to me all the time.