0
votes

I have a problem with the new "throws" - "try" parameters.

I get an Error to add these words and so I added the "throws" at the end of the IBAction Function.

@IBAction func loginButtonPressed(sender: AnyObject)throws {//code here}

Inside I'm dong some irrelevant stuff and then this:

let jsonData:NSDictionary = try NSJSONSerialization.JSONObjectWithData(urlData!, options:NSJSONReadingOptions.MutableContainers ) as! NSDictionary

After that there are no errors but when I run the app and click on the button, the app crashes with the code

2015-06-15 10:43:11.374 BottLED[7283:1175818] -[BottLED.loginViewController loginButtonPressed:]: unrecognized selector sent to instance 0x7fee28da7d20 2015-06-15 10:43:11.381 BottLED[7283:1175818] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[BottLED.loginViewController loginButtonPressed:]: unrecognized selector sent to instance 0x7fee28da7d20' * First throw call stack: ( 0 CoreFoundation 0x000000010d67c885 exceptionPreprocess + 165 1 libobjc.A.dylib 0x000000010cd0edf1 objc_exception_throw + 48 2 CoreFoundation 0x000000010d684b5d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205 3 CoreFoundation 0x000000010d5d1e3a ___forwarding_ + 970 4 CoreFoundation 0x000000010d5d19e8 _CF_forwarding_prep_0 + 120 5 UIKit 0x000000010dc46257 -[UIApplication sendAction:to:from:forEvent:] + 125 6 UIKit 0x000000010dc461b2 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 79 7 UIKit 0x000000010dda1422 -[UIControl sendAction:to:forEvent:] + 67 8 UIKit 0x000000010dda16c6 -[UIControl _sendActionsForEvents:withEvent:] + 272 9 UIKit 0x000000010dda08a9 -[UIControl touchesEnded:withEvent:] + 599 10 UIKit 0x000000010dcacbe8 -[UIWindow _sendTouchesForEvent:] + 835 11 UIKit 0x000000010dcad7d6 -[UIWindow sendEvent:] + 865 12 UIKit 0x000000010dc62705 -[UIApplication sendEvent:] + 263 13 UIKit 0x000000010dc3f5df _UIApplicationHandleEventQueue + 6031 14 CoreFoundation 0x000000010d5a70f1 CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION + 17 15 CoreFoundation 0x000000010d59ceac __CFRunLoopDoSources0 + 556 16 CoreFoundation 0x000000010d59c363 __CFRunLoopRun + 867 17 CoreFoundation 0x000000010d59bd78 CFRunLoopRunSpecific + 488 18 GraphicsServices 0x0000000111fdebca GraphicsServices + 52170 19 UIKit 0x000000010dc4479b UIApplicationMain + 171 20 BottLED 0x000000010c7cb9ad main + 109 21 libdyld.dylib 0x000000011029ca05 libdyld.dylib + 10757 22 ??? 0x0000000000000001 0x0 + 1 ) libc++abi.dylib: terminating with uncaught exception of type NSException (lldb)

when I do some breakpoints and delete the "throws", the app does not crash. I really don't know what to do now.. I hope someone can help me!

The full code is:

@IBAction func loginButtonPressed(sender: AnyObject)throws {
    var name:NSString = textFieldName.text!
    let pass:NSString = textFieldPw.text!
    if ( name.isEqualToString("") || pass.isEqualToString("") ) {
        let loginFailed = UIAlertView(title: "Failed to Signup",
            message: "Please fill in all Textfields",
            delegate: nil,
            cancelButtonTitle: "OK")
        loginFailed.show()
    } else {

            let post:NSString = "username=\(name)&password=\(pass)"

            NSLog("PostData: %@",post);

            let url:NSURL = NSURL(string: "my url")!

            let postData:NSData = post.dataUsingEncoding(NSASCIIStringEncoding)!

            let postLength:NSString = String( postData.length )

            let request:NSMutableURLRequest = NSMutableURLRequest(URL: url)
            request.HTTPMethod = "POST"
            request.HTTPBody = postData
            request.setValue(postLength as String, forHTTPHeaderField: "Content-Length")
            request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
            request.setValue("application/json", forHTTPHeaderField: "Accept")


            var reponseError: NSError?
            var response: NSURLResponse?

            var urlData: NSData?
            do {
                urlData = try NSURLConnection.sendSynchronousRequest(request, returningResponse:&response)
            } catch let error as NSError {
                reponseError = error
                urlData = nil
            }

            if ( urlData != nil ) {
                let res = response as! NSHTTPURLResponse!;

                NSLog("Response code: %ld", res.statusCode);

                if (res.statusCode >= 200 && res.statusCode < 300)
                {
                    let responseData:NSString  = NSString(data:urlData!, encoding:NSUTF8StringEncoding)!

                    NSLog("Response ==> %@", responseData);



                    let jsonData:NSDictionary = try NSJSONSerialization.JSONObjectWithData(urlData!, options:NSJSONReadingOptions.MutableContainers ) as! NSDictionary


                    let success:NSInteger = jsonData.valueForKey("success") as! NSInteger

                    //[jsonData[@"success"] integerValue];

                    NSLog("Success: %ld", success);

                    if(success == 1)
                    {
2
What is your full code? You need to wrap the try in a do-catch block. Are you doing this? - Fogmeister
no I don't. I'll post the whole code in right a minute - Luke Pistrol

2 Answers

1
votes

In Obj-C throws is a syntactic sugar for the Obj-C error: (NSError **)error parameter.

When you add throws to a method, it is secretly adding the parameter. Your method won't be loginButtonPressed: anymore, it will be loginButtonPressed:error: (at least for Obj-C). However, when the event is being handled, the system will still look for method loginButtonPressed: because that's how the event has been connected in the XIB. The method is not there anymore, so the app will crash with unrecognized selector sent to instance.

Solution: don't use throws in action handlers, it is violating the contract of the method because the system doesn't expect anything to be thrown there. Catch all errors inside your action handler.

do {
    urlData = try NSURLConnection.sendSynchronousRequest(request, returningResponse:&response)
} catch let error as NSError {
    reponseError = error
    urlData = nil
} catch {
   // Catch all error-handling
    urlData = nil
}
0
votes

Nothing can catch the error. You need to take your throws method out of the button IBAction.

Remove throws from the IBAction and create a new method. Then do try and catch the error in the method. Either way, don't throw from an IBAction.