Xcode Swift 3: Timer and Segue View Controller Error
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()
Xcode doesn't Recognise Timer()- Swift 3
Timer
is a Swift 3 type, but judging from the rest of your method signatures, you appear to be using Swift 2. Use NSTimer
in Swift 2.
Also, for future reference, in addition to the timeInterval
typo (which you've now fixed), the third parameter is selector
, not selecter
.
So, in Swift 2:
NSTimer.scheduledTimerWithTimeInterval(8.0, target: self, selector: #selector(changeview), userInfo: nil, repeats: false)
Or in Swift 3:
Timer.scheduledTimer(timeInterval: 8.0, target: self, selector: #selector(changeview), userInfo: nil, repeats: false)
iOS Looking to delay segue between view controllers when button is pressed
Whenever you user performSegue
method then you need to use like that
In the example with a 10 second delay
DispatchQueue.main.asyncAfter(deadline: .now() + 10.0, execute: {
self.performSegue(withIdentifier: "segue", sender: self )
})
Updated
In this example with 5 second delay
DispatchQueue.main.asyncAfter(deadline:.now() + 5.0, execute: {
self.performSegue(withIdentifier:"segue",sender: self)
})
Swift Timer.scheduledTimer() doesn't work
Timers don't work on background queues (without some sleight of hand involving creating run loops or manually scheduling it on an existing run loop). But you should never initiate any UI update from anything other than the main queue, anyway.
So, since you're calling performSegue
from a URLSession
completion closure (which runs on a background queue), it's actually running viewDidLoad
from the background queue, too. Thus the attempt to schedule the timer is failing. To get around this, you have to manually dispatch the performSegue
code to the main queue:
let task = URLSession.shared.dataTask(with: url!) { data, response, error in
...
if isPassed != "null" {
DispatchQueue.main.async {
self.performSegue(withIdentifier: "gotoGame", sender: ...)
}
}
}
If you're ever unsure whether some code is running on the main queue or not, refer to the documentation. Or you can use a dispatch precondition:
dispatchPrecondition(condition: .onQueue(.main))
That way it will (in debug builds) stop the app if you've accidentally invoked the code from a background queue.
Unrelated to your current problem, but as an aside, to avoid a strong reference cycle between the timer and the view controller, you generally want to keep a reference to the timer so that you can invalidate
it when the view disappears (e.g. create timer in viewDidAppear
and remove it in viewDidDisappear
). Otherwise you can end up retaining the GameViewController
after it was dismissed, e.g.:
class GameViewController: UIViewController {
weak var timer: Timer?
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
timer = Timer.scheduledTimer(timeInterval: 1.0, target:self, selector: #selector(setCalculationLs(_:)), userInfo: nil, repeats: true)
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
timer?.invalidate()
}
@objc func setCalculationLs(_ timer: Timer) {
print("Tick")
}
}
Or in iOS 10 or later, you can use the block-based variant with weak
reference to self
, and invalidate
in deinit
:
class GameViewController: UIViewController {
weak var timer: Timer?
override func viewDidLoad() {
super.viewDidLoad()
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] timer in
self?.setCalculationLs()
}
}
deinit {
timer?.invalidate()
}
func setCalculationLs() {
print("Tick")
}
}
Getting : Attempt to dismiss from view controller while a presentation or dismiss is in progress
simply use:-- dismiss(animated: true, completion: nil) and omit self
different viewcontroller segue
When you say B_Controller().goToC()
you are creating a new instance of B_Controller
, you aren't referring to the existing instance that was created by the goToB
segue. Further, since your new instance of B_Controller
isn't being created from the storyboard, it doesn't know anything about segues.
You need to store a reference to the instance of B_Controller
that you are presenting in a property. Then you can use that property to invoke the goToC
function.
class A_ViewController: ViewController {
var bController: B_Controller?
...//in Timer
//first 1 minute
performSegueWithIdentifier("goToB", sender: self)
//second minute
self.bController?.goToC()
...
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToB" {
self.bController = segue.destination as! B_ViewController
self.bController.msg = "From AtoB"
}
if segue.identifier == "goToSearchLocation" {
let C_ViewController = segue.destination as! C_ViewController
C_ViewController.msg = searchWord
}
}
class B_Controller: ViewController {
...
func goToC() {
performSegueWithIdentifier("goToC", sender: self)
}
}
You might want to re-design your code though; It would probably be cleaner to have a new timer in B that presents C rather than trying to use a single timer in A.
Related Topics
How to Give Dynamic Height to Uitableview
Swiftui - Mapkit - Binding Mapkit and Show View on Annotation Callout Buttons
Downloading Firebase Storage Files Device Issue
Swift Format Text Field When User Is Typing
How to Increment Exponentially in Swift
How to Get All Characters of the Font with Ctfontcopycharacterset() in Swift
Contextual Member Has No Associated Value in Swift 3
Value of Optional Type 'Nsurl' Not Unwrapped; Did You Mean to Use '!' or ''
How to Create a Dynamic Link in Firebase Programmatically? Swift
Learning Swift: Expressions Are Not Allowed at the Top Level
Swift Sorting Array of Structs by String Double
Swift Issue in Passing Variable Number of Parameters
Raw Value of Enumeration, Default Value of a Class/Structure, What's the Different
How to Handle Two Possible Date Formats
Why Can't I Use 'Type' as the Name of an Enum Embedded in a Struct