Target Action to UIButton of nib not working in parentViewConteroller - swift

I am trying to add targetAction to my UIButton of my subView.
Here is how I add UINib to my parentViewController.
let myView = UINib(nibName: "myNibName", bundle: .main).instantiate(withOwner: nil, options: nil).first as! CarTypeCollectionCell
myView.setData(param, secondParam)
self.mainView.addSubview(myView)
myView.button.addTarget(self, action: #selector(onClickBtn(_:)), for: .touchUpInside)
And here is my onClickBtn function.
#objc func onClickBtn(_ sender: UIButton) {
print("this is clicked")
}
But the button action is not working. I set all of my button and view isUserInteractionEnabled to true.
When I tried with UITapGesture to myNibView, its working pretty well. But not with in that button addTarget case.
Is there something I am missing?

Related

Open swiftUI view from UIKit code for rightBarItem

This is code of UIKit File.I want to open view which is editButtonCustomizeView and written in swiftUI. How can I take action of this button which navigates to swiftUI
override func viewDidLoad() { super.viewDidLoad()
let editButton = UIBarButtonItem(image: editImage, style: .Plain,
target: self, action: editButtonCustomizeView())
}
Right now getting error is "Cannot convert value of type 'editButtonCustomizeView' to expected argument type 'Selector?' "
That is because the action expects a selector to point to what action is to be called when the button is tapped so you can't pass a view.
If you want to show a SwiftUI view when that button is tapped you have to first add a action to show the viewcontroller, then create the action to show the viewcontroller and lastly add you SwiftUI view in a viewcontroller so it can be used in UIKit.
Adding the action to the button:
let editButton = UIBarButtonItem(image: editImage, style: .Plain, target: self, action: #selector(showSwiftUIView))
Then the action to show the view:
#objc func showSwiftUIView(sender: UIControl) {
let vc = editButtonCustomizeVC()
present(vc, animated: true)
}
And lastly turn your view to a ViewController:
final class editButtonCustomizeVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let childView = UIHostingController(rootView: editButtonCustomizeView())
addChild(childView)
childView.view.frame = view.bounds
view.addSubview(childView.view)
childView.didMove(toParent: self)
}
}

How do I call an interstitial ad to load on another UIViewController?

I have a UIViewController with a UIView displayed on it; pressing a button on the UIView loads my interstitial ad. When the UIView is subsequently displayed, I want the interstitial to be displayed with the rootVC as the UIViewController.
However, this code does not seem to work as intended:
1) My View Controller:
class MyViewController: UIViewController {
let button: UIButton = {
let btn = UIButton()
btn.translatesAutoresizingMaskIntoConstraints = false
btn.setTitle("BUTTON", for: .normal)
btn.addTarget(self, action: #selector(showUIView), for: .touchUpInside)
return btn
}()
#objc func showUIView(_ sender: UIButton) {
let popUp = MyUIView()
self.view.addSubview(popUp)
}
2) My UIView:
class MyUIView: UIView {
var interstitial: GADInterstitial!
let button: UIButton = {
let btn = UIButton()
btn.translatesAutoresizingMaskIntoConstraints = false
btn.setTitle("UIVIEW BUTTON", for: .normal)
btn.addTarget(self, action: #selector(prepareInterstitial), for: .touchUpInside)
return btn
}()
#objc func prepareInterstitial(_ sender: UIButton) {
interstitial = GADInterstitial(adUnitID: "ca-app-pub-3940256099942544/4411468910")
let request = GADRequest()
interstitial.load(request)
dismissPopUp()
if interstitial.isReady {
interstitial.present(fromRootViewController: MyViewController())
}
}
I get this in the console:
Warning: Attempt to present <GADFullScreenAdViewController: 0x7f8611e22fc0> on <Project.MyViewController: 0x7f8612884800> whose view is not in the window hierarchy!`
which I do not understand because MyViewController is still very much a part of the view hierarchy.
I'd be really grateful if someone could show me how to fix this error, I'm relatively new to coding and not sure what I am doing wrong. Thank you!
The reason why this doesn't work is because you are creating a brand new VC here:
interstitial.present(fromRootViewController: MyViewController())
This MyViewController() is not the VC that is shown on the screen! You just created by calling its initialiser.
You need to somehow get the VC that's shown on the screen. One simple way to do this is to add a rootVC property to your MyUIView:
weak var rootVC: UIViewController?
And then present this instead:
if let rootVC = self.rootVC { // nil check!
interstitial.present(fromRootViewController: rootVC)
}
In showUIView, set self as rootVC:
#objc func showUIView(_ sender: UIButton) {
let popUp = MyUIView()
popUp.rootVC = self
self.view.addSubview(popUp)
}

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

swift present controller with a back button to get back to last screen

I am presenting a UICollectionViewController but it just ends up as a controller with no back buttons to get back to the last controller or the home controller, how would i add a back button? or what other options do i have?
class UserProfileController: UICollectionViewController, UICollectionViewDelegateFlowLayout, UserProfileHeaderDelegate, ProfileHeaderClosedDelegate {
func presentFRC() {
let PE = FriendsRequestsController(collectionViewLayout:
UICollectionViewFlowLayout())
let NPE = UINavigationController(rootViewController: PE)
self.present(NPE, animated: true, completion: nil)
}
}
Add the following code in the view did load of the view controller you are presenting.
override func viewDidLoad() {
super.viewDidLoad()
var backbutton = UIButton(type: .Custom)
backbutton.setImage(UIImage(named: "BackButton.png"), forState: .Normal)
backbutton.setTitle("Back", forState: .Normal)
backbutton.setTitleColor(backbutton.tintColor, forState: .Normal) // You can change the TitleColor
backbutton.addTarget(self, action: "backAction", forControlEvents: .TouchUpInside)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backbutton)
}
func backAction() -> Void {
self.navigationController?.popViewControllerAnimated(true)
}
You have two options:
Embed your view controllers into UINavigationController and use UINavigationBar and segues for navigation. The easiest way to build such a system would be through storyboard though. But you can do that programmatically as well, but it would be a lot more work.
Add your own back button programmatically the way #ZahurafzalMirza has shown you. Since you are not using UINavigationController, your navigationController will be nil. So the action should look like this
func backAction() -> Void {
self.dismiss(animated: true)
}

Calling a NavigationController (to push another view controller) from a CollectionViewCell

Here is what I'm trying to do.
class UserProfileHeader: UICollectionViewCell {
lazy var button: UIButton = {
let button = UIButton(type: .system)
//...
button.addTarget(self, action: #selector(handleButtonTapped), for: touchUpInside)
return button
}()
func handleButtonTapped() {
print("action working now")
// How to push another vc here?
}
// ...
}
I want to call a navigationController to push(show) another ViewController here in the collectionViewCell. How can I access there? I tried, not worked. Is it because of MVC pattern? Cell can't talk with others? Or is there any ways to make it? like using Delegate/Protocol? I don't know much about those things.
Create one custom delegate and set to its viewcontroller and then when you tap on collectionview cell button called that delegate method and it will invoke inside your viewcontroller there you can push the view controller
func handleButtonTapped() {
//Your delegate method showuld be invoked here
delegate?.buttontappFromCollectionViewCell()
}
//Now inside your view controller
func buttontappFromCollectionViewCell() {
let vc = UIStoryboard(name: "storyboardName", bundle: nil).instantiateViewController(withIdentifier: "yourViewControllerIdentifier")
let navigationController = UINavigationController(rootViewController: vc)
navigationController.pushViewController(vc, animated: true)
}