This question already has an answer here:
NSTimer does not invoke a private func as selector
(1 answer)
Closed 7 years ago.
I'm getting a weird bug with my code, when I try to assign/run a timer its throwing an exception.
var timer: NSTimer?
self.timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "repeatData", userInfo: nil, repeats: true)
Here is my function
private func repeatData() {
print("test")
}
This throws
016-02-01 14:45:31.169 twu[43110:60021261] -[Test.Repeater repeatData:]: unrecognized selector sent to instance 0x7f848ba14e10
Error without :
2016-01-28 17:27:51.958 my_target[16476:48497867] -[Test.Repeater repeatData]: unrecognized selector sent to instance 0x7fd06bc1c310
2016-01-28 17:27:51.968 my_target[16476:48497867] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Test.Repeater repeatData]: unrecognized selector sent to instance 0x7fd06bc1c310'
I've tried it with and without the colon.
Your problem is that you repeatData is private. Just remove the private and your timer should work.
The methods being with selectors need to be accessible methods otherwise it wont find them, that's why it is crashing with the unrecognized selector error
The selector should be "repeatData". The colon means that the method takes a parameter which your implementation of repeatData does not.
Related
Using iOS 16.1 Xcode 14.1
Used reality converter to change my *.usd model into a *.usdz
Used reality composer to add a standard jiggle behavior and now trying to load it into my project.
But as it does so it crashes with this message...
2022-12-10 20:33:07.457940+0100 LAC[6905:4041138] -[USKObjectPath UTF8String]: unrecognized selector sent to instance 0x281a5c560
2022-12-10 20:33:07.458127+0100 LAC[6905:4041138] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[USKObjectPath UTF8String]: unrecognized selector sent to instance 0x281a5c560'
*** First throw call stack:
(0x186e59e88 0x1801878d8 0x186fce84c 0x186e6ffa0 0x186ed8350 0x195271bfc 0x1952710c4 0x1952783ac 0x195271238 0x1f8f9cf5c 0x1f8cd20f0 0x1f8cd2708 0x1f8cd23dc 0x1f8cd18a8 0x1f8d5225c 0x1f8f9000c 0x1f8f9026c 0x1f8f9026c 0x1f8f9093c 0x1f8f9128c 0x1f8f8eddc 0x1f8f92308 0x1f8f8efb8 0x201738af4 0x1f8f8dfac 0x1f8f8df48 0x1f8f247ec 0x1f8f338a8 0x1f8d3891c 0x1026945a8 0x10269605c 0x10269e10c 0x10269ee68 0x1026abcbc 0x1d3eafdf8 0x1d3eafb98)
libc++abi: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[USKObjectPath UTF8String]: unrecognized selector sent to instance 0x281a5c560'
terminating with uncaught exception of type NSException
Tried doing so with no behavior, it works! so the *.usdz file without the behavior is good... its clearly the standard behavior?
I should add that I can select the *.usdz file in xcode and it displays the content no problem, so the file it would appear isn't corrupted? I just missed something in the code when I import it.
Has anyone succeeded in doing this? These few lines will crash it.. the loadModel
let nextAsset = "rook12"
do {
let asset2Load = try Entity.loadModel(named:nextAsset)
} catch {
print("error \(error)")
}
Try load(named:in:) type method. It always saves the day.
Xcode 14.2 RC.
let nextAsset = "qwerty.usdz"
do {
let asset2Load = try Entity.load(named: nextAsset)
print(asset2Load)
let me = asset2Load.findEntity(named: "Mesh0")?.children[0] as? ModelEntity
me?.model?.materials[0] = UnlitMaterial(color: .orange)
let anchor = AnchorEntity()
asset2Load.setParent(anchor)
arView.scene.anchors.append(anchor)
} catch {
print("Error: \(error.localizedDescription)")
}
.usdz model's components' hierarchy.
I'm facing a NSInvalidArgumentException exception after upgrading a project to Swift 4.2 (conversion from 4.0).
2018-09-19 15:37:33.253482+0100 <redacted>-beta[3715:1010421] -[Swift._EmptyArrayStorage _getValue:forType:]: unrecognized selector sent to instance 0x107e6c290
2018-09-19 15:37:33.254312+0100 <redacted>-beta[3715:1010421] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Swift._EmptyArrayStorage _getValue:forType:]: unrecognized selector sent to instance 0x107e6c290'
It's something related with a NSMutableAttributedString and the code it's adding some attributes, for example, a NSAttributedString.Key.underlineStyle.
The exception happens when the attributed string is about to be assigned: textView.attributedText = mutableAttributedString.
UPDATE:
So, it's was working in Swift 4:
mutableAttributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.styleNone.rawValue, range: range)
Then, with Swift 4.2, the compiler suggests changing the NSUnderlineStyle.styleNone.rawValue to NSUnderlineStyle.none.rawValue
After that, the compiler starts yelling "'none' is unavailable: use [] to construct an empty option set":
mutableAttributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.none.rawValue, range: range)
^~~~~ 'none' is unavailable: use [] to construct an empty option set
I just found out what was wrong in the code.
So, because of the compiler error "'none' is unavailable: use [] to construct an empty option set", I replaced the NSUnderlineStyle.none.rawValue with [] 🤦♂️ And that's not the right case because it was using the rawValue, not the type none.
So, the fix is using 0.
Wrong: mutableAttributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: [], range: range)
Right: mutableAttributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: 0, range: range)
I've read the other posts. I've read the docs. I've read nearly everything I can get my hands on in regards to this issue, but it persists. To be clear, this problem ONLY happens if I want to capture the timer as a parameter in the receiving function.
Here's the error:
2016-03-07 18:26:29.000 AlarmClockAI[12286:3807622] -[AlarmClockAI.Alarm playAlarm]: unrecognized selector sent to instance 0x7fd0936289e0
I have a class derived from NSObject. In that class, I'm creating a series of timers like so:
timer = NSTimer(fireDate: fireDate, interval: 5.0, target: self, selector: Selector("playAlarm:"), userInfo: ["UUID":UUID], repeats: false)
NSRunLoop.currentRunLoop().addTimer(timer!, forMode: NSDefaultRunLoopMode)
func playAlarm(timer: NSTimer) {}
I still get the unrecognized selector error.
Other variations I've tried:
NSTimer(fireDate: fireDate, interval: 5.0, target: self, selector:"playAlarm:", userInfo: ["UUID":UUID], repeats: false)
Same error.
Other notes:
I'm running Swift 2.1.1
I realize I shouldn't need the #objc tag, but I've tried that too.
Clean + build + restart didn't help.
FML
Ugh. Sorry guys. I found the answer: I have more than one method that creates timers, and I was looking at the wrong one.
I recently started to update my app to Swift 2.0, but I've run into a problem that has a hundred different answers on SO, none of which seemed to be related to my problem.
(This worked before updating the application to Swift 2.0), but I havn't been able to find any changes made to tap gesture recognisers?
Here's the full error I'm getting:
[Stocks.SidePanelViewController proFormulaTapGesture]: unrecognized selector sent to instance 0x14f06ae00
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Stocks.SidePanelViewController proFormulaTapGesture]: unrecognized selector sent to instance 0x14f06ae00'
*** First throw call stack:
(0x1830904d0 0x197afff9c 0x1830971ec 0x183094188 0x182f9920c 0x188c3c58c 0x188899b50 0x18872d104 0x188c3bc30 0x1886ed28c 0x1886eb3ac 0x18872b088 0x18872a5ec 0x1886fb908 0x1886f9fac 0x183047d6c 0x183047800 0x183045500 0x182f75280 0x18e0ec0cc 0x188762df8 0x100158184 0x1983428b8)
libc++abi.dylib: terminating with uncaught exception of type NSException
It's a simple tap gesture. But it seems to not recognize the selector anymore.
Here's the code I use to set up the recognizer:
let proFormulaTap = UITapGestureRecognizer()
proFormulaTap.addTarget(self, action:"proFormulaTapGesture")
proFormulaView.addGestureRecognizer(proFormulaTap)
Here's the function I'm trying to run:
func proFormulaTapGesture() throws {
print("proFormulaTapGesture")
selectView(proFormulaView)
selectedMenuItem = 0
Formula = 1
menuTabBarController.selectedIndex = 0
navigationController?.navigationBar.topItem!.title = "BASIC FORMULA"
try (menuTabBarController.viewControllers as! [SuggestionsViewController])[0].loadSuggestions()
}
However since it never prints "proFormulaTapGesture" in the console. I definitely think the error occurs before the function. Also suggested by the error mentioning the selector.
Obviously try/catch has been added to the function since the update to Swift 2.0, but nothing has been changed in the setup of the tapGestureRecognizer.
I tried removing the "throws" and try from the function, but the problem perists. I also tried making a button instead of a tap gesture recognizer. But I'm still getting the same error, suggesting it might be a problem with the selector (function) and not the tap gesture / button. However all my other buttons in my app works just fine?
I also tried to rename the selector/function, and the tap gesture recognizer. Still the same.
The original Code was programmed in Swift, not Obj-C. The throws and try, was added during Apple's code conversion to Swift 2.0
Any help to why this is suddenly broken would be greatly appreciated.
Thanks!
The issue may be that UIKit does not know how to call a selector that throws, at least in this context.
Remember that UIKit will be calling this function in response to a tap action. It is not accustomed to calling a function that throws; obviously the throw must alter the method's call signature as far as the Objective-C runtime is concerned. Beyond that, if your function proFormulaTapGesture did throw an error, what would UIKit do with the error even if it could catch it?
I'm not sure where you added do/try/catch. But unless it was inside your action function proFormulaTapGesture, I do not see how it could be relevant. I believe that you will need to implement the try/catch error handling inside proFormulaTapGesture, so that it effectively swallows the error, so that proFormulaTapGesture does not throw.
I just created a quick test project myself and found that a throwing target action gives the same "Unrecognized selector" error you got:
override func viewDidLoad() {
super.viewDidLoad()
self.tapper = NSClickGestureRecognizer(target: self, action: "didClick")
self.view.addGestureRecognizer(self.tapper!)
}
func didClick() throws {
print("did click")
}
2015-07-27 00:16:43.260 Test1[71047:54227175] -[Test1.ViewController didClick]: unrecognized selector sent to instance 0x6000000c5010
...
I believe you will need to rework your code to handle the error internally in your action function so that it does not throw - something like this:
func proFormulaTapGesture() {
print("proFormulaTapGesture")
selectView(proFormulaView)
selectedMenuItem = 0
Formula = 1
menuTabBarController.selectedIndex = 0
navigationController?.navigationBar.topItem!.title = "BASIC FORMULA"
do {
try (menuTabBarController.viewControllers as! [SuggestionsViewController])[0].loadSuggestions()
} catch {
// Handle the error here somehow
}
}
If you are unable to handle the error within proFormulaTapGesture, you'll have to be more creative with passing it out of the function (think NSNotification, etc...).
To be clear, I created a new Single View iOS application in Xcode 7 beta 4, and used this exact code as my ViewController. No other changes. The app compiles and works just fine in the iOS simulator.
#robertvojta also points out that if didTap below is marked private, #objc is also required to avoid a dynamic dispatch crash.
import UIKit
class ViewController: UIViewController {
var tapper: UITapGestureRecognizer?
override func viewDidLoad() {
super.viewDidLoad()
self.tapper = UITapGestureRecognizer(target: self, action: "didTap")
self.view.addGestureRecognizer(self.tapper!)
}
func didTap() {
print("did Tap")
}
}
(Note I also tested on an OS X project, which is the code I used earlier in the answer).
I have a function with one parameter. This parameter has a default value. (true)
func disableButton(animated: Bool = true) {
if (animated) {
...
} else {
...
}
}
So i can call the function as:
disableButton(animated: true)
or:
disableButton()
and they give me the same result.
Now I have an NSTimer running a selector on completion like this:
buttonFadeTimer = NSTimer.scheduledTimerWithTimeInterval(NSTimeInterval(1.5), target: self, selector: Selector("disableButton"), userInfo: nil, repeats: false)
It will send the disableButton() message on completion. However on completion it causes the app to crash.
If i do:
func disableButton() {
disableButton(animated: true)
}
Then the timer successfully sends that message and the app does not crash.
Of course this is really ugly and kind of limits the great Swift feature of default parameters.
Is this a bug (that I should report) or am I doing it wrong?
Thanks for any help!
There's a difference between -disableButton and -disableButton: selectors. But you can't just use your desired selector like this:
buttonFadeTimer = NSTimer.scheduledTimerWithTimeInterval(NSTimeInterval(1.5), target: self, selector: Selector("disableButton:"), userInfo: nil, repeats: false)
because NSTimer here assumes selector with no arguments or selector with single argument (which will be used to pass firing NSTimer instance).
I believe, you should migrate from using selectors, as you want to use all that great features Swift delivers, as far as selectors is outdated pattern.
Just a note: it could work if you use "disableButton:" selector, maybe NSTimer's pointer will be interpreted as true and maybe not, not sure what will happen (maybe it could crash due to Swift strong typing stuff). But depending on that behaviour is a bad practice which could lead to bugs which are extremely hard to exterminate.