Xcode Swift 3: Timer and Segue View Controller Error - swift

This code is in ViewController 1. goToMainUI is assigned to the segue connection ID between ViewController 1 and 2. Also, the storyboard ID for ViewController 2 is the same (goToMainUI). After the timer is finished, there is an error and the ViewControllers do not switch. Anyone know what the problem is? Thanks!
override func viewDidLoad() {
super.viewDidLoad()
let timer = Timer.scheduledTimerWithTimeInterval(8.0, target: self, selector: #selector(timeToMoveOn), userInfo: nil, repeats: false)
func timeToMoveOn() {
self.performSegue(withIdentifier: "goToMainUI", sender: self)
}

Try this code:
Note: Code tested in Swift 3.
Step 1: First set storyboard Segue Identifier
Step 2:
let emptyString = String() // Do nothing
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
Timer.scheduledTimer(timeInterval: 8.0, target: self, selector: #selector(timeToMoveOn), userInfo: nil, repeats: false)
}
func timeToMoveOn() {
self.performSegue(withIdentifier: "goToMainUI", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "goToMainUI") {
let dest = segue.destination as! viewTwo // viewTwo is your destination ViewController
dest.emptyString = emptyString
print("Segue Performed")
}
}
In your ViewTwo add this above viewDidLoad method.
var emptyString = String()

Related

Set condition on a segue function swift

In a single button, i put both alart system and a pop up view. If the text fields are blank then it will send an alart. If everything is okay then it will show popup view. Alart system and pop up is conflicting. How do I set conditon to segue function when to perform or not?
The function is not written proper. I can understand. But I am confused writing it. How do i call the overrride func?
func stateCondition(state: Bool) {
if state {
print("Entered into the state") //entering into the func
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "info"{
_ = segue.destination as! InfoViewController
}
if segue.identifier == "popUp" {
let vc = segue.destination as! PopUpViewController
vc.age = Double(ageTextField.text!)!
vc.gender = genderTextField.text!
vc.bmi = Double(bmiLabel.text!)!
print("Entered into the segue") //is not entering into this func
}
}
}
}
Try to read the code and comments.
First of all, the method func prepare(for segue: UIStoryboardSegue, sender: Any?) must not be in another method. Somehow you managed to squeeze it in func stateCondition(state: Bool) . Second you are not calling performSegue(withIdentifier: identifier, sender: self) anywhere. You probably should :) Check out the code, hope it helps. I remember my first segue, it took me some time to understand what is going on.
class ViewController: UIViewController {
#IBOutlet private var ageTextField: UITextField!
#IBOutlet private var genderTextField: UITextField!
#IBOutlet private var bmiLabel: UILabel!
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// 3
// This method gets called and there you do your stuff with respective VCs
if segue.identifier == "info", let infoViewController = segue.destination as? InfoViewController {
// 3.1
// If the identifer is set to INFO then you go to the InfoViewController and assigne message
infoViewController.message = "Some fields are empty"
} else if segue.identifier == "popUp", let popUpViewController = segue.destination as? PopUpViewController {
// 3.2
// If the identifer is set to POPUP then you go to PopUpViewController and assign age, gender and bmi
popUpViewController.age = "33"
popUpViewController.gender = "male"
popUpViewController.bmi = "20"
} else {
print("Identifer is none of the above")
}
}
#IBAction private func buttonTapped(_ sender: Any) {
// 1.
// First you need to figure out where you want to take the user
// You do that in the method getSegueIdentifier() where you get the identifier
let identifier = getSegueIdentifier()
// 2.
// Then you performSegue with that identifer
performSegue(withIdentifier: identifier, sender: self)
}
private func getSegueIdentifier() -> String {
if ageTextField.text?.isEmpty == true && genderTextField.text?.isEmpty == true && bmiLabel.text?.isEmpty == true {
return "info"
} else {
return "popUp"
}
}
}
class InfoViewController: UIViewController {
var message = ""
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
showAlert()
}
func showAlert() {
// show alert with message
print(message)
}
}
class PopUpViewController: UIViewController {
var age = ""
var gender = ""
var bmi = ""
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
showPopUp()
}
func showPopUp() {
// show popUp with age gender and bmi
print(age, gender, bmi)
}
}
There is general misunderstanding: You must not call prepare(for segue – besides the syntax is wrong anyway – the function is called by the framework just before the segue is performed.
You probably mean something like
func stateCondition(state: Bool) {
if state {
print("Entered into the state") //entering into the func
performSegue(withIdentifier: "info", sender: nil)
} else {
performSegue(withIdentifier: "popUp", sender: nil)
}
}
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "popUp" {
let vc = segue.destination as! PopUpViewController
vc.age = Double(ageTextField.text!)!
vc.gender = genderTextField.text!
vc.bmi = Double(bmiLabel.text!)!
print("Entered into the segue") //is not entering into this func
}
}

how to use segue after using webview?

how do i perform segue when i exit the webview? it keeps throwing the sigbart error
class Sample: UIViewController, WKUIDelegate{
var url = String()
#IBOutlet var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let myURL = URL(string:"\(url)")
let myRequest = URLRequest(url: myURL!)
webView.configuration.preferences.javaScriptEnabled = true
webView.load(myRequest)
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
self.performSegue(withIdentifier: "toMain", sender: self)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
webView.stopLoading()
}
}
Shouldn't have to do to with the webview if it is crashing on the segue. If you are trying to push to a new controller make sure you have your identifier set like below:
If you are just trying to go back one controller you can use:
self.dismiss(animated: true, completion: nil)
instead of:
self.performSegue(withIdentifier: "toMain", sender: self)
If you need to go back multiple views look into unwindToSegue functionality.
I would also consider moving the stopLoading function to viewWillDisappear since it has nothing to do with the segue itself.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.webView.stopLoading()
}

Attempting to pass data from one viewcontroller to another using segues

I have two viewcontrollers setup and set the segue connections as well. I'm attempting to pass data from one of the VC's to the other. Using the below code and using the func override works. What i want to do is only have the override func prepare fire off when a button is pressed and when i paste the override func code into a button action, it doesnt work - the label on the first VC doesnt update - it stays to the default value i set.
First ViewController code:
var testLabel1:String = "default"
#IBOutlet weak var testLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
testLabel?.text = testLabel1
// Do any additional setup after loading the view.
}
Second ViewController code:
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if segue.destination is ViewController
{
let vc = segue.destination as? ViewController
vc?.testLabel1 = "Success"
}
}
Button action that ive tried
#IBAction func actionBtn(_ sender: Any) {
func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if segue.destination is ViewController
{
let vc = segue.destination as? ViewController
vc?.testLabel1 = "Success"
}
}
}
You need to trigger it with performSegue
class FirstVc:UIViewController {
#IBOutlet weak var lbl:UILabel!
#IBAction func goToSecond(_ sender: Any) {
self.performSegue(withIdentifier:"YourSegueName",sender:nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "YourSegueName" {
let vc = segue.destination as! SecondVC
vc.testLabel1 = "Success"
}
}
func setData(_ str:String){
self.lbl.text = str
}
}
class SecondVC:UIViewController {
var testLabel1 = ""
weak var delegate:FirstVc?
func goBack() {
self.delegate?.setData("FromSecond")
self.dismiss(animated: true, completion: nil)
}
}

Execute a function from other view controller

I have the following interfaces:
In the table view I set the new values for the user and I would like to call the function to update the data from the server when the button "Done" from the main view is pressed.
How I can do it?
I have tried:
#IBAction func doneTapped(_ sender: Any){
ProfileEditingTableViewController().updateData()
}
But all the text fields from the other view are null because it seems to be a new instance of ProfileEditingTableViewController.
updateData() can't be static.
class ProfileEditingViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func cancelButton(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
#IBAction func doneTapped(_ sender: Any) {
// Here I have to save the data from the other View
dismiss(animated: true, completion: nil)
}
}
class ProfileEditingTableViewController: UITableViewController {
func updateData() {
...
}
}
This line
ProfileEditingTableViewController().updateData()
is incorrect as it creates a new instance, you need to use delegate to access the presented ProfileEditingTableViewController
class ProfileEditingTableViewController: UITableViewController {
var profileInstance: ProfileEditingViewController!
}
When you present information from profile:
let info = //
info.delegate = self // here self is the profile instance
Then use:
profileInstance.updateData()
//
Edit: connect the segue source to the vc itself ( yellow circular icon ) , this inside ( ProfileEditingViewController)
self.performSegue(withIdentifier: "goToNext", sender: nil)
//
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
if segue.identifier == "goToNext" {
let des = segue.destination as! ProfileEditingTableViewController
des.profileInstance = self
}
}

How to hide and show label when navigation VC1 to VC2 back and forth

Say, I have a label show : Loading...
problem: When return from VC(2). The label is not hidden.
How to hide it when return from VC(2) and dont hide it when in navigating to VC(2) and show the message : Loading....
in VC(1)
#IBOutlet weak var lbLoadingMsg
In viewDidLoad() {
lbLoadingMsg.hidden = true
}
-2-- turn it on when prepare to navigate to VC(2)
override func shouldPerformSegueWithIdentifier(identifier: String?, sender: AnyObject?) -> Bool
{
--code--
lbLoadingMsg.hidden = false
}
Override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!){
}
You can use NSNotificationCenter for that.
Follow this simple steps:
1.In your VC(2) add this code into your button from where you are going back:
#IBAction func goBack(sender: AnyObject) {
NSNotificationCenter.defaultCenter().postNotificationName("hide", object: nil)
self.dismissViewControllerAnimated(true, completion: nil)
}
2.In your First View add this code into viewDidLoad method:
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "hideLabel:", name:"hide", object: nil)
}
now this method will call this function:
func hideLabel(notification: NSNotification){
self.lbLoadingMsg.hidden = true
}
And this will hide your label in first view when ever goBack button will pressed from first view.
Hope this will help you.
Write this in VC2
,
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var identifier = segue.identifier
if(identifier! == "yourIdentifier"){
var vc1:VC1 = segue.destinationViewController as! VC1
vc1.lbLoadingMsg.hidden = true
}
}
func viewDidAppear(_ animated: Bool) {
lbLoadingMsg.hidden = true
}
Move
lbLoadingMsg.hidden = true
line from viewDidLoad to viewDidAppear. I think most quicker way.