I recently updated my app to Swift 2, and had one error, which I solved thanks to you guys.
And now, I have a second error, which is at runtime, when I press the one button to play a sound. It is a signal SIGABRT error.
Here is the error message I get in the debug console:
2016-01-25 09:16:09.019 WarningShot1.0.0[291:19030] -[WarningShot1_0_0.ViewController playMySound:]: unrecognized selector sent to instance 0x135547d30
2016-01-25 09:16:09.021 WarningShot1.0.0[291:19030] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[WarningShot1_0_0.ViewController playMySound:]: unrecognized selector sent to instance 0x135547d30'
*** First throw call stack:
(0x182835900 0x181ea3f80 0x18283c61c 0x1828395b8 0x18273d68c 0x18755fe50 0x18755fdcc 0x187547a88 0x18755f6e4 0x18755f314 0x187557e30 0x1875284cc 0x187526794 0x1827ecefc 0x1827ec990 0x1827ea690 0x182719680 0x183c28088 0x187590d90 0x10005e2e0 0x1822ba8b8)
libc++abi.dylib: terminating with uncaught exception of type NSException
Also, this is the part of the code where it throws this error, in the second line, where the class is declared:
import UIKit
#UIApplicationMain
-> class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
What is happening here? What am I missing / misnaming? What do I need to change in my code to get ot running again. This app is ridiculously simple, and worked for months under the last version of Swift. Why is it now giving me errors?
Thank you for your help.
Here is the code for my ViewController.swift file:
import UIKit
import AVFoundation
import CoreMotion
class ViewController: UIViewController {
var myPlayer = AVAudioPlayer()
var mySound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("RemSound_01", ofType: "wav")!)
func initYourSound() {
do {
try myPlayer = AVAudioPlayer(contentsOfURL: mySound, fileTypeHint: nil)
myPlayer.prepareToPlay()
// myPlayer.volume = 1.0 // < for setting initial volume, still not perfected.
} catch {
// handle error
}
var motionManager = CMMotionManager()
var currentMaxAccelY : Double = 0.0
func viewDidLoad() {
super.viewDidLoad()
initYourSound()
// Do any additional setup after loading the view, typically from a nib.
//set motion manager properties
motionManager.accelerometerUpdateInterval = 0.17
//start recording data
// motionManager.startAccelerometerUpdatesToQueue(NSOperationQueue.currentQueue(), withHandler: {
// (accelerometerData: CMAccelerometerData!,error:NSError!) -> Void in
// self.outputAccelerationData(accelerometerData.acceleration)
// if(error != nil) {
// print("\(error)")
// }
// })
motionManager.startAccelerometerUpdatesToQueue(NSOperationQueue.currentQueue()!, withHandler: {
(accelerometerData,error) in outputAccelerationData(accelerometerData!.acceleration)
if(error != nil) {
print("\(error)", terminator: "")
}
})
}
//func outputAccelerationData(acceleration : CMAcceleration){
// accY?.text = "\(acceleration.y).2fg"
//if fabs(acceleration.y) > fabs(currentMaxAccelY)
//{
// currentMaxAccelY = acceleration.y
//}
// maxAccY?.text = "\(currentMaxAccelY) .2f"
//}
func outputAccelerationData(acceleration : CMAcceleration){
if fabs(acceleration.y) >= 1.25 {
myPlayer.play()
}
}
func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func playMySound(sender: AnyObject) {
myPlayer.play()
}
// self.resetMaxValues()
// #IBOutlet var accY: UILabel!
// #IBOutlet var maxAccY: UILabel!
// #IBAction func resetMaxValues() {
// currentMaxAccelY = 0
// }
}
}
"unrecognized selector sent to instance" means that there is a mismatch between the action-name in "addTarget()" and the name of the function you want to call. Probably something with the parameters of the function.. It's hard to say without seeing any code.
action: Selector("playMySound:")
would expect to find a function:
func playMySound(sender: AnyObject?) {};
To easier track what's happening, you might add a symbolic breakpoint for all exceptions. You do that in Xcode on the "exceptions" tab (left part of the window) and when an exception is thrown, Xcode stops like usual and you might look up the stack trace. If the call is synchronous, you should easily find and see your mistake.
EDIT: Oh well, you seem to have done the user interface using a XIB file. The mistake could be, you wired the button's action in the XIB file to the view controller. If you later change the method's signature (parameter, name, etc.), UIKit can't find the method. Open the XIB and fix your error. ;-)
Related
import AVFoundation
import UIKit
class ViewController: UIViewController {
#IBOutlet var button: UIButton!
var player: AVPlayer?
var playerItem:AVPlayerItem?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func didTapButton(urlRadio: String){
if let player = player, player.isMuted{
//stop playback
}
else{
do {
try AVAudioSession.sharedInstance().setMode(.default)
try AVAudioSession.sharedInstance().setActive(true, options: .notifyOthersOnDeactivation)
guard let urlRadio = URL.init(string: "http://live.shtorm.fm:8000/mp3_rushtorm") else {
return
}
let playerItem:AVPlayerItem = AVPlayerItem.init(url: urlRadio)
player = AVAudioPlayer.init(playerItem: playerItem)
}
catch {
print("something went wrong")
}
}
}
}
shows error Exception NSException * "-[RozetkaRadio.ViewController didTapButton]: unrecognized selector sent to instance 0x7ff070f07a50" 0x00006000008c7210 after pressing button in emulator
using storyboard
Your issue is with this line of code. Specifically, the parameter urlRadio.
#IBAction func didTapButton(urlRadio: String){
It looks like you have changed the standard IBAction from what was set in storyboard. You cannot change the parameters in an IBAction as the storyboard no longer recognizes where to send the tap to.
Your IBAction should look something like this
#IBAction func didTapButton(_ sender: Any)
Whenever you see Unrecognized selector sent to instance you should immediately think "Something is not hooked up properly between my storyboard and my ViewController"
One quick way to look is by right clicking your controller scene name on the storyboard. You can see I commented out my SignIn IBAction function. If I wanted to remove it I would have to also remove the connection on the storyboard. You can see the storyboard will let me know by leaving a yellow warning label.
Exception NSException * "-[Xylophone.ViewController buttonClicked:]:
unrecognized selector sent to instance
0x7faa47409400" 0x0000600002148690
I'm trying to make a xylophone app in which the buttons would play different sounds, there are 7 buttons however only the first button doesn't work, all other buttons work. on pressing the first button the app crashes.
Here is the code:
import UIKit
import AVFoundation
class ViewController: UIViewController {
var player: AVAudioPlayer!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func keyPressed(_ sender: UIButton) {
playSound(soundName: sender.currentTitle!)
}
func playSound(soundName:String) {
let url = Bundle.main.url(forResource: soundName, withExtension: "wav")
player = try! AVAudioPlayer(contentsOf: url!)
player.play()
}
}
what is the issue here?
I faced the same issue and here's how I solved it:
right-click every button you have in Main.storyboard, and check the connection it has in the small menu like this:
When I had more than one connection it gave me this error.
Here is the problematic ViewController class.
class ViewController: UIViewController {
#IBOutlet weak var photoSelectActionSheet: UIButton!
#IBOutlet weak var selectedImageView: UIImageView!
var imagePicker: UIImagePickerController!
var selectedImage: UIImage? = ni
var iCloud = ICloud() // see below for code of that file
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Must use this system to check each time the view appears.
// This is checked each time so if user goes into settings and come back in same session
// then this will be updated => viewDidLoad is cached and not reloaded each time.
NotificationCenter.default.addObserver(
self,
selector:#selector(ICloud.checkIfUserIsLoggedInIcloud), // PROBLEM IS HERE
name: UIApplication.didBecomeActiveNotification,
object: nil)
}
// more code not shown
}
Problem is in viewWillAppear: the notification center calls a selector that is in an other Model file ICloud.swift:
import UIKit
import CloudKit
class ICloud {
var isLoggedInIcloud: Bool? = nil
var userIcloudId: String? = nil
func getUserIcloudId() {
// Run this only if user is logged into icloud, and we don't have yet its iCloud id.
if isLoggedInIcloud ?? false && userIcloudId == nil {
CKContainer.default().fetchUserRecordID(completionHandler: { (recordId, error) in
if let id = recordId?.recordName {
print("userIcloudId set to: " + id)
self.userIcloudId = id
}
else if let error = error {
print(error.localizedDescription)
}
})
}
}
#objc func checkIfUserIsLoggedInIcloud() {
// Check if user is logged into iCloud
CKContainer.default().accountStatus { accountStatus, error in
if accountStatus == .available {
self.isLoggedInIcloud = true
print("isLoggedInIcloud set to true")
self.getUserIcloudId()
return
}
print("User is not logged into icloud")
}
}
}
I expected "ICloud.checkIfUserIsLoggedInIcloud" passed in selector to work. It doesn't:
2020-07-01 11:46:12.931419+0200 QDog[53348:3422745] -[QDog.ViewController checkIfUserIsLoggedInIcloud]: unrecognized selector sent to instance 0x7fcad5f0c1d0
2020-07-01 11:46:12.938567+0200 QDog[53348:3422745] *** Terminating app due to uncaught exception
If I add back the functions and variables from ICloud.swift directly into the ViewController file and pass to the selector "checkIfUserIsLoggedInIcloud" it WILL WORK properly.
I wanted to put all icloud code into a separate model file for separation of concerns and to make the code more clear.
Question is: why does 'ICloud.checkIfUserIsLoggedInIcloud' passed as selector doesn't work? And how to make this work with ICloud code in its own file, and not in ViewController file?
According to the documentation, the first parameter should be the observer, which in your case you're pointing to self.
In this case, self is your ViewController, which doesn't have the method checkIfUserIsLoggedInIcloud. In order to make it work, as an observer, you need to pass the property iCloud instead of self.
I have just started to code, but I have already encountered some error which I cannot figure out. Would you please help me?
class ViewController: UIViewController {
#IBOutlet var getNumber: UITextField!
#IBAction func computePrime(_ sender: AnyObject) {
if let userString = getNumber.text { // Convert input to Int
let userNumber = Int(userString)
if let number = userNumber {
var i = 2 // Variable declaration
var prime = true
while i < number { // Prime calculation
if number & i == 0 {
prime = false
i = number
} else {
i += 1
}
}
if prime == false { // Output result
displayResult.text = "It is not prime"
} else {
displayResult.text = "It is prime"
}
} else {
displayResult.text = "Please enter a positive whole number" // Error message in case value entered is not good
}
}
}
#IBOutlet var displayResult: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
When I try to run it, the app crashes and it gives me this error:
"Thread 1: signal SIGABRT"
highlighting this line:
"class AppDelegate: UIResponder, UIApplicationDelegate {"
from the AppDelegate.swift file, which I have not modified.
How can I fix it?
Thank you!
Probably you don't have connected in Storyboard the getNumber and displayResult (IBOutlet) object.
Check that answer:
IBOutlet not connecting in SWIFT
The highlighted line is at the application delegate because the system regressed all the way back to the top trying to find a layer with an exception handler for the exception that was thrown. Check the last few lines of the Xcode console for a description of the exception which may tell you where it was caused.
You can add an "Exception Breakpoint" to stop execution at the moment of the exception to see the point of origin. Many articles exist on how to do this.
class ABC{
#NSManaged var liked: Bool
.....
}
in other class
class xyz{
func afunc(){
let item = ABC()
if item.liked == true{ // getting crash on this line
}}}
[Error]: Type info TC,N,D not yet supported
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[...]: unrecognized selector sent to instance 0x15d78310'
* First throw call stack:
I am simply accessing a value that I have created in a class and
its working fine on one device(ios version 8.1 and 8.3) and throwing error on another device(ios version 8.4).
I think you have created swift class. Then it should be like below :
class ABC {
var liked = Bool()
}
class XYZ {
func execute() {
let item = ABC()
if item.liked == true { // getting crash on this line
}
}
}
class ClassA: NSObject {
var liked:Bool
override init() {
liked = true
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
execute();
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func execute(){
let item = ClassA();
if item.liked==true{
print(item.liked)
}
}
}