Sreyals
Sreyals

Reputation: 23

Terminating app due to uncaught exception 'NSInvalidArgumentException' in my "game"

I'm following and online course and got stock because even by following the step (or maybe I missed some ? ) i get and error. I made several search on google and here but since i'm new to IOS development, even with answer from others, i can relate to my issue..

here is the error:

2015-06-12 23:03:17.477 Pirate Game[6511:1193126] -[RBTile setWeapon:]: unrecognized selector sent to instance 0x78830dc0
2015-06-12 23:03:17.481 Pirate Game[6511:1193126] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[RBTile setWeapon:]: unrecognized selector sent to instance 0x78830dc0'
*** First throw call stack:
(
0   CoreFoundation                      0x00874746 __exceptionPreprocess + 182
1   libobjc.A.dylib                     0x004fda97 objc_exception_throw + 44
2   CoreFoundation                      0x0087c705 -[NSObject(NSObject) doesNotRecognizeSelector:] + 277
3   CoreFoundation                      0x007c3287 ___forwarding___ + 1047
4   CoreFoundation                      0x007c2e4e _CF_forwarding_prep_0 + 14
5   Pirate Game                         0x00014a94 -[RBFactory tiles] + 388
6   Pirate Game                         0x00011c6f -[ViewController viewDidLoad] + 143
7   UIKit                               0x00d97da4 -[UIViewController loadViewIfRequired] + 771
8   UIKit                               0x00d98095 -[UIViewController view] + 35
9   UIKit                               0x00c89e85 -[UIWindow addRootViewControllerViewIfPossible] + 66
10  UIKit                               0x00c8a34c -[UIWindow _setHidden:forced:] + 287
11  UIKit                               0x00c8a648 -[UIWindow _orderFrontWithoutMakingKey] + 49
12  UIKit                               0x00c989b6 -[UIWindow makeKeyAndVisible] + 80
13  UIKit                               0x00c2ded8 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 3217
14  UIKit                               0x00c31422 -[UIApplication _runWithMainScene:transitionContext:completion:] + 1639
15  UIKit                               0x00c4a93e __84-[UIApplication _handleApplicationActivationWithScene:transitionContext:completion:]_block_invoke + 59
16  UIKit                               0x00c3004a -[UIApplication workspaceDidEndTransaction:] + 155
17  FrontBoardServices                  0x031d6c9e __37-[FBSWorkspace clientEndTransaction:]_block_invoke_2 + 71
18  FrontBoardServices                  0x031d672f __40-[FBSWorkspace _performDelegateCallOut:]_block_invoke + 54
19  FrontBoardServices                  0x031e8d7c __31-[FBSSerialQueue performAsync:]_block_invoke_2 + 30
20  CoreFoundation                      0x00796050 __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 16
21  CoreFoundation                      0x0078b963 __CFRunLoopDoBlocks + 195
22  CoreFoundation                      0x0078b7bb __CFRunLoopRun + 2715
23  CoreFoundation                      0x0078aa5b CFRunLoopRunSpecific + 443
24  CoreFoundation                      0x0078a88b CFRunLoopRunInMode + 123
25  UIKit                               0x00c2fa02 -[UIApplication _run] + 571
26  UIKit                               0x00c33106 UIApplicationMain + 1526
27  Pirate Game                         0x000148da main + 138
28  libdyld.dylib                       0x02c00ac9 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

So what i could understand from my search, is that i'm trying to send something that is not the same type. I have the same problem with all 3 custom class.

//
//  RBFactory.m
//  Pirate Game
//
//  Created by Richard Berube on 2015-06-06.
//  Copyright (c) 2015 Richard Berube. All rights reserved.
//

#import "RBFactory.h"
#import "RBTile.h"

@implementation RBFactory

-(NSArray *)tiles{


    RBTile *tile1 = [[RBTile alloc] init];
    tile1.story = @"Captain, we need a fearless leader such as you to undertake a voyage. You must stop the evil pirate Boss before he steals any more plunder. Would you like a blunted sword to get started?";
    tile1.backgroundImage = [UIImage imageNamed:@"PirateStart.png"];
    CCWeapon *bluntedSword = [[CCWeapon alloc]init];
    bluntedSword.name = @"Blunted sword";
    bluntedSword.damage = 12;
    NSLog(@"%@", bluntedSword);
    tile1.weapon = bluntedSword;
    tile1.actionButtonName =@"Take the sword";

I tested with breakpoint and the crash occure

tile1.weapon = bluntedSword;

NSLog return:

2015-06-12 23:03:14.602 Pirate Game[6511:1193126] <CCWeapon: 0x786a6f50>

here is the tile class

//
//  RBTile.h
//  Pirate Game
//
//  Created by Richard Berube on 2015-06-06.
//  Copyright (c) 2015 Richard Berube. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "CCWeapon.h"
#import "CCArmor.h"

@interface RBTile : NSObject

@property (nonatomic, strong) NSString *story;
@property (strong, nonatomic) UIImage *backgroundImage;
@property (nonatomic, strong) NSString *actionButtonName;
@property (strong, nonatomic) CCWeapon *weapon;
@property (strong, nonatomic) CCArmor *armor;
@property (nonatomic) int healthEffect;

@end

The .m file is empty

//
//  RBTile.m
//  Pirate Game
//
//  Created by Richard Berube on 2015-06-06.
//  Copyright (c) 2015 Richard Berube. All rights reserved.
//

#import "RBTile.h"

@implementation RBTile

@end

And the last one is the custom class, one of them actualy, because all 3 are causing the same issue..

//
//  CCWeapon.h
//  Pirate Game
//
//  Created by Richard Berube on 2015-06-10.
//  Copyright (c) 2015 Richard Berube. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface CCWeapon : NSObject

@property (strong,nonatomic) NSString *name;
@property (nonatomic) int damage;

@end

A little help would be really apreciated! i'm now stock since 2 days.. i could start over all the video (online course) but that won't teach me how to debug ..

Maybe the last usefull info could be that i used Xcode 6.3.1

THanks !

update 1 : The final project is this one https://github.com/codecoalition/Pirate-Adventure-Assignment/tree/master/Pirate%20Adventure

my RBtile is the CCtile in the github project

update 2: here is my viewcontroler

//
//  ViewController.m
//  Pirate Game
//
//  Created by Richard Berube on 2015-06-06.
//  Copyright (c) 2015 Richard Berube. All rights reserved.
//

#import "ViewController.h"
#import "RBFactory.h"
#import "RBTile.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    RBFactory *factory = [[RBFactory alloc]init];
    self.tiles = [factory tiles];
    self.character = [factory character];
    self.currentPoint = CGPointMake(0, 0);
    [self updateTile];
    [self updateButtons];
    [self updateCharacterStatsForArmor:nil withWeapons:nil withHealthEffect:0];
}

-(void)updateTile{
    RBTile *tileModel = [[self.tiles objectAtIndex:self.currentPoint.x] objectAtIndex:self.currentPoint.y];
    self.storyLabel.text = tileModel.story;
    self.backgroundImageView.image = tileModel.backgroundImage;
    self.healthLabel.text = [NSString stringWithFormat:@"%i", self.character.health];
    self.damageLabel.text = [NSString stringWithFormat:@"%i", self.character.damage];
    self.armorLabel.text = self.character.armor.name;
    self.weaponLabel.text = self.character.weapon.name;
    [self.actionButton setTitle:tileModel.actionButtonName forState:UIControlStateNormal];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)actionButtonPressed:(UIButton *)sender {

    RBTile *tile = [[self.tiles objectAtIndex:self.currentPoint.x] objectAtIndex:self.currentPoint.y];
    [self updateCharacterStatsForArmor:tile.armor withWeapons:tile.weapon withHealthEffect:tile.healthEffect];
    [self updateTile];
}

- (IBAction)northButtonPressed:(UIButton *)sender {

    self.currentPoint = CGPointMake(self.currentPoint.x, self.currentPoint.y +1);
    [self updateButtons];
    [self updateTile];
}

- (IBAction)southButtonPressed:(UIButton *)sender {

    self.currentPoint = CGPointMake(self.currentPoint.x, self.currentPoint.y -1);
    [self updateButtons];
    [self updateTile];

}

- (IBAction)eastButtonPressed:(UIButton *)sender {

    self.currentPoint = CGPointMake(self.currentPoint.x + 1, self.currentPoint.y);
    [self updateButtons];
    [self updateTile];
}

- (IBAction)westButtonPressed:(UIButton *)sender {

    self.currentPoint = CGPointMake(self.currentPoint.x - 1, self.currentPoint.y);
    [self updateButtons];
    [self updateTile];
}

- (IBAction)restartButtonPressed:(UIButton *)sender {
}

-(void)updateButtons{
    self.westButton.hidden = [self tilesExistAtPoint:CGPointMake(self.currentPoint.x -1, self.currentPoint.y)];
    self.eastButton.hidden = [self tilesExistAtPoint:CGPointMake(self.currentPoint.x+1, self.currentPoint.y)];
    self.northButton.hidden = [self tilesExistAtPoint:CGPointMake(self.currentPoint.x, self.currentPoint.y+1)];
    self.southButton.hidden = [self tilesExistAtPoint:CGPointMake(self.currentPoint.x, self.currentPoint.y-1)];
}

-(BOOL)tilesExistAtPoint:(CGPoint)point{
    if (point.y >= 0 && point.x >=0 && point.x < [self.tiles count] && point.y < [[self.tiles objectAtIndex:point.x] count]) {
        return NO;
    }
    else{
        return YES;
    }
}

-(void)updateCharacterStatsForArmor:(CCArmor *)armor withWeapons:(CCWeapon *)weapon withHealthEffect:(int)healtEffect{

    if (armor != nil ) {
        self.character.health = self.character.health - self.character.armor.health +armor.health;
        self.character.armor = armor;
    }
    else if (weapon != nil){
        self.character.damage = self.character.damage - self.character.weapon.damage + weapon.damage;
        self.character.weapon = weapon;
    }
    else if (healtEffect != 0){
        self.character.health = self.character.health + healtEffect;
    }
    else {
        self.character.health = self.character.health + self.character.armor.health;
        self.character.damage = self.character.damage + self.character.weapon.damage;
    }
}

@end

Another update:

I was able to find with the breakpoint that some of my property are not showing up.. tile1

When in fact it should be like that:

Should be like this

So now i know that when i try to pass tile1.weapon = bluntedSword; it is not working because tile1.weapon do not exist. But if you look in my RBTile.h all my property are there..

Upvotes: 2

Views: 232

Answers (2)

Zonker.in.Geneva
Zonker.in.Geneva

Reputation: 1499

I am following the same course, and my code is the same as yours, and it works. The Tile.m files is empty.

In recent Xcode versions, synthesize statements are not always necessary. Some rare cases, I think, still need them.

I think the reason you don't see the other properties in the debug window is because the code that creates them hasn't run yet.

Try commenting out the lines that related to bluntedSword and see if the other properties are set successfully, or if they also cause the app to crash.

Another thing to try, and I understand how silly it sounds, is to re-type the lines (not copy and paste) and related lines that are causing the problems. Sometimes this works, so it's worth trying.

Good luck!

Upvotes: 1

Johnathon Sullinger
Johnathon Sullinger

Reputation: 7414

The root of the issue is this

[RBTile setWeapon:]: unrecognized selector sent to instance 0x78830dc0

That is telling you that your RBTile.weapon property on the RBTile class does not have a setter. Please update your post with the .m file showing how you are creating the weapon property on the RBTile. Odds are you are declaring a getter and potentially forgetting the setter.

Your .m file is empty, which is causing the issue. The header file just defines a contract between an object using your class, and the implementation of the class in the .m file. You can think of it as a bridge of sorts between something using the class, and the actual implementation of the class.

At runtime, the game can't find an implementation of the property to work with, thus the reason why unrecognized selector is being thrown.

Upvotes: 0

Related Questions