Search code examples
iosswift

How to use a function outside of the class?


I want to use this code:

var buttonNumber = 0

func settings() {
    CNavigationViewController().contextMenu()
}

class CNavigationViewController: UINavigationController {

...

@objc func rightbuttonAction(sender: UIButton!) {
    buttonNumber = sender.tag
    settings()
}

func contextMenu() {
    
    print(buttonNumber)
    
    if pressed == true { pressed = false
        
        child.willMove(toParentViewController: nil)
        child.view.removeFromSuperview()
        child.removeFromParentViewController()
        visualEffectView.removeFromSuperview()
        
        for index in 1...rightBarButtonsCount {
            if index == buttonNumber { continue }
            rightStackView.arrangedSubviews[index-1].alpha = 1
        }
        
    } else { pressed = true
        
        visualEffectView.frame = UIScreen.main.bounds
        navigationView.addSubview(visualEffectView)
        navigationView.sendSubview(toBack: visualEffectView)
        addChildViewController(child)
        
        guard let childView = child.view else { fatalError("error") }
        view.addSubview(childView)
        child.didMove(toParentViewController: self)
            
        childView.translatesAutoresizingMaskIntoConstraints = false
        childView.topAnchor.constraint(equalTo: rightStackView.arrangedSubviews[buttonNumber-1].topAnchor, constant: rightStackView.arrangedSubviews[buttonNumber-1].frame.size.height + 8).isActive = true
        childView.trailingAnchor.constraint(equalTo: rightStackView.arrangedSubviews[buttonNumber-1].trailingAnchor).isActive = true
        
        for index in 1...rightBarButtonsCount {
            if index == buttonNumber { continue }
            rightStackView.arrangedSubviews[index-1].alpha = 0
        }
    }
}
}

but in this case code doesn't work. I can't see my context menu(child) view. But the code will work if I do this:

@objc func rightbuttonAction(sender: SLButton!) {
    buttonNumber = sender.tag
    contextMenu() // instead settings()
}

Why I can't see the child view? How to use first way of code and function outside of the class?

Update:

I have this code to start app:

SceneDelegate

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    if let windowScene = (scene as? UIWindowScene) {
        let window = UIWindow(windowScene: windowScene)
        window.rootViewController = CLoadingViewController()
        self.window = window
        window.makeKeyAndVisible()
    }
}

CLoadingViewController

class CLoadingViewController: UIViewController {

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    mainScreen()
}

func mainScreen() {
    let navigationView = CNavigationViewController()
    let mainView = CStoreViewController()
    navigationView.navigationBar.frame.size = navigationView.navigationBar.sizeThatFits(CGSize(width: navigationView.navigationBar.frame.size.width, height: 2))
    navigationView.viewControllers = [mainView]
    present(navigationView, animated: false, completion: nil)
}

}


Solution

  • Why I can't see the child view

    The reason is that CNavigationViewController(), used in your settings function, is not the same as your actual CNavigationViewController already in use in your interface. It creates a view controller, which is new and different from the view controller you're looking for.

    You would need to work out a way to get a reference to the actual view controller already in use in your interface. (For example, it might be your app's key window's root view controller. But then again it might not; you haven't provided enough info about that.)

    Best of all, though, would be: don't do that. There should never be a reason for using a global function, and certainly not one that tries to refer to a view controller. It's a Bad Smell. And since, in the only call shown, you don't need it (as you've already shown), you should just delete it. It was a bad idea to start with. If the goal is to make some sort of shortcut, why not just put settings inside the view controller's code, as a method of the view controller, and refer to the view controller as self?