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

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().

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)
}
}

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

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)
}

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

How can I call an action through UIButton variable

I have a UIButton in a prototype UItableviewcell that is made in a nib.
The UITableView is inside a UIViewController.
The requirement is: When I press the UIButton, a segue should be performed from Main UIViewController to another second UIViewController . I can access the UIButton IBOutlet from the table , so is there any way to call a function through that UIButton Variable.
// for reference
let x= cell.followButton;
Add a target to the button to call a method in your view controller. In this code, self is your view controller.
cell.followButton.addTarget(self, action: #selector(buttonPressed), forControlEvents: .TouchUpInside)
Then implement buttonPressed to handle segueing.
func buttonPressed() {
performSegueWithIdentifier("Identifier", sender: self)
}

Show viewController swift

I have a tableView and i made its cells custom and added a UIButton to the cell
i want when i press the button to popOver a new ViewController and in it the text in the cell i clicked the button in it. I don't want to use didSelectRowAtIndexPath func, i want to use the event of the button in each cell.
I tried to connect the button with the new viewController using popOver segue but the build fails because it is dynamic.
Please help and make the answer in swift.
Thanks in advance
You shouls set target to button inside the cell in cellForRowAtIndexPath function
cell.button.addTarget(self, action: "showPopupPage:", forControlEvents: UIControlEvents.TouchUpInside)
create a function
func showPopupPage(sender: UIButton) {
let view = button.superview!
let cell = view.superview as! custom cell
// you can get cell contents here
// call your popupview pass the value
}
Example=>
Swift - UIPopoverController in iOS 8

Resources