I am trying to pass information to my custom PopUpViewController using the github extension (https://github.com/Orderella/PopupDialog). The Popup uses a viewcontroller I've named PopUpViewController(with a xib file), and the view controller that the PopUp is initiated from is called MainViewController.
The information passed to the PopUpViewController will be an array(named: popUpArray) of type String and used for displaying the contained information within a table (named: tableView).
MainViewController code:
func showCustomDialog(_ sender: UIButton) {
// Create a custom view controller
let PopUpVC = PopUpViewController(nibName: "PopUpViewController", bundle: nil)
// Create the dialog
let popup = PopupDialog(viewController: PopUpVC, buttonAlignment: .horizontal, transitionStyle: .bounceDown, gestureDismissal: true)
// Create second button
let buttonOne = DefaultButton(title: "Ok", dismissOnTap: true) {
}
// Add buttons to dialog
popup.addButton(buttonOne)
// Present dialog
present(popup, animated: true, completion: nil)
}
PopUpViewController Code:
import UIKit
class PopUpViewController: UIViewController {
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var tableView: UITableView!
Just declare a new variable on PopUpViewController called data with type Array<String>.
After this, when you are creating your viewController, you can just pass it to the controller. After that it is just a simple tableView implementation in PopUpViewController to display the data.
Extend PopUpViewController with data parameter.
import UIKit
class PopUpViewController: UIViewController {
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var tableView: UITableView!
// Data variable
public var data: [String] = []
}
Add the data upon calling showCustomDialog() function
// Create a custom view controller
let PopUpVC = PopUpViewController(nibName: "PopUpViewController", bundle: nil)
// Assign the data
PopUpVC.data = popUpArray
Create a convenience init in PopUpViewController like following
convenience init(nibName: String, arrayOfString: [String] ){
self.data = arrayOfString
self.init(nibName: nibName, bundle:nil)
}
Then on MainViewController call the convenience init you just created like this something like this
// Create a custom view controller
let PopUpVC = PopUpViewController("PopUpViewController", arrayOfString: ["String1", "String2"])
Related
So I want to instantiate a view controller from storyboard and change its static variables.
This is "vc1" - the view controller to be instantiated:
import UIKit
class vc1: UIViewController {
#IBOutlet weak var lbl_title: UILabel!
static var title = "initial value"
override func viewDidLoad() {
super.viewDidLoad()
lbl_title.text = vc1.title
}
}
And this is my root vc.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var btn_go: UIButton!
#IBAction func btn_gogogo(_ sender: Any) {
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "vc1") as! vc1
vc.title = "bla"
self.present(vc, animated: true, completion: nil)
}
}
Here I'm trying to change the static variable of the view controller that I just instantiated,
with no effect. The variable ( in my case 'title' ) is always stuck to its initial value.
What is the problem here?
Best
Mark
Don't try to override the view controller's title property. Instead, create your own:
class vc1: UIViewController {
#IBOutlet weak var lbl_title: UILabel!
var myTitle = "initial value"
override func viewDidLoad() {
super.viewDidLoad()
lbl_title.text = myTitle
}
}
class ViewController: UIViewController {
#IBOutlet weak var btn_go: UIButton!
#IBAction func btn_gogogo(_ sender: Any) {
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "vc1") as! vc1
vc.myTitle = "bla"
self.present(vc, animated: true, completion: nil)
}
}
class FourthViewController : UIViewController {
#IBOutlet weak var previousLabel: UILabel!
#IBOutlet weak var backButton: UIButton!
var delegate: FourthToFirst?
var label = ""
// MARK: - Lifecycle method
override func viewDidLoad() {
super.viewDidLoad()
previousLabel.text = label
let fourthViewController = storyboard?.instantiateViewController(withIdentifier: "FourthViewController") as? FourthViewController
navigationController?.pushViewController(fourthViewController!, animated: true)
}
// MARK: - IBAction
#IBAction func backToFirst(_ sender: Any) {
navigationController?.popToRootViewController(animated: true)
}
Actually I am in fourthviewController it was going recursively(i.e pushing the fourthViewcontroller again and again, nonstop)
if I pressed back button in the controller I have to go back(i.e firstviewcontroller)
problem is:
In my code it was going (i.e non stop)
I can't press the back button to go back(i.e firstviewcontroller)
navigationController?.popViewController(animated: true) instead of navigationController?.popToRootViewController(animated: true) could be what's you need mate. (Based on what's you just edited)
I have 2 view controller.
1. ViewController (VC)
2. WebViewController (WVC)
In VC I click on a button and WVC is shown.
After successfully completing all tasks in WVC, I want to show VC and execute a particular function in VC.
Now, Storyboard contains some objects and add to VC using click and drag.
Initially, it has some values(not nil).
I Click on button, WVC is pushed, After completing all task in WVC,
VC is pushed.
Now some values in VC is nil.
error,welcome (UILabel, UIView) is nil...
And also is want to call a function in VC.
How it is possible.?
Code
ViewController.swift
class LoginController:UIViewController,UITextFieldDelegate{
#IBOutlet weak var password: UITextField!
#IBOutlet weak var username: UITextField!
#IBOutlet weak var error: UILabel!
#IBOutlet weak var welocome: UILabel!
......
#IBAction func BtnClicked(sender: AnyObject) {
let webViewCnt = self.storyboard!.instantiateViewControllerWithIdentifier("WebViewController") as UIViewController
self.navigationController?.pushViewController(webViewCnt, animated: true)
}
func doSomeProcess(){
}
}
WebViewController.swift
class WebViewController: UIViewController, UITextFieldDelegate,UIWebViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
webView.delegate = self
self.start()
}
func start(){
---- do some process ----
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let ViewCont = self.storyboard!.instantiateViewControllerWithIdentifier("LoginController") as UIViewController
self.navigationController?.pushViewController(ViewCont, animated: true)
ViewController().doSomeProcess() // call viewcontroller doSomeProcess() function
}
})
}
}
Simple your are pushing VC to WVC,
So logically after pushing WVC to NavigationController.
it added WVC to the top of Navigation Stack.
& it it better to pop this WVC from Navigation will automatically show VC with previous values.
use this
ViewController.swift
class LoginController:UIViewController,UITextFieldDelegate{
#IBOutlet weak var password: UITextField!
#IBOutlet weak var username: UITextField!
#IBOutlet weak var error: UILabel!
#IBOutlet weak var welocome: UILabel!
var isBackFromWVC = false
......
#IBAction func BtnClicked(sender: AnyObject) {
let webViewCnt = self.storyboard!.instantiateViewControllerWithIdentifier("WebViewController") as UIViewController
self.navigationController?.pushViewController(webViewCnt, animated: true)
isBackFromWVC = true
}
func doSomeProcess(){
}
func vieWillAppear(){
if(isBackFromWVC){
doSomeProcess()
}
}
}
WebViewController.swift
class WebViewController: UIViewController, UITextFieldDelegate,UIWebViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
webView.delegate = self
self.start()
}
func start(){
---- do some process ----
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.navigationController?.popViewController(animated:true)
}
})
}
}
Try to pop:
In this start() method just replace a line self.navigationController?.popViewController(animated: true)
instead of pushing the ViewController.
func start(){
---- do some process ----
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let ViewCont = self.storyboard!.instantiateViewControllerWithIdentifier("LoginController") as UIViewController
self.navigationController?.pushViewController(ViewCont, animated: true)
ViewController().doSomeProcess() // call viewcontroller doSomeProcess() function
}
})
}
Reason:
When you are pushing to any ViewController, The storyboard will create a new reference of ViewController and the OOP's says every object has its own properties and method so that's why your pushing view controller properties may be nil assume that your username: UITextField! text will be nil due to separate instance of ViewController.
For calling the function of your view-controller you have to implement the delegate if it is not for every time else you may work in viewwillappear.
From my understanding, probably what you want is to dismiss WVC and go back to VC.
in WebViewController's start():
self.navigationController?.popViewController(animated: true)
and after pop, you need to execute doSomeProcess() function. There're several ways to do this and I'll introduce one here.
in ViewController, implement UINavigationControllerDelegate:
func navigationController(_ navigationController: UINavigationController, animationCOntrollerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewCOntroller) -> UIViewControllerAnimatedTransitioning? {
switch operation {
case .pop:
let to = toVC as! ViewController
to.doSomeProcess()
default:
break
}
return nil
}
of course you'll need
self.navigationController?.delegate = self
inside VC's viewDidLoad() as well.
//Index=0 //contains buttonToSwitchTab to pop to TabOneVC
TabZeroNavCntrlr ----TabZeroVC --- TabChangeVC
//segmntCntrl /
NavCntlr--ContainerView---
\ //Index=1
TabOneNavCntrlr ---- TabOneVC
I have a NavController that hasContainerView connected to it. Inside the containerView there is a segmentControl. The containerView has 2 more nav controllers connected to it that each lead to their own child controllers: TabZeroVC and TabOneVC. Initially the first view shown is TabZeroVC (selectedSegmentIndex = 0). There is a button inside there that leads to TabChangeVC which has a buttonToSwitchTab inside of it. Pressing that button I want to pop to TabOneVC.
I tried this code below by using my navigation controller to make the switch but on the line tabOneVC.segmentedControl.selectedSegmentIndex = 1 I get a crash: unexpectedly found nil while unwrapping an Optional value
I put a break point on it and the containerVC gets initialized but it's 3 properties segmentedControl, tabZeroVC, and tabOneVC are all coming up as nil. Since segmentedControl is nil that's where the crash is happening.
class TabChangeVC: UIViewController{
#IBAction func buttonToSwitchTab(sender: UIButton){
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let containerVC = mainStoryboard.instantiateViewControllerWithIdentifier("ContainerViewController") as! ContainerViewController
containerVC.segmentedControl.selectedSegmentIndex = 1 //crash happens here
self.navigationController?.popToViewController(containerVC, animated: true)
}
}
ContainerView:
class ContainerViewController: UIViewController{
#IBOutlet weak var segmentedControl: UISegmentedControl!
#IBOutlet weak var tabZeroVC: UIView!
#IBOutlet weak var tabOneVC: UIView!
...
}
TabOneVC is selectedSegmentIndex = 1
My question is how do I pop to TabOneVC from the TabChangeVC and more importantly why is the containerVC's segmentedControl coming up as nil?
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil
let tabOneVC = mainStoryboard.instantiateViewControllerWithIdentifier("TabOneNavigationController") //TabOneNavCntrlr identifire
tabOneVC.segmentedControl.selectedSegmentIndex = 1
appDelegate.window!.rootViewController = tabOneVC
I don't know why the segmentedControl is coming up as nil but I was able to pop to tabOneVC by using NSNotificationCenter. I created a func named tabSwitch() with the segment I wanted to show and then I added a listener inside the viewDidLoad of the ContainerViewController:
class ContainerViewController: UIViewController{
#IBOutlet weak var segmentedControl: UISegmentedControl!
#IBOutlet weak var tabZeroVC: UIView!
#IBOutlet weak var tabOneVC: UIView!
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(tabSwitch), name: "tabSwitch", object: nil)
}
func tabSwitch(){
self.segmentedControl.selectedSegmentIndex = 1
self.tabZeroVC.hidden = true
self.tabOneVC.hidden = false
}
}
Inside the TabChangeVC I added a notifier to trigger it and navigationController?.popToRootViewControllerAnimated(true) to get back to the root vc:
class TabChangeVC: UIViewController{
#IBAction func buttonToSwitchTab(sender: UIButton){
NSNotificationCenter.defaultCenter().postNotificationName("tabSwitch", object: nil)
self.navigationController?.popToRootViewControllerAnimated(true)
}
}
My view contain a button which bring a custom view which contain a ContainerView and it has a label. When I bring the custom view to the front I get the label text empty. So please where would be my issue?
View Controller Code:
#IBAction func PushAlert(sender: UIButton) {
let alert = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("alertViewController") as! AlertViewController
var alertText = AlertTextViewController()
alertText.lblText = "DONE"
alert.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext
alert.modalTransitionStyle = UIModalTransitionStyle.CrossDissolve
self.presentViewController(alert, animated: true, completion: nil)
}
class AlertTextViewController: UIViewController {
#IBOutlet weak var lblAlertText: UILabel!
var lblText = ""
override func viewDidLoad() {
super.viewDidLoad()
lblAlertText.text = lblText
}
}
I have created a link for the source code which will be much easier to understand source code
What about var lblText: String? in your AlertTextViewController.
Maybe it's overriden by your declaration (for some reason I wouldn't be able to explain)?
Or wait, I'm confused by
var alertText = AlertTextViewController()
as you are presenting creating and presenting the ViewController alert. How is alertText and alert related?
Edit:
class AlertViewController: UIViewController {
#IBOutlet weak var container: UIView!
override func viewDidLoad() {
super.viewDidLoad()
var alertText: AlertTextViewController = self.childViewControllers[0] as! AlertTextViewController
alertText.lblAlertText.text = "Test"
// Do any additional setup after loading the view.
}
Do this in your AlertViewController, and it works. I don't know what your final purpose is though, and this might not be the most elegant solution. I've created an outlet, the containerView to your class.
I think you may have a order of events problem. Try setting lblAlertText.text in viewWillAppear instead of viewDidLoad.