Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS

Completed Ribbit app now crashes in Xcode 6

I had fully completed the Ribbit app using Xcode 5 / iOS 7. Everything worked fine. I've now upgraded to Xcode 6 and am finding that I get an exception at runtime.

In viewDidLoad of RMInboxViewController.m, the problem seems to be that performSegueWithIdentifier isn't ever getting called even though it makes it inside the else statement (I've verified this with NSLogs and break points). I also double checked the segue identified in storyboard and it matches the code.

Everything worked 100% fine with Xcode 5. Any suggestions?

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.moviePlayer = [[MPMoviePlayerController alloc] init];

    PFUser *currentUser = [PFUser currentUser];
    if (currentUser) {
        NSLog(@"Current user: %@", currentUser.username);
    } else {
        [self performSegueWithIdentifier:@"showLogin" sender:self];
    }

    self.refreshControl = [[UIRefreshControl alloc] init];
    [self.refreshControl addTarget:self action:@selector(retrieveMessages) forControlEvents:UIControlEventValueChanged];
}

Here is the exception:

2014-10-17 18:17:39.475 Ribbit[3630:378619] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Cannot do a comparison query for type: (null)'
*** First throw call stack:
(
    0   CoreFoundation                      0x02f96df6 __exceptionPreprocess + 182
    1   libobjc.A.dylib                     0x028aea97 objc_exception_throw + 44
    2   CoreFoundation                      0x02f96d1d +[NSException raise:format:] + 141
    3   Ribbit                              0x0009e2d1 +[PFInternalUtils assertValidClassForQuery:] + 375
    4   Ribbit                              0x00084ecd -[PFQuery whereKey:equalTo:] + 91
    5   Ribbit                              0x0006a491 -[RMInboxViewController retrieveMessages] + 193
    6   Ribbit                              0x000692dc -[RMInboxViewController viewWillAppear:] + 236
    7   UIKit                               0x013f414f -[UIViewController _setViewAppearState:isAnimating:] + 545
    8   UIKit                               0x013f46ca -[UIViewController __viewWillAppear:] + 148
    9   UIKit                               0x01426389 -[UINavigationController _startTransition:fromViewController:toViewController:] + 931
    10  UIKit                               0x01426fdb -[UINavigationController _startDeferredTransitionIfNeeded:] + 669
    11  UIKit                               0x01427c52 -[UINavigationController __viewWillLayoutSubviews] + 57
    12  UIKit                               0x01599ebc -[UILayoutContainerView layoutSubviews] + 213
    13  UIKit                               0x013239c0 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 608
    14  libobjc.A.dylib                     0x028c4771 -[NSObject performSelector:withObject:] + 70
    15  QuartzCore                          0x00dea27f -[CALayer layoutSublayers] + 152
    16  QuartzCore                          0x00dde105 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 397
    17  QuartzCore                          0x00dddf60 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 26
    18  QuartzCore                          0x00d3c676 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 284
    19  QuartzCore                          0x00d3da3c _ZN2CA11Transaction6commitEv + 392
    20  QuartzCore                          0x00e03789 +[CATransaction flush] + 52
    21  UIKit                               0x012967e6 -[UIApplication _reportMainSceneUpdateFinished:] + 39
    22  UIKit                               0x01297761 -[UIApplication _runWithMainScene:transitionContext:completion:] + 3163
    23  UIKit                               0x012afd30 __84-[UIApplication _handleApplicationActivationWithScene:transitionContext:completion:]_block_invoke + 59
    24  UIKit                               0x01295d7f -[UIApplication workspaceDidEndTransaction:] + 155
    25  FrontBoardServices                  0x065369de __37-[FBSWorkspace clientEndTransaction:]_block_invoke_2 + 71
    26  FrontBoardServices                  0x0653646f __40-[FBSWorkspace _performDelegateCallOut:]_block_invoke + 54
    27  FrontBoardServices                  0x06548425 __31-[FBSSerialQueue performAsync:]_block_invoke + 26
    28  CoreFoundation                      0x02eba7a0 __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 16
    29  CoreFoundation                      0x02eb00b3 __CFRunLoopDoBlocks + 195
    30  CoreFoundation                      0x02eaff0b __CFRunLoopRun + 2715
    31  CoreFoundation                      0x02eaf1ab CFRunLoopRunSpecific + 443
    32  CoreFoundation                      0x02eaefdb CFRunLoopRunInMode + 123
    33  UIKit                               0x01295744 -[UIApplication _run] + 571
    34  UIKit                               0x01298e16 UIApplicationMain + 1526
    35  Ribbit                              0x00045aed main + 141
    36  libdyld.dylib                       0x03c56ac9 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)

6 Answers

Hey Jacob McLaws not sure if you've figured out the problem yet, but I had the same error tonight and found a fix. Aman Tohan was right about where the app was crashing. You can just add a quick if statement to check if your current user exists yet before executing the code to grab messages. This worked for me inside of the inbox view controller:

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];

    if ([PFUser currentUser]==nil) {
        [self performSegueWithIdentifier:@"showLogin" sender:self];
    }else{
    PFQuery *query=[PFQuery queryWithClassName:@"Messages"];
    //find all the images where they were sent to your username.
    [query whereKey:@"recipientIds" equalTo:[[PFUser currentUser]objectId]];
    [query orderByDescending:@"createdAt"];
    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
        if (error) {
            NSLog(@"Error: %@ %@",error,error.userInfo);
        }
        else{
            //means we found messages
            self.messages=objects;
            [self.tableView reloadData];
            NSLog(@"Retrieved %ld messages", [self.messages count]);
        }
    }];}
}

Hello again Jacob McLaws. I'm guessing you haven't finished the final course, Implementing Designs for iPhone in the iOS Development with Objective-C track where some changes occur to the code for organizing purposes. If this is the case then you'll find your query code for retrieving the messages in the - (void)viewWillAppear:(BOOL)animated method of the InboxViewController class. Please try wrapping the @try and @catch blocks as mentioned in my previous post accordingly.

I just realized that there's also some more code in relation to the final course in my previous post which I'll edit and add a comment for so you can ignore all of it completely. It has to do with the self.refreshControl.

Additionally, I just came across this discussion from about a month ago regarding a similar issue. There they have another proposed solution to the issue you guys are having by simply moving the code from the - (void)viewDidLoad method to the - (void)viewWillAppear:(BOOL)animated method.

Have you tried doing a Clean and then a Build from the Product drop down menu after the upgrade? I just tried doing that with my code and it fixed an issue I was having earlier with the 4" retina display background. Along with this you also might want to try and Reset Content and Settings from the iOS Simulator drop down in the simulator. If you're testing on the phone, then you may want to try deleting the app and then running it on it from Xcode again.

Another thing to check and see if your layouts in the storyboard for the Log-in and Sign up screen aren't all jumbled up by any chance.

I've got the same problem. Funny thing is that it works fine on my actual phone since I'm still logged into an account. Just terminates when trying to get to the login page with the same "null" issue.

Aman Tohan, both of your recommendations seem logical, but neither resolved the issue: Cleaning didn't solve the issue. Reseting content and settings didn't resolve the issue.

Here's a link to a similar question: https://www.parse.com/questions/ios-most-elegant-way-to-catch-assertvalidclassforquery-problems

I see what you mean Jacob McLaws. I have managed to somewhat replicate the error and upon setting some breakpoints I am noticing that the issue doesn't occur till you get to the line commented upon in the retrieveMessages method below...

- (void)retrieveMessages
{
    PFQuery *query = [PFQuery queryWithClassName:@"Messages"];
    [query whereKey:@"recipientIds" equalTo:[[PFUser currentUser] objectId]]; // Here's where the uncaught exception is occurring
    ...
}

The reason I mentioned the clean and then build to Robert Moore was mainly due to him mentioning that his performSegueWithIdentifier method wasn't running for him despite the breakpoint in the code asserting in the else statement. For the Reset Content and Settings, I recommended it in case he was dealing with corrupt user data on the simulator or on the phone.

It's tough to replicate the exact situation you guys are getting since my app is working okay. Based on the link to the post you provided Jacob at parse.com, I have modified my retrieveMessages code a little. Please try this out to see what you get.

- (void)retrieveMessages
{
    @try {
        PFQuery *query = [PFQuery queryWithClassName:@"Messages"];
        [query whereKey:@"recipientIds" equalTo:[[PFUser currentUser] objectId]];
        [query orderByDescending:@"createdAt"];
        [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
            if (error)
            {
                NSLog(@"Error: %@ %@", error, [error userInfo]);
            }
            else
            {
                // We found messages!
                self.messages = objects;
                [self.tableView reloadData];
                NSLog(@"Retrieved %lu messages", (unsigned long)[self.messages count]);
            }

            /* 
            // you can ignore this part, this comes in the final course of the iOS Development with Objective-C track
            if ([self.refreshControl isRefreshing])
            {
                [self.refreshControl endRefreshing];
            }*/
        }];
    }
    @catch (NSException *exception) {
        NSLog(@"exception: %@", exception.name);
        if ([exception.name isEqualToString:NSInvalidArgumentException])
        {
            [self performSegueWithIdentifier:@"showLogin" sender:self];

            /* 
            // more code related to the self.refreshControl which can be ignored for now
            self.refreshControl = [[UIRefreshControl alloc] init];
            [self.refreshControl addTarget:self action:@selector(retrieveMessages) forControlEvents:UIControlEventValueChanged];*/
        }
    }
}

Aman Tohan, thanks for such a thoughtful response. I really do appreciate it. I'm trying to implement your suggestions, but I'm a little bit confused. Where should I be placing this code? In the InboxViewController? I'm getting a failed build and "USe of undeclared identifier 'retrieveMessage"... Thanks for the help. You're awesome.