Linking up a button through a segue when using material.io - ios

Im a beginner in swift and I am creating a login screen using Material.io in Swift and my UI looks like this .
However i dont see anything on my main.storyboard
I am used to creating a segue manually and then using
performSegue(withIdentifier: <#T##String#>, sender: <#T##Any?#>)
to use the segue but now since i dont see the button i'm unable to use the segue on clicking the 2 buttons Login and Register.
Also, usually from main.storyboard you have an IBOutlet or IBAction block to trigger certain features such as do something on a button click.
How does that work when you use MDCButton for instance. How do you link up the button to an action such as trigger a segue or update a text field.
Thank you.
I have declared my button like this
let nextButton: MDCButton = {
let nextButton = MDCButton()
let containerScheme = MDCContainerScheme()
nextButton.applyTextTheme(withScheme: containerScheme)
nextButton.setTitleColor(.white, for: .normal)
nextButton.translatesAutoresizingMaskIntoConstraints = false
nextButton.setTitle("CREATE NEW ACCOUNT", for: .normal)
nextButton.addTarget(self, action: #selector(didTapNext(sender:)), for: .touchUpInside)
return nextButton
}()
And i am calling it like this
#objc func didTapNext(sender: Any) {
self.performSegue(withIdentifier: "toRegistration", sender: self)
self.dismiss(animated: true, completion: nil)
}
I have a segue linking the 2 view controllers.

I can't see your code and don't have enough rep to comment, but it looks like you are building your view programmatically. To see when the button receives touchUp as you would from an outlet, you need to add a target. Try something like this:
func functionWhereYouCreateTheButton() { (PROBABLY YOUR VIEW DID LOAD)
let loginButton = UIButton()...
...
...
...
loginButton.addTarget(self, action: #selector(self.buttonTapped), for: .touchUpInside)
}
func buttonTapped() {
self.performSegue(withIdentifier: "SEGUEID", sender: self)
}

Related

Why back button is not working to return back from ViewController?

I am using SecondView programmatically. I click the button in ViewController to open SecondView controller, but now I want to back to ViewController from SecondView. I do not have storyboard in SecondView and I want to click the closeButton to go back to ViewController. My code work but when I click the close button it does not work. Any idea?
import UIKit
class SecondView: UIViewController {
var closeButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
closeButton.addTarget(self, action: #selector(dismissActionSheet), for: .touchUpInside)
}
#objc func dismissActionSheet() {
self.navigationController?.popViewController(animated: true)
}
}
You are instantiating a new UIButton, adding a target, but never adding the button to the UI. If you are seeing a button in your UI, it must be one that you added in Interface Builder, not the one you reference here. I suspect your intent was not:
var closeButton = UIButton()
but rather:
#IBOutlet var closeButton: UIButton!
… and hook that button’s outlet in IB.
Or better, rather than adding a target in viewDidLoad, hook up an #IBAction for the button directly in IB:
#IBAction func didTapButton(_ sender: Any) {
navigationController?.popViewController(animated: true)
}
You don't appear to need the closeButton outlet (at least for what you have shared with us thus far).
By the way, popViewController only works if this is embedded in a navigation controller. If you are not using a navigation controller (i.e., you “presented” the view controller rather than “pushing” one), the navigationController will be nil (and navigationController?.popViewController will do nothing). If not using navigation controller, call dismiss rather than popViewController.
If you have created the Second view programmatically:
Why not set a frame to the button and add it to self.view?
eg:
let button = UIButton(frame: CGRect(x: 50, y: 100, width: 80, height: 40))
button.setTitle("Pop VC", for: .normal)
button.addTarget(self, action: #selector(btnTouched), for: .touchUpInside)
self.view.addSubview(button)
then try to pop back:
func btnTouched(sender: UIButton!) {
if let navController = self.navigationController {
navController.popViewController(animated: true)
}
}

Two ViewControllers unwind issue

I have three View Controllers and want to go back from the third to the first on button click. I do the following:
Add the target to my button: doneButton.addTarget(self, action: #selector(ThirdViewController.doneButtonPressed(_:)), for: .touchUpInside)
Create the action in the first controller: #IBAction func unwindFromNewSubscription(segue: UIStoryboardSegue) {
}
Create the unwind segue linking it to the action from #2 in the storyboard and set the "chageFromNewToMain" identifier
Create the action for my button in the third controller: #IBAction func doneButtonPressed(_ sender:UIButton!) {
print("DONE BUTTON PRESSED")
performSegue(withIdentifier: "changeFromNewToMain", sender: self)
}
And it works, BUT when I tap the button in V3 it instantly disappears and I see the animation: V2 slides down, so finally I can see the V1. But I want to animate the V3 to slide down instead of disappearing to see V1 after that. Any ideas how to fix that?
(V1, V2, V3 - View Controller 1, 2, 3)
Try to use presentingViewController?.dismiss(animated: true, completion: nil) inside your #IBAction func doneButtonPressed(_ sender:UIButton!) action instead of calling performSegue(withIdentifier: "changeFromNewToMain", sender: self).

Swift 4 - How to activate segue programmatically from button nested in UICollectionViewCell

I am trying to activate a segue between a UICollectionView, subview of a UIViewController, and a separate ViewController (called RegisterController). The CollectionView is all set up programmatically, and there is a button on the last cell. However, I can't do the typical performSegue(_:withIdentfier) because the button is in the CollectionView. So, I have set up a method in the ViewController holding the CollectionView to performSegue(_:withIdentifier). I set up an instance in the CollectionViewController to call the method:
lazy var registerButton: UIButton = {
let btn = UIButton(type: .system)
btn.setTitle("Don't have an account?", for: .normal)
btn.setTitleColor(lighterOrange, for: .normal)
btn.addTarget(self, action: #selector(registerScreenAppear), for: .touchUpInside)
return btn
}()
#objc func registerScreenAppear(){
let vc: ViewController = ViewController()
_ = vc.toRegister()
}
The method in the ViewController is
func toRegister(){
performSegue(withIdentifier: "toRegister", sender: self)
}
I am getting the call stack:
NSInvalidArgumentException', reason: 'Receiver (<audible.ViewController: 0x7fe780724770>) has no segue with identifier 'toRegister''
I know I'm probably doing something completely wrong, but I've searched and searched and can't find a solution. Any help is appreciated, thanks
(Yes, I have configured the segue and gave it an identifier in the storyboard, but the reason I have to do this through code is because the CollectionView and the button are created programmatically, so I can't use the Interface Builder)
call performSegue in registerScreenAppear method or call self.toRegister() like
#objc func registerScreenAppear(){
self.toRegister()
}
OR
#objc func registerScreenAppear(){
performSegue(withIdentifier: "toRegister", sender: self)
}
Note: use later one as it will remove the extra function call i.e. toRegister().

UIButton setImage not Setting Image, button is Custom

In my code, I call a function to change the image of my custom UIButton from a blue button to a different colored one.
func changeButtonColor(_ colorChange: String, buttonToChange: UIButton) {
switch colorChange {
case "Blue": buttonToChange.setImage(#imageLiteral(resourceName: "blue-glossy-button-blank-hi"), for: .normal)
print("Blue")
case "Green": buttonToChange.setImage(#imageLiteral(resourceName: "asia2Greenadd"), for: .normal)
print("green")
case "Red": buttonToChange.setImage(#imageLiteral(resourceName: "asia2Redadd"), for: .normal)
case "Purple": buttonToChange.setImage(#imageLiteral(resourceName: "asia2add"), for: .normal)
default: print("Error")
}
print("hello")
greenButton1.setImage(#imageLiteral(resourceName: "asia2add"), for: .normal)
}
This function is in the View Controller that it wishes to modify.
Strangely, the "Blue" and the "Green" get printed when they should. And after it prints "Hello" I tried to set the button image again with its corresponding outlet, but when it returns to my view controller,all the buttons are the same images as before. Do I have to do this image setting in viewDidLoad? Am I missing a step for my view to be modified?
This is where I call changeButtonColor
class EditorViewController: UIViewController
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "Back" {
if let destinationVC = segue.destination as? ViewController {
destinationVC.tagColorPairings[button!] = colorToSendBack
delegate?.changeButtonColor(colorToSendBack, buttonToChange: (button)!)
}
}
}
RESOLVED
-I was having a button segue back to my root view controller which was pushing an un-updated VC onto the stack, when I really needed to use self.navigationController?.popToRootViewController

Perform unwind segue programmatically

Currently I have the following storyboard:
UITableViewController -> Segue -> UINavigationController -> Relationship -> UITableViewController
In the last UITableViewController I added a back button with the code below:
navigationItem.setLeftBarButtonItem(UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.Plain, target: self, action: "unwind"), animated: true)
let attributes = [NSFontAttributeName: UIFont.fontAwesomeOfSize(30), NSForegroundColorAttributeName: Constants.InterfaceColors.firstHighlightColor] as Dictionary!
let unwindNavigationItem = navigationItem.leftBarButtonItem! as UIBarButtonItem
unwindNavigationItem.setTitleTextAttributes(attributes, forState: .Normal)
unwindNavigationItem.title = String.fontAwesomeIconWithName(FontAwesome.AngleLeft)
As far as I read I have to connect the File's owner to the exit in the storyboard. I found out, that this is only possible if you have an action in your controller code like the one below.
#IBAction func unwindToWeekOverview(segue: UIStoryboardSegue) {
NSLog("unwind to week overview")
dismissViewControllerAnimated(true, completion: nil)
}
Since I don't now how to directly connect the action of a button to my unwind action I added the unwind function.
func unwind() {
performSegueWithIdentifier("UnwindToWeekOverview", sender: self)
}
When I now click the back button, the unwind function is called, but not the segue.
What am I missing?
Have a look at this link. It is by MIKE WOELMER and he explains it very clearly.
https://spin.atomicobject.com/2014/10/25/ios-unwind-segues/
So first of all, you need to create an IBAction in a destination view controller, something like this:
#IBAction func goBack(segue: UIStoryboardSegue) {
print("go back")
Then you just need to connect (control drag) from your button to Exit outlet. In the pop up you will see the function added previously, just select it and it should work.

Resources