passing float gives garbage value - iphone

I'm dealing with some very weird issues by simply trying to pass a float parameter in obj-c.
I have a method which is called via an NSNotification:
- (void)presetChanged:(NSNotification*)notification {
float newValue = [[S76PresetManager sharedManager] getValueForKey:symbol];
[self setValue:newValue animated:YES];
[PdBase sendFloat:newValue toReceiver:symbol];
}
When I run this through the debugger, a float (say 0.5) will remain the same and get sent to the [PdBase sendFloat:] line. However, in the [self setValue:animated:] call, I get a garbage value of 3.68934881e+19. This is very strange. Any suggestions?
Thanks in advance
EDIT: Nothing special was happening in [self setValue:animated:], just doing some bounds checking before sending it to another method...
- (void)setValue:(float)newValue animated:(BOOL)animated {
float oldValue = value;
if (newValue < 0.0)
value = 0.0;
else if (newValue > maxValue)
value = maxValue;
else
value = newValue;
[self valueDidChangeFrom:oldValue to:value animated:animated];
}

Assuming you aren't doing anything strange in [self setValue:newValue animated:YES]...
How about:
NSNumber *newValue = [NSNumber numberWithFloat:[[S76PresetManager sharedManager] getValueForKey:symbol]];
[self setValue:newValue animated:YES];
[PdBase sendFloat:[newValue floatValue] toReceiver:symbol];

Related

App Crashing When Calling Release on Autorelease Pool - Timing Issue ? iPhone

I have the following method in my app :
- (void) loadModel {
// Runs in a seperate thread so we need to create an additional NSAutoreleasePool
pool = [[NSAutoreleasePool alloc] init];
NSData *getData = [activeModelInfo getFileData];
if (getData) {
if ([activeModel loadFromFileData:daeData]) {
[activeModel reset];
[mainViewController performSelectorOnMainThread:#selector(showModelView) withObject:nil waitUntilDone:NO];
}
else {
}
}
else {
}
[pool release];
}
The loadFromFileData method calls the following code which loads data. :
- (void) loadVerticesFromSource:(NSString*)verticesSourceId meshNode:(TBXMLElement*)meshNode intoMesh: (Mesh3D*) mesh {
NSLog(#"Getting Vertices for Source %#",verticesSourceId);
FloatArray *floatArray = [self getFloatArrayFromSource: verticesSourceId meshNode: meshNode];
if (floatArray) {
[daeFloatArray addObject:floatArray];
}
if (floatArray) {
if ([floatArray.array count] % 3 != 0) {
NSLog(#"Float array length not divisible by 3!");
}
else {
mesh->verticesCount = [floatArray.array count] / 3;
mesh->vertices = malloc(sizeof(Vector3D) * mesh->verticesCount);
for (int i=0; i<mesh->verticesCount; i++) {
mesh->vertices[i].x = [[floatArray.array objectAtIndex:(i*3)] floatValue];
mesh->vertices[i].y = [[floatArray.array objectAtIndex:(i*3)+1] floatValue];
mesh->vertices[i].z = [[floatArray.array objectAtIndex:(i*3)+2] floatValue];
// update extents information
if (!extents.pointDefined || mesh->vertices[i].x < extents.minX) extents.minX = mesh->vertices[i].x;
else if (!extents.pointDefined || mesh->vertices[i].x > extents.maxX) extents.maxX = mesh->vertices[i].x;
if (!extents.pointDefined || mesh->vertices[i].y < extents.minY) extents.minY = mesh->vertices[i].y;
else if (!extents.pointDefined || mesh->vertices[i].y > extents.maxY) extents.maxY = mesh->vertices[i].y;
if (!extents.pointDefined || mesh->vertices[i].z < extents.minZ) extents.minZ = mesh->vertices[i].z;
else if (!extents.pointDefined || mesh->vertices[i].z > extents.maxZ) extents.maxZ = mesh->vertices[i].z;
if (!extents.pointDefined) extents.pointDefined = YES;
[pointerStorageArray addObject:[NSValue valueWithPointer:mesh->vertices]];
}
}
}
}
Since this method is called several times while the data loads, each time mallocing memory for the mesh->vertices struct, I have created a pointerStorage array where I store the pointer to the malloced memory.
The app then displays a 3D object using OpenGL ES. When the user presses a Main Menu button, I then free up the pointerStorageArray as follows :
- (void) freeUpMallocedMemory
for (NSValue * value in pointerStorageArray) {
free(value);
}
The problem is that the app then crashes during this process. All I get is the EXC_BAD_ACCESSS error message and a pointer to the following line of code in the loadModel method above :
[pool release];
Nothing in the stack trace. I have also tried turning on NSZombie, NSAutoreleaseTrackFreedObjectCheck and NSDebugEnabled, but I still don't get any additional information.
The odd thing is that if I put a delay on the button of 2 seconds (i.e only trigger the freeUpMallocedMemory method after 2 seconds), the app no longer crashes and works fine.
Can anyone suggest what might be causing this - really confused and have already spent a few days troubleshooting.
Thank you !
You are over-releasing... the values in pointerStorageArray are created via a convenience method and as such don't need releasing, simply removing them from the array will dispose of them.

iOS - NSTimer - SIGABRT after invalidate - Edit Now DeAlloc Msg

I have my NSTimer embedded in a class that plays image sequences. Basically it loops and changes a UIImageView. Everything goes well if I let the image sequence finish but... on it's own if I try to stop the timer while it is playing I get a sigabrt. Edit: No longer a sigabrt but now a DeAlloc I can't explain.
The "stop" at the end of a frame sequence is the same stop I am calling mid sequence.
So what might cause an NSTimer to break mid function and DeAlloc. More to the point what might I look at to fix it.
Thanks.
I am using some example code from here: http://www.modejong.com/iOS/PNGAnimatorDemo.zip
Edit: I'll add what I believe to be the pertinent code here.
// Invoke this method to start the animation
- (void) startAnimating
{
self.animationTimer = [NSTimer timerWithTimeInterval: animationFrameDuration target: self selector: #selector(animationTimerCallback:) userInfo: NULL repeats: TRUE];
[[NSRunLoop currentRunLoop] addTimer: animationTimer forMode: NSDefaultRunLoopMode];
animationStep = 0;
if (avAudioPlayer != nil)
[avAudioPlayer play];
// Send notification to object(s) that regestered interest in a start action
[[NSNotificationCenter defaultCenter]
postNotificationName:ImageAnimatorDidStartNotification
object:self];
}
- (void) animationTimerCallback: (NSTimer *)timer {
if (![self isAnimating])
return;
NSTimeInterval currentTime;
NSUInteger frameNow;
if (avAudioPlayer == nil) {
self.animationStep += 1;
// currentTime = animationStep * animationFrameDuration;
frameNow = animationStep;
} else {
currentTime = avAudioPlayer.currentTime;
frameNow = (NSInteger) (currentTime / animationFrameDuration);
}
// Limit the range of frameNow to [0, SIZE-1]
if (frameNow < 0) {
frameNow = 0;
} else if (frameNow >= animationNumFrames) {
frameNow = animationNumFrames - 1;
}
[self animationShowFrame: frameNow];
// animationStep = frameNow + 1;
if (animationStep >= animationNumFrames) {
[self stopAnimating];
// Continue to loop animation until loop counter reaches 0
if (animationRepeatCount > 0) {
self.animationRepeatCount = animationRepeatCount - 1;
[self startAnimating];
}
}
}
- (void) stopAnimating
{
if (![self isAnimating])
return;
[animationTimer invalidate];
self.animationTimer = nil;
animationStep = animationNumFrames - 1;
[self animationShowFrame: animationStep];
if (avAudioPlayer != nil) {
[avAudioPlayer stop];
avAudioPlayer.currentTime = 0.0;
self->lastReportedTime = 0.0;
}
// Send notification to object(s) that regestered interest in a stop action
[[NSNotificationCenter defaultCenter]
postNotificationName:ImageAnimatorDidStopNotification
object:self];
}
Edit2: So I commented out an NSAssert in DeAlloc, commenting that out shed a bit more light. Now getting to self.animationTimer = nil; and saying *** -ImageAnimator setAnimationTimer:]: Message sent to deallocated instance.
DeAlloc is being called right when I invalidate the timer... so I'm a bit confused here.
I have a solution which is working but not optimal.
I just added another function to set the frame it's on to the last frame and it ends the sequence as I need.
But it doesn't solve the question of why it's doing it's crashing if I try to stop the sequence mid run.
Well, I wrote this code so I can assure you that it should be working just fine :) You need to invoke stopAnimating before you are done with the view, the only way you would have got the assert in dealloc is if the view was deallocated while it was still animating. That should not happen, which is exactly why there way an assert there. There is also a big comment explaining the assert, what is unclear about that?
- (void)dealloc {
// This object can't be deallocated while animating, this could
// only happen if user code incorrectly dropped the last ref.
NSAssert([self isAnimating] == FALSE, #"dealloc while still animating");
self.animationURLs = nil;
self.imageView = nil;
self.animationData = nil;
self.animationTimer = nil;
[super dealloc];
}
Just call:
[view stopAnimating];
Before you remove the view from its superview and everything will be just fine.

Animating a sprite in cocos2d , box2d and Xcode

Please, I need help in making this code work. I intend to do an animation with a sprite I added using cocos2d and box2d in xcode. But for some odd reasons I cannot get the sprite to animate repeatedly.
This code builds successfully but animates only once. Can anyone help and tell me what I am not doing right?
The implementation file are as follows:
#import "Mosquito.h"
#import "Box2DHelpers.h"
#implementation Mosquito
#synthesize flyingAnim;
- (void) dealloc{
[flyingAnim release];
[super dealloc];
}
-(void)initAnimations {
flyingAnim = [self loadPlistForAnimationWithName:#"flyingAnim"
andClassName:NSStringFromClass([self class])];
[[CCAnimationCache sharedAnimationCache] addAnimation:flyingAnim
name:#"flyingAnim"];
}
-(void)changeState:(CharacterStates)newState {
[self stopAllActions];
id action = nil;
// id flyingAction = nil;
//CGPoint newPosition;
[self setCharacterState:newState];
switch (newState) {
case kStateIdle:
[self setDisplayFrame:
[[CCSpriteFrameCache sharedSpriteFrameCache]
spriteFrameByName:#"Mosquito_anim_1.png"]];
break;
case kStateFlying:
action = [CCAnimate actionWithAnimation:flyingAnim
restoreOriginalFrame:NO];
break;
case kStateTakingDamage:
action = [CCBlink actionWithDuration:1.0 blinks:3.0];
break;
default:
//CCLOG(#"Unhandled state %d in Mosquito", newState);
break;
}
if (action != nil) {
[self runAction:action];
}
}
- (id)initWithWorld:(b2World *)theWorld atLocation:(CGPoint)location {
if ((self = [super init])) {
world = theWorld;
[self setDisplayFrame:[[CCSpriteFrameCache
sharedSpriteFrameCache]
spriteFrameByName:#"Mosquito_anim_1.png"]];
gameObjectType = kMosquitoType;
characterHealth = 100.0f;
[self createBodyAtLocation:location];
[self initAnimations];
}
return self;
}
- (void) updateStateWithDeltaTime:(ccTime)deltaTime
andListOfGameObjects:(CCArray *)listOfGameObjects {
//CGPoint oldPosition = self.position;
if ((characterState == kStateDestroyed) &&
([self numberOfRunningActions] > 0)) {
return;
}
if (characterState != kStateFlying &&
[self numberOfRunningActions] == 0) {
[self changeState:kStateFlying];
}
}
#end
Thanks.
id repeatAnimation = [CCRepeatForever actionWithAction:action];
To repeat forever, you need to do that, otherwise you need to just do:
[self runAction:action];
again.
Also, you might want to consider not reassigning action to CCBlink and make another action and call
[self stopAllActions];
id blinkAction = [CCBlink actionWithDuration:1.0 blinks:3.0];
[self runAction:blinkAction];
This may Help you.
One of the easiest ways for sprite animation.
https://sites.google.com/site/rajanallathambi1/cocos2d-tutorials/sprite-animation-without-plist-file

UIColor in SetStrokeColorWithColor triggers EXC_BAD_ACCESS - memory issue?

I have a large line to draw that the colour changes along the line.
Now and again I get EXC_BAD_ACCESS on the 4th line of the code there.
I suspect that it is something to do with the autoreleasing of the *tempColor but cannot work out how to get this to work effeiciently and not to crash.
Any ideas? This crashes on say 1 in 50 runs of this code.
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, lastx, lasty);
CGContextAddLineToPoint(ctx, point.x, point.y);
UIColor *tempColor = [self colorForHex:[[heightLocal objectAtIndex:idx] doubleValue]];
CGContextSetStrokeColorWithColor(ctx,tempColor.CGColor);
CGContextStrokePath(ctx);
lastx = point.x;
lasty = point.y;
EDIT:
Just had a quick play after that suggestion and possibly think it is because heightLocal is not initialized?
I cahnged it to the code here...
if(idx > [heightLocal count]){
heightVar = 0;
NSLog(#"Made it here");
}else {
heightVar = [[heightLocal objectAtIndex:idx] doubleValue];
}
UIColor *tempColor = [self colorForHex:heightVar];
and it gets the same error on the first line. The if!
heightLocal is initialized using...
NSArray *heightLocal = routeGrabInstance.pointHeights;
I would say that the array you get with:
routeGrabInstance.pointHeights;
Is not being retained properly. If it's like many classes it could be returned as autorelease.
Try a :
[heightLocal retain]
after your
NSArray *heightLocal = routeGrabInstance.pointHeights;

Need help with a memory management problem in my game model

I'm a beginner level programmer trying to make a game app for the iphone and I've encountered a possible issue with the memory management (exc_bad_access) of my program so far. I've searched and read dozens of articles regarding memory management (including apple's docs) but I still can't figure out what exactly is wrong with my codes. So I would really appreciate it if someone can help clear up the mess I made for myself.
//in the .h file
#property(nonatomic,retain) NSMutableArray *fencePoleArray;
#property(nonatomic,retain) NSMutableArray *fencePoleImageArray;
#property(nonatomic,retain) NSMutableArray *fenceImageArray;
//in the .m file
- (void)viewDidLoad {
[super viewDidLoad];
self.gameState = gameStatePaused;
fencePoleArray = [[NSMutableArray alloc] init];
fencePoleImageArray = [[NSMutableArray alloc] init];
fenceImageArray = [[NSMutableArray alloc] init];
mainField = CGRectMake(10, 35, 310, 340);
..........
[NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:#selector(gameLoop) userInfo:nil repeats:YES];
}
So basically, the player touches the screen to set up the fences/poles
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if(.......) {
.......
}
else {
UITouch *touch = [[event allTouches] anyObject];
currentTapLoc = [touch locationInView:touch.view];
NSLog(#"%i, %i", (int)currentTapLoc.x, (int)currentTapLoc.y);
if(CGRectContainsPoint(mainField, currentTapLoc)) {
if([self checkFence]) {
onFencePole++;
//this 3 set functions adds their respective objects into the 3 NSMutableArrays using addObject:
[self setFencePole];
[self setFenceImage];
[self setFencePoleImage];
.......
}
}
else {
.......
}
}
}
}
The setFence function (setFenceImage and setFencePoleImage is similar to this)
-(void)setFencePole {
Fence *fencePole;
if (!elecFence) {
fencePole = [[Fence alloc] initFence:onFencePole fenceType:1 fencePos:currentTapLoc];
}
else {
fencePole = [[Fence alloc] initFence:onFencePole fenceType:2 fencePos:currentTapLoc];
}
[fencePoleArray addObject:fencePole];
[fencePole release];
and whenever I press a button in the game, endOpenState is called to clear away all the extra images(fence/poles) on the screen and also to remove all existing objects in the 3 NSMutableArray. Point is to remove all the objects in the NSMutableArrays but keep the array itself so it can be reused later.
-(void)endOpenState {
........
int xMax = [fencePoleArray count];
int yMax = [fenceImageArray count];
for (int x = 0; x < xMax; x++) {
[[fencePoleImageArray objectAtIndex:x] removeFromSuperview];
}
for (int y = 0; y < yMax; y++) {
[[fenceImageArray objectAtIndex:y] removeFromSuperview];
}
[fencePoleArray removeAllObjects];
[fencePoleImageArray removeAllObjects];
[fenceImageArray removeAllObjects];
........
}
The crash happens here at the checkFence function.
-(BOOL)checkFence {
if (onFencePole == 0) {
return YES;
}
else if (onFencePole >= 1 && onFencePole < currentMaxFencePole - 1) {
CGPoint tempPoint1 = currentTapLoc;
CGPoint tempPoint2 = [[fencePoleArray objectAtIndex:onFencePole-1] returnPos]; // the crash happens at this line
if ([self checkDistance:tempPoint1 point2:tempPoint2]) {
return YES;
}
else {
return NO;
}
}
else if (onFencePole == currentMaxFencePole - 1) {
......
}
else {
return NO;
}
}
So the problem here is, everything works fine until checkFence is called the 2nd time after endOpenState is called. So its like tap_screen -> tap_screen -> press_button_to_call_endOpenState -> tap screen -> tap_screen -> crash
What I'm thinking of is that fencePoleArray got messed up when I used [fencePoleArray removeAllObjects] because it doesn't crash when I comment it out. It would really be great if someone can explain to me what went wrong. And thanks in advance.
First, a couple of suggestions:
if (!elecFence) {
fencePole = [[Fence alloc] initFence:onFencePole
fenceType:1 fencePos:currentTapLoc];
}
else {
fencePole = [[Fence alloc] initFence:onFencePole
fenceType:2 fencePos:currentTapLoc];
}
You’re making this too hard, how about this:
const int fenceType = elecFence ? 2 : 1;
Fence *fencePole = [[Fence alloc] initFence:onFencePole
fenceType:fenceType fencePos:currentTapLoc];
And this:
int xMax = [fencePoleArray count];
int yMax = [fenceImageArray count];
for (int x = 0; x < xMax; x++) {
[[fencePoleImageArray objectAtIndex:x] removeFromSuperview];
}
for (int y = 0; y < yMax; y++) {
[[fenceImageArray objectAtIndex:y] removeFromSuperview];
}
Could be shortened using makeObjectsPerformSelector:
const SEL remove = #selector(removeFromSuperview);
[fencePoleImageArray makeObjectsPerformSelector:remove];
[fenceImageArray makeObjectsPerformSelector:remove];
This is shorter and safer, as the xMax bound in your code is computed from fencePoleArray and used to iterate over fencePoleImageArray. (Could be right, could be wrong.)
Now to the objectAtIndex: call. If the array is still in memory and you tried to access an object beyond the array bounds, you would get an exception. So that I guess that either the array or some of the objects in it got released without you knowing it. You could try to NSLog the array and the object on given index and try to log their retainCount. If the logging line crashes, you have found the object that’s been released and can start looking for the cause.
(And one more thing: You should split the game logic into a separate model class. This simplifies the code and makes it easier to reason about.)
If you want to use properties, you should use self.propertyName = ... instead of propertyName = ....
Hope this will help.