i want to triger navigationcontroller when i press button in UIView class - ios

I want to trigger Navigation controller to some other screen when i press the button in UIView class. How can i do this?
//Code for UIView Class in Which Button Iboutlet is created
import UIKit
protocol ButtonDelegate: class {
func buttonTapped()
}
class SlidesVC: UIView {
var delegate: ButtonDelegate?
#IBAction func onClickFinish(_ sender: UIButton) {
delegate?.buttonTapped()
}
#IBOutlet weak var imgProfile: UIImageView!
}
//ViewController Class code in Which Button Protocol will be entertained
class SwipingMenuVC: BaseVC, UIScrollViewDelegate {
var slidesVC = SlidesVC()
override func viewDidLoad() {
super.viewDidLoad()
slidesVC = SlidesVC()
// add as subview, setup constraints etc
slidesVC.delegate = self
}
extension BaseVC: ButtonDelegate {
func buttonTapped() {
self.navigationController?.pushViewController(SettingsVC.settingsVC(),
animated: true)
}
}

A more easy way is to use typealias. You have to write code in 2 places. 1. your viewClass and 2. in your View Controller.
in your SlidesView class add a typealias and define param type if you need otherwise leave it empty.
class SlidesView: UIView {
typealias OnTapInviteContact = () -> Void
var onTapinviteContact: OnTapInviteContact?
#IBAction func buttonWasTapped(_ sender: UIButton) {
if self.onTapinviteContact != nil {
self.onTapinviteContact()
}
}
}
class SwipingMenuVC: BaseVC, UIScrollViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let slidesView = SlidesView()
slidesView.onTapinviteContact = { () in
// do whatever you want to do on button tap
}
}

You can use the delegate pattern to tell the containing ViewController that the button was pressed and let it handle whatever is needed to do next, The view doesn't really need to know what happens.
A basic example:
protocol ButtonDelegate: class {
func buttonTapped()
}
class SomeView: UIView {
var delegate: ButtonDelegate?
#IBAction func buttonWasTapped(_ sender: UIButton) {
delegate?.buttonTapped()
}
}
class ViewController: UIViewController {
var someView: SomeView
override func viewDidLoad() {
someView = SomeView()
// add as subview, setup constraints etc
someView.delegate = self
}
}
extension ViewController: ButtonDelegate {
func buttonTapped() {
self.showSomeOtherViewController()
// or
let vc = NewViewController()
present(vc, animated: true)
}
}

Related

Function not getting called with protocol delegate and view controller swift

I needed to delegate an click action for my UIView class to my UIViewController class since swift does not support multiple class inheritance. So i wanted it such that once a button is clicked on my subview, a function in my ViewController class is called. Am using protocol delegate to achieve this but on the click of my button it does not work for me as the function does not get called. Please help me out. Code snippet would be largely appreciated.
ViewController
var categoryItem: CategoryItem! = CategoryItem() //Category Item
private func setupExplore() {
//assign delegate of category item to controller
self.categoryItem.delegate = self
}
//function to be called
extension BrowseViewController: ExploreDelegate {
func categoryClicked(category: ProductCategory) {
print("clicked")
let categoryView = ProductByCategoryView()
categoryView.category = category
categoryView.modalPresentationStyle = .overCurrentContext
self.navigationController?.pushViewController(categoryView, animated: true)
}
}
Explore.swift (subview)
import UIKit
protocol ExploreDelegate:UIViewController {
func categoryClicked(category: ProductCategory)
}
class Explore: UIView {
var delegate: ExploreDelegate?
class CategoryItem: UIView {
var delegate: ExploreDelegate?
var category: ProductCategory? {
didSet {
self.configure()
}
}
var tapped: ((_ category: ProductCategory?) -> Void)?
func configure() {
self.layer.cornerRadius = 6
self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.categoryTapped)))
self.layoutIfNeeded()
}
#objc func categoryTapped(_ sender: UIGestureRecognizer) {
delegate?.categoryClicked(category: ProductCategory.everything)
self.tapped?(self.category)
}
}

Call function from child to parent in Swift

I am using xlpagertabstrip and I have a parent view controller which has two children (child1, child2).
In my parent view controller, I show a UIActivityViewIndicator but I want to know how to hide that indicator in my child1.
This is my code:
ParentViewController:
override func viewDidLoad() {
showActivityIndicator()
super.viewDidLoad()
}
func showActivityIndicator() {
//code related to titleview
navigationItem.titleView = titleView
}
func hideActivityIndicator() {
navigationItem.titleView = nil
}
Child1ViewController:
override func viewDidLoad() {
super.viewDidLoad()
call_api()
}
func call_api(){
//code related to api
//if api is ok, I call hideActivityIndicator()
let pctrl = ParentViewController()
pctrl.hideActivityIndicator()
}
But that code does not work. How can I solve that?
Just pass hideActivityIndicator() from the parent to the child and call it when necessary. So whenever you create your child controller do this:
// Parent Controller
childVC.someMethodFromParent = hideActivityIndicator
And in your ChildController do this:
// Child Controller
internal var someProperty: (() -> Void)!
override func viewDidLoad() {
super.viewDidLoad()
call_api()
}
func call_api(){
//code related to api
//if api is ok, I call hideActivityIndicator()
someMethodFromParent()
}
This should work
How about having a ChildViewControllerDelegate? Something like:
class ParentViewController {
func someFunc(){
...
childVC.delegate = self
...
}
}
extension ParentViewController: ChildViewControllerDelegate {
func childViewControllerDidFinishApiCall() {
hideActivityIndicator()
}
}
protocol ChildViewControllerDelegate: class {
func childViewControllerDidFinishApiCall()
}
class ChildViewController {
weak var delegate: ChildViewControllerDelegate?
func call_api(){
//code related to api
let pctrl = ParentViewController()
delegate?.childViewControllerDidFinishApiCall()
}
}

Click on the addsubview event button

I have a button in a subview called UIViewControllerB. Someone who taught me how to capture click event in UIViewControllerB will add a new view to UIView in UIViewcontroller A under string as my code.
This is the button in ViewControllerB displayed in UIView in UIViewController A
#IBAction func button_complate(sender: AnyObject) {
NSLog("aaa", "bbb")
}
Here is the UIViewControllerA containing UIView
#IBOutlet weak var addview: UIView!
override func viewDidLoad() {
super.viewDidLoad()
}
try code:
class UIViewControllerA: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
func addView(/*param */) {
// do something
}
// when push to UIViewControllerB set install for viewcontrollerA
private func goToScreenB(){
let viewB = UIViewControllerB()
viewB.viewcontrollerA = self
self.navigationController?.pushViewController(viewB, animated: true)
}
}
class UIViewControllerB: UIViewController {
// In UIViewControllerB create a install of UIViewControllerA
var viewcontrollerA : UIViewControllerA?
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func button_complate(sender: AnyObject) {
self.viewcontrollerA?.addView()
}
}

Delegate not executing after call swift

I have a viewController with another containerView insider set up to appear temporarily (added programmatically). The containerView is a sort of operation bar, which allows you to change values of the viewController. The protocol called from an IBAction of a button however, does not call the protocol set up inside the viewController class.
Here is the code from both classes:
class viewController: UIViewController, updateListDelegate {
let dataSource = containerView()
override func viewDidLoad() {
super.viewDidLoad()
dataSource.delegate = self
}
func updateList(sender: containerView) {
print("is called") //is not printed
}
}
The code from the containerView:
protocol updateListDelegate {
func updateList(containerView)
}
class containerView: UIViewController {
var delegate: updateListDelegate?
#IBAction func AddSong(_ sender: UIButton) {
self.delegate?.updateList(sender: self)
}
}
If this method is only to be called from one object, then, in my opinion, I would not define a protocol. If multiple objects are to call this method, then I would define a protocol. This is typically how you would call a method backwards, using a basic delegate.
class ViewController: UIViewController {
let container = ContainerView()
override func viewDidLoad() {
super.viewDidLoad()
container.viewControllerDelegate = self
// push to this instance of container at some point
}
func doSomething() {
print("great success")
}
}
class ContainerView: UIViewController {
weak var viewControllerDelegate: ViewController?
#objc func someAction() {
if let viewControllerDelegate = viewControllerDelegate {
viewControllerDelegate.doSomething()
}
}
}
// prints "great success" when someAction() called
One of the most common mistakes people make is not keeping track of instances. For delegates to work, you must be sure you are using the specific instances that you've instantiated and assigned those delegates to.

Hide a view container with a button in the ViewContainer

I have a View. In this view, I have a Container View. And in the ContainerView I have a button.
When I am touching the button of the ContainerView, I want the ContainerView become hidden.
I want to do something like that :
class ContainerView: UIViewController {
#IBAction func closeContainerViewButton(sender: AnyObject) {
//I try this : self.hidden = false
//or this : self.setVisibility(self.INVISIBLE)
}
}
Any idea how do it?
There are serval ways but here is the easiest one, not prettiest though. You should really use delegates but this is a hacky way to get started. Just create a global variable of the class that holds the container (startController in this case). Then call it from your other view controller (MyViewInsideContainer) and tell it to hide the view you´re in. I have not run this code but it should work.
var startController = StartController()
class StartController:UIViewController {
#IBOutlet var myViewInsideContainerView: UIView
....
override func viewDidLoad() {
super.viewDidLoad()
startController = self
}
func hideContainerView(){
self.myContainerView.hidden = true
}
}
class MyViewInsideContainer:UIViewController {
...
#IBAction func hideThisView(sender: AnyObject) {
startController.hideContainerView()
}
}
i think a cleaner solution is to use delegation:
in the ParentViewController
class ParentViewController: UIViewController ,ContainerDelegateProtocol
{
#IBOutlet weak var containerView: UIView!
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
//check here for the right segue by name
(segue.destinationViewController as ContainerViewController).delegate = self;
}
func Close() {
containerView.hidden = true;
}
in the ContainerViewController
protocol ContainerDelegateProtocol
{
func Close()
}
class ContainerViewController: UIViewController {
var delegate:AddTaskDelegateProtocol?
#IBAction func Close(sender: AnyObject) { //connect this to the button
delegate?.CloseThisShit()
}

Resources