App just crashes when changing station? - AppDelegate error - swift

So I am getting the following error code
Thread 1: Exception: "-[__NSCFTimer copyWithZone:]: unrecognized selector sent to instance 0x281e8a1c0"
However I have no idea what sent to what instance the error is highlighted on this line
class AppDelegate: UIResponder, UIApplicationDelegate {
The only command I ran is the following
#objc func playdrn1(sender:UIButton!){
MusicPlayer.shared.startBackgroundMusic(url: "http://stream.radiomedia.com.au:8006/stream?uuid=\(uuid ?? "")")
nowplaying(npurl:"https://api.drn1.com.au/station/DRN1/playing")
}
I have narrowed the error to the nowplaying function.
it seems not to like the fact am looping or something like that
func scheduledTimerWithTimeInterval(){
// Scheduling timer to Call the function "updateCounting" with the interval of 1 seconds
timer = Timer.scheduledTimer(timeInterval: 30, target: self, selector: #selector(self.nowplaying), userInfo: nil, repeats: true)
}
The issue is am not sending npurl info with the self.nowplaying.
#selector(self.nowplaying)
How can I make #objc func nowplaying(npurl:String){ run without resending the npurl?

The signature #objc func nowplaying(npurl:String) { is wrong. You cannot pass a custom parameter type
A timer action method can have two forms
#objc func nowplaying() { ...
and
#objc func nowplaying(_ timer : Timer) { ...
Either pass the string in the userInfo dictionary or create a temporary property.

Related

Does not implement methodSignatureForSelector and unrecognized selector when using Timer

Here I have a simple class that prints "test" several times a second:
import Foundation
class TestClass {
static var count = 0
static var timer = Timer()
init() {
TestClass.start()
}
static func start() {
TestClass.timer = Timer.scheduledTimer(timeInterval: 1.0/5.0, target: self, selector: #selector(printTest), userInfo: nil, repeats: true)
}
#objc func printTest() {
print(count)
count += 1
}
}
I made the function start the variable timer static so that later on I can start and stop the timer from another class
In my main ViewController file, I simply make a new TestClass by saying:
let _ = TestClass()
Then I try to stop and start the timer by doing:
if /*something*/ {
TestClass.timer.invalidate()
}
if /*something else*/ {
TestClass.start()
}
However when I run the project, I get multiple errors in the console:
NSForwarding: warning: object 0x10eaab580 of class 'DeleteMe.TestClass' does not implement methodSignatureForSelector: -- trouble ahead
and
Unrecognized selector +[DeleteMe.TestClass printTest]
Is there something I have to modify in the class to resolve the errors?
The problem is that start is a static method so self is the class, not an instance. This means that printTest also needs to be static.
But why are these static? Why create an instance just to call the static start method?
Get rid of init and simply use TestClass.start().
Or make everything a proper instance property and instance method. Then you can create separate instances of TestClass each their own timer.

Swift Runtime exception: unrecognized selector

In my ViewController class, I have a function:
func updateTimes() {
// (code)
}
I create a timer:
class ViewController: NSViewController {
var timer = Timer.scheduledTimer(timeInterval: 5,
target: self,
selector:
#selector(ViewController.updateTimes),
userInfo: nil,
repeats: true)
The compiler is happy with this. At runtime, when the timer fires, I get an exception:
unrecognized selector sent to instance 0x6000000428b0
Am I doing something obviously wrong?
As I wrote as a comment on NaGib ToroNgo's answer, he has given us a nice suggestion.
The selector may not be sent to the instance of ViewController.
I guess the ViewController would be taking this form:
class ViewController: UIViewController {
var timer = Timer.scheduledTimer(timeInterval: 5,
target: self,
selector: #selector(ViewController.updateTimes),
userInfo: nil,
repeats: true)
//...(Other property declarations or method definitions)...
func updateTimes() {
// (code)
}
}
The variable timer is declared as an instance property, and self is used in an initial value of timer. (In some old versions of Swift, this sort of usage caused error, so I was thinking that this line exists in any of the methods.)
In the current version of Swift (tested with Swift 3.1/Xcode 8.3.3), the code above does not cause error, but self is interpreted as a method reference of self() method declared in NSObjectProtocol. So, Selector("updateTimes") is sent to the closure representing the method reference (curried function), not to the instance of the ViewController.
The closure does not have a method named updateTimes, which caused the exception:
unrecognized selector sent to instance
Move the initial value code into some instance context, and then self represents the instance of the ViewController:
class ViewController: UIViewController {
var timer: Timer? //<- Keep `timer` as an instance property, but move the initial value code into `viewDidLoad()`.
//...(Other property declarations or method definitions)...
override func viewDidLoad() {
super.viewDidLoad()
//Do initialize the timer in the instance context.
timer = Timer.scheduledTimer(timeInterval: 5,
target: self,
selector: #selector(self.updateTimes),
userInfo: nil,
repeats: true)
//...
}
//In Swift 3, `#objc` is not needed, just for a preparation for Swift 4
#objc func updateTimes() {
// (code)
}
}
I believe this does not cause unrecognized selector exception.
The code you have provided seems perfect. I think the problem is, somehow your view controller is getting released or having dangling pointer.
Its time to say good bye to selectors!!! use the below code
Timer.scheduledTimer(withTimeInterval: 5, repeats: true) { (timer) in
// check self for nil before using
}

Repeat function using NSTimer fails with target: self in Swift

I found this question and tried to copy the code to my Xcode project, but I'm getting the following error message.
error: use of unresolved identifier 'self'
What's the right way?
EDIT: Here the code, tested in a playground:
//: Playground - noun: a place where people can play
import Cocoa
import Foundation
func sayHello() {
print("hello World")
}
var SwiftTimer = NSTimer()
SwiftTimer = NSTimer.scheduledTimerWithTimeInterval(1, target:self, selector: Selector("sayHello"), userInfo: nil, repeats: true)
Usually using uppercase to the properties name it's considered as a bad attitude, you should use swiftTimer.
These expressions are not allowed ad the top level:
var swiftTimer = NSTimer()
swiftTimer = NSTimer.scheduledTimerWithTimeInterval(1, target:self, selector: Selector("sayHello"), userInfo: nil, repeats: true)
You must put it in a function like for example:
override func viewDidLoad() {
super.viewDidLoad()
var swiftTimer = NSTimer()
swiftTimer = NSTimer.scheduledTimerWithTimeInterval(1, target:self, selector: Selector("sayHello"), userInfo: nil, repeats: true)
}
self refers to the object for which a method (a function defined within a class) is defined, so can only be used in a method. (It is the equivalent of this in C++/Java/Javascript.) In your code, sayHello() is a global function, not a method, so there is no self to refer to.
In order for the scheduledTimerWithTimeInterval() function call to work with those arguments, it must be called within an instance method so that there is a self, and that class must have a method named sayHello().
You could also change the target: to another object as long as that object has a sayHello() method.
Basically an asynchronous timer doesn't work in a Playground and a since the top level of a Playground isn't a class there is no self property.
To test NSTimer in a Playground
Wrap the timer in a class.
Import XCPlaygound.
Add XCPlaygroundPage.currentPage.needsIndefiniteExecution = true to enable support of asynchronous tasks.

NSTimer Swift difficulty

I am trying to create a NSTimer so that I can move a UIImageView down but
The NSTImer is having difficulty, saying first that this.
var timer = NSTimer.scheduledTimerWithTimeInterval(0.5, target:self(), selector: Selector ("mrockdown"), userInfo: nil, repeats: true)
is missing argument for parameter #1 in call. But when I remove the brackets from the target:self() it tells me
Cannot invoke 'scheduledTimerWIthTimerInterval' with an argument list of type '(Double, target: ViewController -> () -> ViewController, selector: Selector, userinfo: nil, repeates Bool.
What should I do?
The problem has to do with where you are saying this. It looks like you are trying to say this as part of a property declaration:
class ViewController {
var timer = ...
// ...
}
But you can't do that, because there is no self as far as a stored property is concerned. You need to declare the timer as an Optional and then initialize it later:
class ViewController {
var timer = NSTimer!
func someMethod {
timer = ...
}
}
Then you will remove the parentheses (they are wrong) and everything will compile just fine.
You can do this inside the function where you want to trigger the timer (i.e. viewDidLoad or some IBAction)
_ = Timer.scheduledTimer(timeInterval: yourInterval, target: self, selector: #selector(yourFunction), userInfo: nil, repeats: true)
That being said, to animate a view you should use this instead:
UIView.animate(withDuration: yourDuration) {
// set yourView's final position here
}

NSUnknownKeyException this class is not key value coding-compliant for the key

So I am working through a tutorial and I have made sure that I followed the author to the letter and my code throws the following error.
2014-10-01 22:26:14.545 stopwatch2[3503:861733] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<stopwatch2.ViewController 0x7c57f050> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key pause.'
My Question is:
Based on the error provided what is the reason my application is failing ?
Here's my code that won't compile:
import UIKit
class ViewController: UIViewController {
var timer = NSTimer()
#IBOutlet var time : UILabel!
var count = 0
#IBAction func play(sender : AnyObject) {
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("result"), userInfo: nil, repeats: true)
}
#IBAction func pause(sender : AnyObject) {
timer.invalidate()
}
#IBAction func reset(sender : AnyObject) {
timer.invalidate()
count = 0
time.text="0"
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
func result() {
count++
time.text = String(count)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
What I would really like to know, is how to investigate this on my own because I am sure the authors other videos will yield the same results.
The videos are from udemy.com, The Complete iOS8 and Swift Course..
Thanks in advance for any help.
"this class is not key value coding-compliant for the key pause" usually means you have a referencing outlet problem. Look in the Connections Inspector for your different buttons. You may likely either have:
2 referencing outlets for one button and the program does not know which ne to use, etc.
I ran the code hooking up 1 label to an IBOutlet and three buttons (play, pause, reset), one to each IBAction, and it ran perfectly.