Obj-c EXC_BAD_ECCESS error - objective-c

I'm having a strange crash, at the 4th line below.
{
...
int exp = [[resourceCompletionReward objectAtIndex:experienceD] integerValue];
int xx = mySprite.x;
int yy = mySprite.y;
[self setupRisingText:exp withX:xx withY:yy];
...
}
-(void)setupRisingText:(int)risingValue withX:xx withY:yy {
...
}
When it tries to run the setupRising Text method it just crashes. Can't see anything wrong though?

What ever you do with xx and yy in setupRisingText::: they are treated as id (something like NSObject *, not exactly like that but similar)
So instead of int variables pointers to objects (any object, not just subclasses of NSObject) are accessed and dealt with. That is the default for any parameter without a type.
Use
-(void)setupRisingText:(int)risingValue withX:(int)xx withY:(int)yy {
...
}
instead.
BTW, if you used NSNumber you would have less of a problem here.

I am wondering, shouldn't your method look like this?
-(void)setupRisingText:(int)risingValue withX:(int)xx withY:(int)yy {
//NSLog(#"%d",risingValue+xx+yy);
}

Related

Objective-C compile error: Invalid operands to binary expression

-(void)updateCharacterStatsForArmor:(RKArmor *)armor withWeapons:(RKWeapon *)weapon withHealthEffect:(int)healtheffect
{
if (armor != nil){
self.character.health = self.character.health - self.character.armor.health + armor.health;
self.character.armor = armor;
}
else if (weapon != nil){
// The problematic line:
self.character.damage = self.character.damage - self.character.weapon.damage + weapon.damage;
self.character.weapon = weapon;
}
else if (healtheffect != 0){
self.character.health = self.character.health + healtheffect;
}
else {
self.character.health = self.character.health + self.character.armor.health;
self.character.damage = *(self.character.damage + self.character.weapon.damage);
}
}
#end
The line with the error is marked in the code snippet. The error says invalid operand to binary expression int int*.
Would It be best to restart the whole thing?
You probably defined one of the damage properties you're using as an int* instead of int. Check your character and weapon classes for that. I'd suspect self.character.damage.
If the line you indicated really is the problem, it looks like you've probably declared the damage property of the character class to return int * instead of int. It's easy to make that mistake because properties that point to objects are always pointers. int, however, is not an object type, so there's usually not need to store a pointer to one in a property.
The line you say is a problem is:
self.character.damage = self.character.damage - self.character.weapon.damage + weapon.damage;
But later on you have:
self.character.damage = *(self.character.damage + self.character.weapon.damage);
It looks like this second line is some kind of attempt to avoid a compiler error, but it doesn't seem to make a lot of sense. You'd only dereference the result of the addition if you were doing pointer arithmetic, but that doesn't make much sense for a property called damage.
To fix all this, take a look at your character class declaration. You'll probably see something like:
#property(...) int *damage;
Remove that * and make sure the attribute is assign, like this:
#property(assign) int damage;
Also, it's not clear how pirates are involved. Perhaps ye have been a mite hasty in makin' yer query? Arrr!

how to pass block as a macro's argument in objective-c?

In my code i have a lot of code like:
if (block) block(....)
So I want to define a macro, something like
#define safetyCall(block, ...) if((block)) {block(##__VA_ARGS__)};
But i couldn't get it to work. Any idea?
You don't need the ## and the ; needs moving:
#define safetyCall(block, ...) if((block)) { block(__VA_ARGS__); }
This can run into issues if your block is inline and contains code that has a series of comma separated strings, etc.
Example:
safetyCall(^void() {
NSArray *foo = #[#"alice", "bob"];
};
The compiler will complain about "Expected ']' or '.'" and "Expected identifier or '('".
However, if you were to declare the inline block as a separate block before the macro, it will not generate an error.
Example:
void (^fooBlock)(void) = ^void() {
NSArray *foo = #[#"alice", #"bob"];
}
safetyCall(fooBlock);

if statement comparing integers not working in objective c

I am trying to perform logic based on the values of two integers. Here I am defining my integers, and I also have NSLog so I can see if the values are correct when I run the code:
int theHikeFlag = (int)[theNewHikeFlag objectAtIndex:(theID-1)];
NSLog(#"theHikeFlag: %#",theHikeFlag);
int fromTheDB = [self.detailItem hikeFlag];
NSLog(#"fromTheDB: %d",fromTheDB);
And here is the logic:
if (theHikeFlag==1) {
hikeString=#"You have";
}
else if (theHikeFlag==0) {
hikeString=#"You have not";
}
else {
if (fromTheDB==1) {
hikeString=#"You have";
}
else {
hikeString=#"You have not";
}
}
As an example of how this code is working. When theHikeFlag=1 and fromTheDB=0, the code bypasses the if and the else if and goes straight to the else and sets hikeString="You have not". This means that my result is irrelevant of theHikeFlag and is based on the fromTheDB integer.
Since you cannot store ints in an array, the line
(int)[theNewHikeFlag objectAtIndex:(theID-1)];
is not doing what you think it should. You need to pull the data from NSNumber, not cast to int.
int theHikeFlag = [[theNewHikeFlag objectAtIndex:(theID-1)] intValue];
The reason why the log output is correct is a bit funny: you made two mistakes in a row! First, you re-interpreted a pointer as an int, and then you let NSLog re-interpret it as an object again by adding a format specifier %# that is incompatible with int, but works fine with pointers! Since the int value contains a pointer to NSNumber, NSLog produces the "correct" output.

NSArray in if statement strange behaviour

i have the following two pieces of code which i think should be identical
int temp = [[[myArray objectAtIndex:iIndex] objectAtIndex:jIndex] state];
if (temp > 0)
{
NSLog(#"TEST: %d",temp);
}
if ([[[myArray objectAtIndex:iIndex] objectAtIndex:jIndex] state] > 0)
{
NSLog(#"TEST: %d",temp);
}
state is just an int in the objects in the array with accessor like:
#property (assign)int state;
but when state is negative, the first version works (no output), but the second version outputs (for example) "TEST: -4" (?!)
is there any obvious reason why they might be different?
Since -objectAtIndex: returns an id, the compiler will not be able to know what -state should return. If you did not import the header that declares state first, or if the property state has ambiguous declaration (e.g. another class has declared #property(retain) id state before your class is imported), then the compiler may infer a wrong type for -state.
If it infers id, for instance, as all pointers are nonnegative, -4 will be implicitly viewed as 0xFFFFFFFC, thus the > 0 condition passes.
But for code 1, you have specified that temp is an int, so even if the return value of the call is 0xFFFFFFFC, it will be cast back to a signed value (-4), hence the condition fails.
The safest approach is to specify the type of -objectAtIndex:, i.e.
Foo* obj = [[myArray objectAtIndex:iIndex] objectAtIndex:jIndex];
if (obj.state > 0) {
...
I I understand it right, and the two if's are NOT in the same method, then the second one prints an unassigned variable. the fix should go like this:
if ((temp = [[[myArray objectAtIndex:iIndex] objectAtIndex:jIndex] state]) > 0)
{
NSLog(#"TEST: %d",temp);
}

function with multiple arguments

how to pass multiple arguments in a single function in Objective-C? I want to pass 2 integer values and the return value is also integer. I want to use the new Objective-C syntax, not the old C/C++ syntax.
In objective-c it is really super easy. Here is the way you would do it in C:
int functName(int arg1, int arg2)
{
// Do something crazy!
return someInt;
}
This still works in objective-c because of it's compatibility with C, but the objective-c way to do it is:
// Somewhere in your method declarations:
- (int)methodName:(int)arg1 withArg2:(int)arg2
{
// Do something crazy!
return someInt;
}
// To pass those arguments to the method in your program somewhere:
[objectWithOurMethod methodName:int1 withArg2:int2];
Best of luck!
Since this is still google-able and there are better solutions than the accepted answer; there's no need for the hideous withArg2 – just use colons:
Declaration:
#interface
-(void) setValues: (int)v1 : (int)v2;
Definition:
#implementation
-(void) setValues: (int)v1 : (int)v2 {
//do something with v1 and v2
}
Like this:
int sum(int a, int b) {
return a + b;
}
Called like this:
int result;
result = sum(3, 5);
// result is now 8
More here
int add (int a, int b)
{
int c;
c = a + b;
return c;
}
link text