Swift NSTimer Coding - xcode

Using Swift 2.0 and trying to implement Swift NSTimer in Custom Keyboard. Button2 shows up great when Button1 is pressed, until the NSTimer kicks in and crashes the keyboard.
I'm trying to hide Button2 after a few seconds.
#IBAction func Button1(sender: UIButton) {
Button2.setTitle("Text", forState: UIControlState.Normal)
NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: Selector("Hide:"), userInfo: nil, repeats: false)
Button2.hidden = false
}

This should work (note that I changed some of the function names to more closely follow conventions):
#IBAction func button1Tapped() {
button2.setTitle("Text", forState: .Normal)
button2.hidden = false
NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: "hideButton2", userInfo: nil, repeats: false)
}
#objc func hideButton2() {
button2.hidden = true
}

Replace Selector("Hide:") with "Hide:" and add #objc in front of your func

Related

Swift 2.2 - NSTimer with optional completion-handler selector

I am trying to call a function with optional CompletionHandler parameter from a timer. Below is my code snippet:
typealias CompletionHandler = () -> Void
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(ViewController.check(_:)), userInfo: nil, repeats: false)
}
func check(completion: CompletionHandler?) {
print("userinfo1")
}
}
When the timer is triggered after 1.0 second, my app is dead with EXC_BAD_ACCESS and the pointer points to class AppDelegate: UIResponder, UIApplicationDelegate in AppDelegate.
Can you show me how I can call check function with such parameter? (If completion is just an Int, the timer did work!)
Thanks
You can create a timer like this:
NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(connectionTimeoutExpired(_:)), userInfo: nil, repeats: false)
func connectionTimeoutExpired(sender: NSTimer) {
print("Connection Timeout Expired")
connectionTimer?.invalidate()
connectionTimer = nil
}

Present View Controller when the view is not in the window hierarchy

import AVFoundation
import UIKit
import AVKit
class Class1: UIViewController {
var playerViewController = AVPlayerViewController()
var playerView = AVPlayer()
var playerTimer = NSTimer()
override func viewDidAppear(animated:Bool) {
let fileURL = NSURL(fileURLWithPath: "file.mp4")
playerView = AVPlayer(URL: fileURL)
playerViewController.player = playerView
self.presentViewController(playerViewController, animated: true){
self.playerViewController.player?.play()
self.playerTimer = NSTimer.scheduledTimerWithTimeInterval(4.0, target: self, selector:Selector("stopAfter4seconds:"), userInfo: nil, repeats: false)
}
}
func stopAfter4seconds(timer: NSTimer){
self.playerViewController.player?.pause()
self.playerViewController.player = nil
self.presentingViewController?.dismissViewControllerAnimated(false, completion: nil)
self.presentViewController(GameViewController1(), animated: false, completion: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
My Problem is that when I present the line:
self.presentViewController(GameViewController1(), animated: false, completion: nil)
I Get the error "attempt to present GameViewController1... whose view is not in the window hierarchy!"
I made sure to play it in viewDidAppear as to add it to the view hierarchy but it doesn't seem to do so
[Update] Okay i realize now that I'm presenting the avplayerviewcontroller and then trying to play the next view controller after. How exactly do I "Dismiss" the AVplayerviewcontroller as well have my next view in the right window hierarchy???
ANSWER: I was presenting my next view with 'self.' instead of with the view controller that was present, which happened to be the playerViewController so this line of code worked for me.
playerViewController.presentViewController(GameViewController1(),
animated: false, completion: nil)

Connecting multiple outlets to single action?

I'm creating a keyboard extension in XCode Beta 7 (Swift2).
I'm trying to connect multiple buttons to a single action.
However, when I connect all the button outlets to this action, it causes my keyboard to crash which makes me think there's something I'm missing.
#IBOutlet weak var Label: UIButton!
#IBAction func ButtonTapped(sender: AnyObject) {
Label.setTitle("Hello!", forState: .Normal)
Label.hidden = false
Label.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.5)
NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: "hideLabel", userInfo: nil, repeats: false)
}
#objc func hideLabel() {
Label.hidden = true
Label.backgroundColor = UIColor.clearColor()
}
Attaching the same action to multiple buttons is not a problem, and is a common technique.
However, you have Label set as force-unwrapped, which will crash if it is nil.
My guess is that your Label outlet is not connected so Label is nil at runtime.
Change the type of Label from UIButton! to UIButton? and then change your code to use "if let" optional binding to only execute the code using Label if label is non-nil.
BTW, Swift has a strong naming convention. Variable names should start with a lower-case letter and use "camel case" for the rest of the variable name. Only class names and type names should start with a capital letter. So "Label" should be "label" instead. Get in the habit of following that style. It serves as a clear visual cue to you and others reading your code as to what type of thing a name refers to.
Finally, "Label" is a horrible name for a button. It's a button, not a UILabel. Call it "myButton" or something instead.
EDIT
The code might look like this:
#IBOutlet weak var myButton: UIButton?
#IBAction func ButtonTapped(sender: AnyObject)
{
println("myButton = \(myButton)") //See if myButton is nil
if let myButton = myButton
{
myButton.setTitle("Hello!", forState: .Normal)
myButton.hidden = false
myButton.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.5)
NSTimer.scheduledTimerWithTimeInterval(2, target: self,
selector: "hidemyButton",
userInfo: nil, repeats: false)
}
}
#objc func hidemyButton()
{
myButton.hidden = true
myButton.backgroundColor = UIColor.clearColor()
}

Extra argument 'selector' in call

I'm trying to create a simple stopwatch app where the timer label increments when the startButton button is pressed. This is what I have:
#IBOutlet weak var timer: UILabel!
#IBAction func startButton(sender: AnyObject) {
timer = NSTimer.scheduledTimerWithTimeInterval(0.0025, target: self, selector: Selector("result"), userInfo: nil, repeats: true)
}
var count = 0
func result() {
count++
timer.text=String(count)
}
I get the error "Extra argument 'selector' in call" but can't workout the syntax to do it properly.
Swift error messages are a little lacking at times. It should have said something like "NSTimer is not convertible to UILabel". You are assigning the timer you create to your IBOutlet timer which is a UILabel. The timer is an NSTimer. Just assign it to a different variable when you create it and all will be fine.
#IBAction func startButton(sender: AnyObject) {
let myTimer = NSTimer.scheduledTimerWithTimeInterval(0.0025, target: self, selector: "result", userInfo: nil, repeats: true)
}
As a shortcut, you can just use a string as a selector, so Selector("result") can be replaced by just "result".

Change label.text from function Xcode/Swift

I have a timer, which calls a selector.
Directly from that function, I want to change the text of a label.
#IBOutlet weak var myLabel: UILabel!
override func viewDidLoad() {
var timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: Selector("update"), userInfo: nil, repeats: true)
}
func update () {
self.myLabel.text = "MyNewText"
}
Xcode tells me to use "self", but the label is still not updating!
Thanks for your help!
UI updates must always be done in the main thread, so try this:
func update () {
DispatchQueue.main.async {
self.myLabel.text = "MyNewText"
}
}

Resources