Unable to pass image between view controllers - swift

As asked on the question. On my first VC, I have set up a function that passes an image to another VC as follows.
#objc func imageTapped(tapGestureRecognizer1: UITapGestureRecognizer) {
let passimage = tapGestureRecognizer1.view as! UIImageView
let alertController = UIAlertController(title: "...", message: "...", preferredStyle: UIAlertController.Style.alert)
let ok = UIAlertAction(title: "...", style: UIAlertAction.Style.default, handler: {(action) -> Void in
self.performSegue(withIdentifier: "Shop", sender: self)
print("image tapped")
let sb = self.storyboard?.instantiateViewController(withIdentifier: "shopVC") as! shopVC
sb.loadimage = passimage.image
self.present(sb, animated: true, completion: nil)
})
alertController.addAction(ok)
alertController.addAction(UIAlertAction(title: "取消(留在此版面)", style: UIAlertAction.Style.cancel, handler: nil))
self.present(alertController, animated: true, completion: nil)
}
whilst on the other VC, I've set up an Image View which would read the image as shown here.
class shopVC: UIViewController {
#IBOutlet weak var clothimage: UIImageView!
var loadimage: UIImage?
override func viewDidLoad() {
clothimage.image = loadimage
super.viewDidLoad()
}
I know the "passimage.image" is what I want as it shows up in the debugging window - I can't seem to place it in the second VC.

for change ViewController you use two Option same Time, When used individually, each:
// optionOne
self.performSegue(withIdentifier: "Shop", sender: self)
print("image tapped")
// optionTwo
let sb = self.storyboard?.instantiateViewController(withIdentifier: "shopVC") as! shopVC
sb.loadimage = passimage.image
self.present(sb, animated: true, completion: nil)
if use Option One, you must override below function from firstVC and set image directly:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let vc = segue.destination as? shopVC {
vc.image = yourImage
}
}
and if you use present for show ShopVC nothing change code just comment performSegue function.
That means only the following code:
let sb = self.storyboard?.instantiateViewController(withIdentifier: "shopVC") as! shopVC
sb.loadimage = passimage.image
self.present(sb, animated: true, completion: nil)

Need to call super.viewDidLoad() first and then setting up clothimage

Related

While present navigation then presented viewcontroller bar button not coming, why in swift

my viewcontroller flow will be like below:
navigationcontroller -> logoutviewcontroller ->(present)
viewcontroller -> (present) logoutviewcontroller (bar button coming)
|
loginviewcontroller
|
(present) logoutviewcontroller (bar button not coming)
logoutVC code:
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "logout", style: .plain, target: self, action: #selector(handleLogout))
}
#objc func handleLogout(){
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ViewController") as! ViewController
self.present(vc, animated: true, completion: nil)
}
loginVC code: when presenting logoutVC coming but bar button not coming.. why
#IBAction func loginButn(_ sender: Any) {
guard let email = emailTf.text, let password = passwordTf.text
else {
print("form is not valid")
return
}
Auth.auth().signIn(withEmail: email, password: password, completion: { (user, error) in
if error != nil{
print("login adding error: \(String(describing: error))" as Any)
return
}
print("login sucessfully")
let vc = self.storyboard?.instantiateViewController(withIdentifier: "LogOutViewController") as! LogOutViewController
self.present(vc, animated: true, completion: nil)
})
}
please suggest here with code
If by bar button you mean the navigationController's navigationBar, you don't need to present the ViewController but you need to use
self.navigationController?.pushViewController(vc, animated: true)

Can you change view controllers without segue?

Basically i have a button that changes title, and if the button title is something i want the button to take the user to somewhere different to if the button title was something else
let act1 = act1ViewController()
let act2 = act2ViewController()
override func viewDidLoad() {
super.viewDidLoad()
self.buttonName.setTitle(self.text, for: .normal)
// Do any additional setup after loading the view.
}
#IBAction func buttonPressed(_ sender: UIButton) {
if text == "cheer up" {
self.present(act1, animated: true, completion: nil)
}
else if text == "yay" {
self.present(act2, animated: true, completion: nil)
}
}
Instantiate the ViewController depending on the if check, and present it:
let storyBoard: UIStoryboard = UIStoryboard(name: "MyStoryboard", bundle: nil)
let destinationVC = storyBoard.instantiateViewController(withIdentifier: "ViewControllerIdentifier") as! NewViewController
present(destinationVC, animated: true, completion: nil)
Just remember to set the Identificator in the Storyboard
If the 2 controllers that you want to show are,
class Act1ViewController: UIViewController {
//your code...
}
class Act2ViewController: UIViewController {
//your code...
}
You simply need to put a switch-case on buttonName's title and present the relevant controller act1 or act2. Create act1 and act2 using the storyboard.
#IBAction func buttonPressed(_ sender: UIButton) {
switch sender.titleLabel?.text {
case "cheer up":
if let act1 = self.storyboard?.instantiateViewController(withIdentifier: "Act1ViewController") as? Act1ViewController {
self.present(act1, animated: true, completion: nil)
}
case "yay":
if let act2 = self.storyboard?.instantiateViewController(withIdentifier: "Act2ViewController") as? Act2ViewController {
self.present(act2, animated: true, completion: nil)
}
default:
break
}
}
}
Don't forget to set Act1ViewController and Act2ViewController as storyboardID of the respective controllers in the storyboard.

How to programmatically add uibutton action?

I have created a button and I was wondering how do I programmatically code an action for the UIButton to take me to another view controller?
This is all I have so far:
let getStartedButton: UIButton = {
let getStartedButton = UIButton()
getStartedButton.backgroundColor = UIColor(red:0.24, green:0.51, blue:0.59, alpha:1.0)
getStartedButton.setTitle("Get Started", for: .normal)
getStartedButton.titleLabel?.font = UIFont(name: "Helvetica Bold", size: 18)
getStartedButton.translatesAutoresizingMaskIntoConstraints = false
getStartedButton.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
return getStartedButton
}()
#objc func buttonAction(sender: UIButton!) {
print("...")
}
If you want to make the transition to another ViewController after pressing the button, you can do this in 2 ways:
1) present(_:animated:completion:)
#objc func buttonAction(sender: UIButton!) {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "Main") as! SecondViewController
self.present(vc, animated: true, completion: nil)
}
2) pushViewController(_:animated:)
#objc func buttonAction(sender: UIButton!) {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "Main") as! SecondViewController
self.navigationController?.pushViewController(vc, animated: true)
}
There are 3 ways you can show a new View Controller:
Presenting View Controller:
#objc func buttonAction(sender: UIButton!) {
let destinationVC = self.storyboard?.instantiateViewController(withIdentifier: "DestinationViewController") as! DestinationViewController
self.present(destinationVC, animated: true, completion: nil)
}
Performing a Segue from Storyboard:
If you already have the View Controller you want to present in your Storyboard, and it has a segue from your origin VC to your destination VC, then you can add an identifier to the segue and do this...
#objc func buttonAction(sender: UIButton!) {
self.performSegue(withIdentifier: "MySegueIdentifier", sender: self)
}
Pushing View Controller onto Stack (this only works if your original VC is embedded in a Navigation Controller):
#objc func buttonAction(sender: UIButton!) {
let destinationVC = self.storyboard?.instantiateViewController(withIdentifier: "DestinationViewController") as! DestinationViewController
self.navigationController?.pushViewController(destinationVC, animated: true)
}

Storyboard or segue from ViewController to Tabbar Controller

I want to implement a segue / storyboard in a button FROM View Controller TO tab bar controller (Home) in swift 3
My storyboard
This is my sign in code
#IBAction func LogIn(_ sender: Any) {
if self.emailTextfield.text == "" || self.passwordTextfield.text == "" {
let alertController = UIAlertController(title: "Error", message: "Please enter an email and password.", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
} else {
FIRAuth.auth()?.signIn(withEmail: self.emailTextfield.text!, password: self.passwordTextfield.text!) { (user, error) in
if error == nil {
print("You have successfully logged in")
//this is my storyboard but it gives me black screen
let vc = self.storyboard?.instantiateViewController(withIdentifier: "Home")
self.present(vc!, animated: true, completion: nil)
} else {
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
}
}
}
I tried using storyboard
let vc = self.storyboard?.instantiateViewController(withIdentifier: "Home")
self.present(vc!, animated: true, completion: nil)
i tried using segue
self.performSegue(withIdentifier: "Home", sender: self)
both gives me black screen. why? I have a clarification also. where should i connect my segue, is it in the tab bar controller(grey) or to the first TAB controller?
Try Below step,
1) Create new function in AppDelegate class
func LoginNav()
{
self.window = UIWindow(frame: UIScreen.main.bounds)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let mainViewController = storyboard.instantiateViewControllerWithIdentifier("MainTab") as! tabbarControllerViewController // U have to create tabbarControllerViewController for ur TabBarView
self.window?.rootViewController = mainViewController
self.window?.makeKeyAndVisible()
}
2) Then call that func from any viewcontroller like below
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.LoginNav()

Segue and Button programmatically swift

I am using iCarousel and I have to create my own button. I want to pass data from the button made programmatically to another view, but I don't have a segue identifier because I created the button programmatically. I don't know if it is possible to create the identifier of the segue programmatically.
button.addTarget(self, action: #selector(buttonAction3), for: .touchUpInside)
button.setTitle("\(titulos[index])", for: .normal)
tempView.addSubview(button)
let myImage = UIImage(named: "modo4.png") as UIImage?
button.setImage(myImage, for: .normal)
let viewController:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "modo") as! Modo1ViewController
self.present(viewController, animated: false, completion: nil)
if segue.identifier == "" {
if let destination = segue.destination as? Modo1ViewController {
destination.nomb = nombres
}
}
Create seuge
Assign identifier
and your button target
#IBAction func button_clicked(_ sender: UIButton) {
self.performSegue(withIdentifier: "segueToNext", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segueToNext" {
if let destination = segue.destination as? Modo1ViewController {
destination.nomb = nombres // you can pass value to destination view controller
// destination.nomb = arrayNombers[(sender as! UIButton).tag] // Using button Tag
}
}
}
in your case, if you use self.present and you want to send data between views. Try this:
let viewController:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "modo") as! Modo1ViewController
viewController.nomb = nombres
self.present(viewController, animated: false, completion: nil)
I don't know how to set segue's identifier but I think code above can help
If you want do to easier work, you can create segue in IB (Interface Builder) and set it's identifier, then use
performSegue:withIdentifier:sender