Navigation Controller is not loading ( push , present ) another viewController - ios

I cannot load the viewController on clicking the button, knowing that the defined Vc holds a value of the VC that i want to present.
//AppDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let mainViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(identifier: "ViewController") as! ViewController
let navVC = UINavigationController.init(rootViewController: mainViewController)
self.window?.rootViewController = navVC
self.window?.makeKeyAndVisible()
return true
}
//ViewController Class
class ViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var collectionView: UICollectionView!
#IBOutlet weak var button: UIButton!
#IBOutlet weak var pageController: UIPageControl!
private let reuseIdentifier = /*"CollectionViewCell"*/ "Cell"
let collectionViewImages : [UIImage] = [#imageLiteral(resourceName: "cooov"), #imageLiteral(resourceName: "shutterstock535739452"), #imageLiteral(resourceName: "portraitYoungManLyingBedCheckingHisFeverThermometer232147948490")]
let collectionViewTexts : [String] = [
"Stay at home ! your health is our Priority",
"Access Latest Coronavirus articles !",
"Check up on your health on a daily basis !"
]
override func viewDidLoad() {
super.viewDidLoad()
renderButton()
renderCell()
pageController.numberOfPages = collectionViewImages.count
pageController.currentPage = 0
}
#IBAction func buttonClicked(_ sender: UIButton) {
let signupVC = UIStoryboard.init(name:"SignUp", bundle: nil).instantiateViewController(withIdentifier: "SignUp")
as! SignUp
self.navigationController?.pushViewController(signupVC, animated: true)
}
}
//SignUp class The VC that should appear on ButtonClick
class SignUp : BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
//the class that is inherited by ViewController
class BaseViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.isHidden = true
}
}
[enter image description here][1]}
enter image description here
here is a link to the pics provided please check.
https://drive.google.com/drive/folders/1CxysH911PIa3-S9Dx6EUV7DE8vlnEd4l?usp=sharing

Here is the function you can change it like this and let me know the outcome
first run this one
#IBAction func buttonClicked(_ sender: UIButton) {
let signupVC = UIStoryboard.init(name:"SignUp", bundle: nil).instantiateViewController(withIdentifier: "SignUp")
let navVC = UINavigationController.init(rootViewController: signupVC)
// self.present(navVC, animated: true, completion: nil)
if let nav = self.navigationController {
nav.pushViewController(navVC, animated: true)
} else {
print("navigation controller not found")
}
}
And then try to present ... and let me know what happened
#IBAction func buttonClicked(_ sender: UIButton) {
let signupVC = UIStoryboard.init(name:"SignUp", bundle: nil).instantiateViewController(withIdentifier: "SignUp")
let navVC = UINavigationController.init(rootViewController: signupVC)
self.present(navVC, animated: true, completion: nil)
}

You don't need new UINavigation controller to push.
#IBAction func buttonClicked(_ sender: UIButton) {
let signupVC = UIStoryboard.init(name:"SignUp", bundle: nil).instantiateViewController(withIdentifier: "SignUp")
as! SignUp
self.navigationController?.pushViewController(signupVC, animated: true)
}
Also if you are working with iOS 13.0+ and using Xcode 11+, your
SceneDelegate will be called instead of AppDelegate. So try copying the paste to SceneDelegate as well.

Related

Save actions on previous ViewController

I have my main screen with only one button on it "Show next screen". When the second screen(VC) pops up it has 2 buttons (go back and toSelect button).
My goal is to when I show my second screen and select a button on it then go back to first. The button on my second screen will stay selected. How can I do that?
So basically I need to save my actions on the second screen so if I go back to it it will show everything I did.
What is the best way to do it?
Storyboard
The easiest way to achieve this using Delegate and protocol.
you should listen and save the changes of SecondViewController at FirstViewController using delegate methods.
And when you are presenting the secondViewController you will share the saved changes to secondViewController so that button can be selected on behalf of that information
Code -
class FirstViewController: UIViewController {
//secondViewController States
private var isButtonSelected = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func gotoSecondVCAction(_ sender: Any) {
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
guard let secondVC = storyBoard.instantiateViewController(withIdentifier: "SecondViewController") as? SecondViewController else { return }
secondVC.isButtonSelected = isButtonSelected
secondVC.delegate = self
self.present(secondVC, animated: true, completion: nil)
}
}
extension FirstViewController: ButtonSelectionProtocol {
func button(isSelected: Bool) {
isButtonSelected = isSelected
}
}
and for secondViewController
protocol ButtonSelectionProtocol {
func button(isSelected:Bool)
}
class SecondViewController: UIViewController {
var isButtonSelected : Bool = false
var delegate:ButtonSelectionProtocol?
#IBOutlet weak var selectButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
if isButtonSelected {
selectButton.tintColor = .red
selectButton.setTitle("Selected", for: .normal)
}else{
selectButton.tintColor = .green
selectButton.setTitle("Select Me", for: .normal)
}
}
#IBAction func gobackAction(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}
#IBAction func selectAction(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
isButtonSelected.toggle()
delegate?.button(isSelected: isButtonSelected)
}
}

swift ios UIButton inside UIView not working

I made it using a storyboard
I made another view controller for the custom tab bar and created a UIView called innerContents.
And I made another view controller for the setting page in it and put another view controller in innerContents with addSubview.
CustomTabBar with innerContents UIView
thats innerTabBar main CustomTabBar View Controller page
other ViewController
i will put thats ViewController in innerContents. so i writed addSubView. they are showing but UIButtons are not working. only work ScrollView.
How can I fix it?
code
I confirmed that all outlets are connected normally.
But the UIButton inside the UIView inside the UIScrollView inside the UiView of another view controller inside the UiView doesn't work.
mainCustomTabBar Page viewController > innerContents > otherViewController(addSubView) > UIView > UI ScrollView > UIView > UIView > UIButton(it's not working. i want fix that)
if currentPage != 5 {
currentPage = 5
print("탭바 클릭 5")
guard let AppSet = self.storyboard?.instantiateViewController(identifier: "AppSetViewController") as? AppSetViewController else {return}
AppSet.view.frame = ContentsView.bounds
AppSet.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
AppSet.view.tag = 500
removeSubview(tag: nowTag)
nowTag = 500
ContentsView.addSubview(AppSet.view)
let root = UIApplication.shared.windows.first?.rootViewController
root?.addChild(AppSet)
AppSet.didMove(toParent: root!)
page5Mode()
return
}
}
//
// AppSetViewController.swift
// rael
//
// Created by HongDaehyeon on 2021/07/08.
// 앱 설정 페이지를 위한 페이지 입니다.
import UIKit
class AppSetViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBOutlet var ContentView: UIView!{
didSet {
self.ContentView.isUserInteractionEnabled = true
}
}
#IBOutlet var Scrollview: UIScrollView!{
didSet{
self.Scrollview.isExclusiveTouch = true
}
}
//지갑정보
#IBAction func walletInfo(_ sender: Any) {
print("지갑정보")
}
//알림설정
#IBAction func alertSet(_ sender: Any) {
print("알림설정")
}
//인증방식설정
#IBAction func authSet(_ sender: Any) {
print("인증방식설정")
}
//공지사항
#IBAction func noticeNav(_ sender: Any) {
let vc = self.storyboard?.instantiateViewController(identifier: "SettingsNoticeViewController")
let navController = UINavigationController(rootViewController: vc!)
navController.modalPresentationStyle = .fullScreen
navController.modalTransitionStyle = .crossDissolve
navController.setNavigationBarHidden(true, animated: false)
self.present(navController, animated: true, completion: nil)
}
//FAQ
#IBAction func faqNav(_ sender: Any) {
let vc = self.storyboard?.instantiateViewController(identifier: "FaqViewController")
let navController = UINavigationController(rootViewController: vc!)
navController.modalPresentationStyle = .fullScreen
navController.modalTransitionStyle = .crossDissolve
navController.setNavigationBarHidden(true, animated: false)
self.present(navController, animated: true, completion: nil)
}
//고객상담
#IBAction func serviceCenter(_ sender: Any) {
print("고객상담")
}
//약관 및 정책
#IBAction func termsNav(_ sender: Any) {
print("약관 및 정책")
}
//지갑 삭제
#IBAction func removeWallet(_ sender: Any) {
print("지갑삭제")
}
//전화걸기
#IBAction func callService(_ sender: Any) {
print("전화걸기")
let urlString = "tel://1588-8282"
let numberURL = NSURL(string: urlString)
UIApplication.shared.open(numberURL! as URL, options: [:], completionHandler: nil)
}
//앱정보 로딩
#IBOutlet var appVer: UILabel!{
didSet{
self.appVer.text = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
}
}
}```

How to present programmatically a view controller from a UIVIew

I am using a Class which is a subclass of MessageView (Swift Message Library) which is inherit from UIView. Inside, I have a UIButton and I want to present programmatically another ViewController through it.
Here is my code below :
import Foundation
import SwiftMessages
import UIKit
class MyClass: MessageView {
var hideBanner: (() -> Void)?
#IBAction func helpButtonPressed(_ sender: UIButton) {
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: "newViewController") as! NewViewController
self.present(newViewController, animated: true, completion: nil)
#IBAction func tryAgainButtonPressed(_ sender: UIButton) {
hideBanner?()
}
open override func awakeFromNib() {
}
}
I have tried this, but it is not working since the UIView do not have the present method.
First get top ViewController using this. Then you can present your viewController.
if var topController = UIApplication.sharedApplication().keyWindow?.rootViewController {
while let presentedViewController = topController.presentedViewController {
topController = presentedViewController
}
// topController now can use for present.
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: "newViewController") as! NewViewController
topController.present(newViewController, animated: true, completion: nil)
}
.present is a method in UIViewController class, that's the reason you cannot present view controller from UIView class.
To achieve this, get the root view controller and present the controller as follows:
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let viewController = appDelegate.window!.rootViewController as! YourViewController
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: "newViewController") as! NewViewController
viewController .present(newViewController, animated: true, completion: nil)
The iOS convention is that only a ViewControllers presents another ViewController.
So the answers above - where the View is finds the current ViewController via UIApplication.sharedApplication().keyWindow?.... will work but is very much an anti-pattern.
The preferred way would be:
Your MyClass view has presentation code only
You must have a ViewController which has a reference to this MyClass view
This ViewController has the #IBAction func tryAgainButtonPressed
From there, you can present the next ViewController
Try this #simple code.
import Foundation
import SwiftMessages
import UIKit
class MyClass: MessageView {
var hideBanner: (() -> Void)?
#IBAction func helpButtonPressed(_ sender: UIButton) {
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: "newViewController") as! NewViewController
UIApplication.shared.keyWindow?.rootViewController?.present(newViewController, animated: true, completion: nil)
}
#IBAction func tryAgainButtonPressed(_ sender: UIButton) {
hideBanner?()
}
open override func awakeFromNib() {
}
}
Here is the example code using delegation pattern.
class YourViewController: UIViewController {
var yourView: MyClass // may be outlet
override func viewDidLoad() {
super.viewDidLoad()
yourView.delegate = self
}
}
protocol MyClassDelegate:class {
func tryAgainButtonDidPressed(sender: UIButton)
}
class MyClass: MessageView {
weak var delegate: MyClassDelegate?
#IBAction func tryAgainButtonPressed(_ sender: UIButton) {
delegate?.tryAgainButtonDidPressed(sender: sender)
}
}
You can achieve this by two ways
Protocol
By giving reference of that view controller to the view when you are initializing view
Sorry for the late reply. MessageView already provides a buttonTapHandler callback for you:
/// An optional button tap handler. The `button` is automatically
/// configured to call this tap handler on `.TouchUpInside`.
open var buttonTapHandler: ((_ button: UIButton) -> Void)?
#objc func buttonTapped(_ button: UIButton) {
buttonTapHandler?(button)
}
/// An optional button. This buttons' `.TouchUpInside` event will automatically
/// invoke the optional `buttonTapHandler`, but its fine to add other target
/// action handlers can be added.
#IBOutlet open var button: UIButton? {
didSet {
if let old = oldValue {
old.removeTarget(self, action: #selector(MessageView.buttonTapped(_:)), for: .touchUpInside)
}
if let button = button {
button.addTarget(self, action: #selector(MessageView.buttonTapped(_:)), for: .touchUpInside)
}
}
}
which is automatically invoked for any button you connect to the button outlet. So the recommended method for presenting another view controller is to have the presenting view controller configure the presentation logic in this callback:
messageView.tapHandler = { [weak self] in
guard let strongSelf = self else { return }
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: "newViewController") as! NewViewController
strongSelf.present(newViewController, animated: true, completion: nil)
}
If your view has more than one button, you can handle them all through buttonTapHandler since it takes a button argument. You just need to configure the target-action mechanism for each button:
otherButton.addTarget(self, action: #selector(MessageView.buttonTapped(_:)), for: .touchUpInside)
Or you can add one callback for each button by duplicating the above pattern.

SWRevealViewController NOT working

I simply implemented this tutorial until minute 8:35 , and it did not work.
import Foundation
class ViewController: UIViewController {
#IBOutlet weak var Open: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
print("open")
Open.target = self.revealViewController()
Open.action = Selector("revealToggle:")
print("open2")
}
override func viewDidAppear(_ animated: Bool) {
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}}
However, its worth to note. I am getting to this page after splash screen page.And below how am doing it
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "Navigate") as! UINavigationController
//self.present(vc, animated: true, completion: nil)
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = vc
From Splashscontroller i am calling to go main.storyboard.
Navigate, I click on navigation controller and give it storyboardid Navigate.
I get to the page, with open button..but no right reveal controller opens when i click on it.
Please edit your appdelegate "didFinishLaunchingWithOptions" method's code as below
// create viewController code...
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let mainViewController = storyboard.instantiateViewControllerWithIdentifier(""Navigate") as! UINavigationController
let leftViewController = storyboard.instantiateViewControllerWithIdentifier("Left") as! LeftSideMenuViewController
let slideMenuController = SlideMenuController(SailDataViewController:mainViewController , LeftSideMenuViewController : leftViewController)
self.window?.rootViewController = slideMenuController
self.window?.makeKeyAndVisible()
UIApplication.sharedApplication().setStatusBarStyle(UIStatusBarStyle.LightContent, animated: true)
please check in your class name , because I haven't run this code . But in my project it is working.

How to dismiss the current ViewController and go to another View in Swift

I am new to Swift and I want to know how to dismiss the current view controller and go to another view.
My storyboard is like the following: MainMenuView -> GameViewController -> GameOverView. I want to dismiss the GameViewController to go to the GameOverView, not to the MainMenuView.
I use the following code in my MainMenuView:
#IBAction func StartButton(sender: UIButton) {
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewControllerWithIdentifier("GameViewController") as! GameViewController
self.presentViewController(nextViewController, animated:true, completion:nil)
restGame()
}
In the GameViewController, I use this code, but it doesn't dismiss the GameViewController.
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewControllerWithIdentifier("GameOverView") as! GameOverView
self.presentViewController(nextViewController, animated:true, completion:nil)
This is My GameOverView Code :
class GameOverView: UIViewController{
// save the presenting ViewController
var presentingViewController :UIViewController! = self.presentViewController
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func ReplayButton(sender: UIButton) {
restGame()
didPressClose()
}
#IBAction func ReturnMainMenu(sender: UIButton) {
Data.GameStarted = 1
self.dismissViewControllerAnimated(false) {
// go back to MainMenuView as the eyes of the user
self.presentingViewController.dismissViewControllerAnimated(false, completion: nil);
}
/* let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewControllerWithIdentifier("MainScene") as! MainScene
self.presentViewController(nextViewController, animated:true, completion:nil)*/
}
func restGame(){
Data.score = 0
Data.GameHolder = 3
Data.GameStarted = 1
Data.PlayerLife = 3.0
Data.BonusHolder = 30
Data.BonusTimer = 0
}
func didPressClose()
{
self.self.dismissViewControllerAnimated(true, completion:nil)
}
override func shouldAutorotate() -> Bool {
return false
}
deinit{
print("GameOverView is being deInitialized.");
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
override func prefersStatusBarHidden() -> Bool {
return true
}
}
Any suggestions?
What you can do is let the GameOverView be presented, after all when you presenting it the GameViewController is below in the hierarchy, and then in your GameOverView run the following code to close both when you want to dismiss the GameOverView, like in the following way:
#IBAction func ReturnMainMenu(sender: UIButton) {
// save the presenting ViewController
var presentingViewController: UIViewController! = self.presentingViewController
self.dismissViewControllerAnimated(false) {
// go back to MainMenuView as the eyes of the user
presentingViewController.dismissViewControllerAnimated(false, completion: nil)
}
}
The above code need to be called when you want to dismiss the GameOverView.
I hope this help you.
The below code will take you to the main VC, Here's a tried and tested piece of code.
self.view.window!.rootViewController?.dismiss(animated: false, completion: nil)

Resources