-1

.xib file (Interface), Show the Identity Inspector Tab I am new to Xcode and Swift, and was trying to run a simple multiplication game app. However, when I try to run a test on the simulator, I receive a SIGABRT signal error, and the app does not load. I am not sure how to approach this, please help! I have tries everything and nothing seems to work. Note: I am not using storyboards, and have deleted the main.storyboard file from the project folder, focusing on the xib file (I am using Xcode 10.3)

The Error I receive is:

Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key inputField.'

// This is my AppDelegate. I receive the SIGABRT signal on the third line (class AppDelegate). 


import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var mainVC: MainViewController?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        mainVC = MainViewController(nibName: "MainViewController", bundle:nil)

        let frame = UIScreen.main.bounds
        window = UIWindow(frame:frame)

        window!.rootViewController = mainVC
        window!.makeKeyAndVisible()

        return true
    }

}

Separate file

//MainViewController.swift, created with MainViewController.xib

import UIKit

class MainViewController: UIViewController
{   
@IBOutlet weak var number1:UILabel?
@IBOutlet weak var number2:UILabel?
@IBOutlet weak var timeLabel:UILabel?
@IBOutlet weak var scorecounter:UILabel?
@IBOutlet weak var inputField:UITextField?

var score:Int = 0
var timer:Timer?
var seconds:Int = 60

override func viewDidLoad()
{
    super.viewDidLoad()
    setRandomNumberLabel1()
    setRandomNumberLabel2()
    updateScoreLabel()

    inputField?.addTarget(self, action: #selector(textFieldDidChange(textField:)), for:UIControl.Event.editingChanged)
}

func updateScoreLabel()
{
    scorecounter?.text = "\(score)"
}

func updateTimeLabel()
{
    if(timeLabel != nil)
    {
        let min:Int = (seconds / 60) % 60
        let sec:Int = seconds % 60

        let min_p:String = String(format: "%02d", min)
        let sec_p:String = String(format: "%02d", sec)

        timeLabel!.text = "\(min_p):\(sec_p)"
    }
}

func setRandomNumberLabel1()
{
    number1?.text = generateRandomString()
}

func setRandomNumberLabel2()
{
    number2?.text = generateRandomString()
}

@objc func textFieldDidChange(textField:UITextField)
{
    if inputField?.text?.count ?? 0 < 1
    {
        return
    }

    if  let number1_text    = number1?.text,
        let number2_text    = number2?.text,
        let input_text      = inputField?.text,
        let number1 = Int(number1_text),
        let number2 = Int(number2_text),
        let input   = Int(input_text)
    {
        print("Comparing: \(input_text) == \(number1_text) times \(number2_text)")

        if(input == number1 * number2)
        {
            print("Correct!")

            score += 1
        }
        else
        {
            print("Incorrect!")

            score -= 1
        }
    }

    setRandomNumberLabel1()
    setRandomNumberLabel2()
    updateScoreLabel()
    updateTimeLabel()

    if(timer == nil)
    {
        timer = Timer.scheduledTimer(timeInterval: 1.0, target:self, selector:#selector(onUpdateTimer), userInfo:nil, repeats:true)
    }
}

@objc func onUpdateTimer() -> Void
{
    if(seconds > 0 && seconds <= 60)
    {
        seconds -= 1

        updateTimeLabel()
    }
    else if(seconds == 0)
    {
        if(timer != nil)
        {
            timer!.invalidate()
            timer = nil

            let alertController = UIAlertController(title: "Game Over!", message: "Time's up! You got a score of: \(score) points. Good Job!", preferredStyle: .alert)

            let restartAction = UIAlertAction(title: "Restart", style: .default, handler: nil)
            alertController.addAction(restartAction)

            self.present(alertController, animated: true, completion: nil)

            score = 0
            seconds = 60

            updateTimeLabel()
            updateScoreLabel()
            setRandomNumberLabel1()
            setRandomNumberLabel2()
        }
    }
}

override func didReceiveMemoryWarning()
{
    super.didReceiveMemoryWarning()
}

func generateRandomString() -> String
{
    var result:String = ""

    for _ in 1...1
    {
        let digit = Int.random(in: 1..<10)

        result += "\(digit)"
    }

    return result
}
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
Nexpert101
  • 13
  • 6
  • There should be an error message in Console, no? (https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/debugging_with_xcode/chapters/debugging_tools.html) Which one? – Larme Oct 11 '19 at 12:59
  • 2019-10-11 09:04:54.813996-0400 MinuteMath[1588:32715] libMobileGestalt MobileGestalt.c:890: MGIsDeviceOneOfType is not supported on this platform. 2019-10-11 09:04:54.918769-0400 MinuteMath[1588:32715] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Could not find a storyboard named 'Main' in bundle NSBundle – Nexpert101 Oct 11 '19 at 13:06
  • First : Edit your question with that error message, and do you have a Storyboard named Main at least? Is it part of the target of your app? – Larme Oct 11 '19 at 13:07
  • Story board name in segue is not set properly click on threads and check the identifier of each one also check the story board name in Attribute inspector title – Ali Xhah Oct 11 '19 at 13:12
  • Maybe you've created a new (storyboard) application but then tried to make it work in XIB based way. If that's the case select your project then select your target and in General tab there is a `Main interface` field. Clear it. – demosten Oct 11 '19 at 13:12
  • Alright, and I was using a tutorial to build the app, and was told to delete the storyboard file because it was not going to be needed. Is there a way to work around it? Or will I have to go back and recreate that – Nexpert101 Oct 11 '19 at 13:12
  • Ok, I will try that. – Nexpert101 Oct 11 '19 at 13:13
  • I went back to the General tab and saw the Main Interface was set to Main. I removed that and replaced it with MainViewController. However, I still get the SIGABRT error, with the following message displaying on the console: MinuteMath[1898:40837] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key inputField.' – Nexpert101 Oct 11 '19 at 13:19
  • Your view controller may have the wrong class in your xib. Bad Outlet. You have either removed or renamed an outlet name in your .h file. Remove it in .xib or .storyboard file's Connection Inspector. – Ali Xhah Oct 11 '19 at 13:23

1 Answers1

0

Change your outlets to be non-optional:

@IBOutlet weak var number1: UILabel!
@IBOutlet weak var number2: UILabel!
@IBOutlet weak var timeLabel: UILabel!
@IBOutlet weak var scorecounter: UILabel!
@IBOutlet weak var inputField: UITextField!
  1. Open your viewController in your Storyboard and select your controller:

enter image description here

  1. Check the menu on the right. It should have changed to have the last icon, an arrow, selected. Your outlets should be there:

enter image description here

  1. Connect your outlets to each element on the view. You can do this by clicking on the empty radio button on each element and dragging the cursor:

enter image description here

  1. Build and run the project again.

If by any chance you can't see the outlets in step 2, you might have a wrong reference to your class. After step 1, click on the middle button on the right menu:

enter image description here

If the class field doesn't match your controller, change to it. Based in your code, yours should be MainViewController. Set that and go back to step 2.

Marina Aguilar
  • 1,151
  • 9
  • 26
  • Thank you for your response! Is there a way to go about this without using storyboards? I deleted the main.storyboard file from my project, as the assignment said it would not be used for this project. I changed my outlets to non-optional as you said, and ensured that the outlets are connected to the correct element on the view. – Nexpert101 Oct 11 '19 at 15:00
  • Yes, but you will need to create a .xib file to connect the elements. You can also go with view code and don't use any interface resources, just adding the elements via code. Which alternative suits your case the best? – Marina Aguilar Oct 11 '19 at 15:51
  • I have already created an .xib with all of the outlets connected to the elements on the interface, and I'm still getting the same error. :/ I have updated the question so you can see the interface and elements (attached at top) – Nexpert101 Oct 11 '19 at 16:04
  • Can you post a screenshot of your middle icon section? The "Show the Identity inspector" one? – Marina Aguilar Oct 11 '19 at 16:12
  • Alright, just posted it – Nexpert101 Oct 11 '19 at 16:22