teyso
teyso

Reputation: 41

Swift button error on iOS app but not in playground

I am trying to learn swift to make free educational app for my country.

I know only the basics of programming and swift, but I am trying to understand iOS development.

I think I am having a problem with scope, but not sure what to do.

With didMoveToView being (the required) according to books I read, I can't compile and execute the code. So, when I run it in Xcode iOS App Project, my App crashes (even though it works in playground).


The code:

import UIKit
class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()

    class fooo {
        static var bar = "hello world!"

        @IBAction func hello_button(sender: AnyObject) {
            print(fooo.bar)
        }
    }

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


}

Below is the Crash log (Occurs on button touch):

2016-08-26 07:22:00.512 k[2074:37791] -[k.ViewController hello_button:]: unrecognized selector sent to instance 0x7aa2e670
2016-08-26 07:22:00.521 k[2074:37791] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[k.ViewController hello_button:]: unrecognized selector sent to instance 0x7aa2e670'
*** First throw call stack:
(
    0   CoreFoundation                      0x00200494 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x01f17e02 objc_exception_throw + 50
    2   CoreFoundation                      0x0020a253 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
    3   CoreFoundation                      0x0013f89d ___forwarding___ + 1037
    4   CoreFoundation                      0x0013f46e _CF_forwarding_prep_0 + 14
    5   libobjc.A.dylib                     0x01f2c0b5 -[NSObject performSelector:withObject:withObject:] + 84
    6   UIKit                               0x009f2e38 -[UIApplication sendAction:to:from:forEvent:] + 118
    7   UIKit                               0x009f2db7 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 64
    8   UIKit                               0x00b96f3b -[UIControl sendAction:to:forEvent:] + 79
    9   UIKit                               0x00b972d4 -[UIControl _sendActionsForEvents:withEvent:] + 433
    10  UIKit                               0x00b962c1 -[UIControl touchesEnded:withEvent:] + 714
    11  UIKit                               0x00a7352e -[UIWindow _sendTouchesForEvent:] + 1095
    12  UIKit                               0x00a745cc -[UIWindow sendEvent:] + 1159
    13  UIKit                               0x00a15be8 -[UIApplication sendEvent:] + 266
    14  UIKit                               0x009ea769 _UIApplicationHandleEventQueue + 7795
    15  CoreFoundation                      0x00112e5f __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
    16  CoreFoundation                      0x00108aeb __CFRunLoopDoSources0 + 523
    17  CoreFoundation                      0x00107f08 __CFRunLoopRun + 1032
    18  CoreFoundation                      0x00107846 CFRunLoopRunSpecific + 470
    19  CoreFoundation                      0x0010765b CFRunLoopRunInMode + 123
    20  GraphicsServices                    0x04717664 GSEventRunModal + 192
    21  GraphicsServices                    0x047174a1 GSEventRun + 104
    22  UIKit                               0x009f0eb9 UIApplicationMain + 160
    23  k                                   0x00012581 main + 145
    24  libdyld.dylib                       0x02935a25 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

Upvotes: 3

Views: 158

Answers (2)

Fluidity
Fluidity

Reputation: 3995

You're right, the issue is scope (assuming you connected your button properly as others mentioned):


import UIKit

class ViewController: UIViewController {

    class fooo {
        var bar = "hello world!"
        func mSayBar() { print(self.bar)}
    }

    var foo = fooo()

    @IBAction func hello_button(sender: AnyObject) {
        foo.mSayBar()
    }

    override func viewDidLoad() {
        super.viewDidLoad()


    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

viewDidLoad is it's own local scope--it doesn't extend any further than the end brace " } " After the first (millisecond?) everything declared in VDL is no longer alive; thus, it is best for initializing or calling, not declaring.

To declare global, just put everything in a new swift file, or put it outside ALL class scopes. Swift makes global scope easy (but be careful)

You said viewDidLoad is required, which is true, but only for setting up the program. Most of your logic / functions go outside of viewDidLoad

Upvotes: 4

nstosic
nstosic

Reputation: 2614

unrecognized selector sent to instance 0x7aa2e670 means that the button has been linked to an IBAction outlet that isn't defined in your code. Go to your ViewController's Storyboard mode, and right click the button in the subview list. Check if there is an outlet for the Touch Up Inside event and if it has the same name as the function in your code that you want to call (in your case it's hello_button.

Here's a picture if you didn't understand the above paragraph.

enter image description here

Upvotes: 2

Related Questions