Extra argument 'selector' in call - xcode

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".

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
}

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()
}

Swift NSTimer Coding

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

Swift: Display images linked to a timer and slider

I'm new to programming and very new to Swift so am in need of help please.
I want to create a view where images will appear and then disappear from the screen at a specific time. The time will be indicated by a label and also a slider. For example, When 5 seconds is indicated on the the label the image will appear, After 10 seconds on the label, the image will disappear. After 15 seconds another image will appear and so on. This would continue for 60 seconds. This time label would also be connected to the slider. I would like to do this completely in code if possible
Any suggestions as to an efficient way to achieve this would be very much appreciated.
You can use an UIImageView, UILabel, UISlider and NSTimer to achieve this. Make sure you keep the NSTimer instance as a member variable in your ViewController
For example, your viewDidAppear would start the NSTimer with the default interval (lets say 5 seconds):
Your ViewController would look something like this:
import UIKit
class MyViewController : UIViewController
{
// Connect these outlets via InterfaceBuilder
#IBOutlet weak var imageView : UIImageView!
#IBOutlet weak var label : UILabel!
#IBOutlet weak var slider : UISlider!
var timer : NSTimer!
override func viewDidLoad()
{
super.viewDidLoad()
slider.addTarget(self, action: Selector("sliderValueChanged"), forControlEvents: .ValueChanged)
}
override func viewDidAppear(animated: Bool)
{
super.viewDidAppear(animated)
self.startTimerWithInterval(5)
}
func sliderValueChanged()
{
let newValue = slider.value
self.startTimerWithInterval(NSTimeInterval(newValue))
}
func timerDidFire()
{
// Do something with the imageView
}
private func startTimerWithInterval(seconds: NSTimeInterval)
{
if self.timer != nil { self.timer.invalidate() }
self.timer = NSTimer(timeInterval: seconds, target: self, selector: Selector("timerDidFire"), userInfo: nil, repeats: true)
}
}

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