How to continuously update MKAnnotation coordinates on the MKMap - ios

I have a GPSTestViewController class that has a MKMapView with added MKAnnotations (stored in a class called Bases). I'm trying to continuously update the coordinates for the MKAnnotations (with the updateBaseInformation method in Bases) so the bases is moving on the map. The update is invoked from the GPSTestViewController method locationUpdate (since it's called every second):
- (void)locationUpdate:(CLLocation *)location {
NSLog(#"locationUpdate");
self.cachedLocation = location;
[self centerTo:cachedLocation.coordinate];
//Trying to update the coordinates every second
[bases updateBaseInformation]; <--Program received signal: “EXC_BAD_ACCESS”
return;
}
But then I get the following message:
[bases updateBaseInformation]; Program received signal: “EXC_BAD_ACCESS”
Bases.m contains the following code (and even when some code is commented it crashes):
- (void)updateBaseInformation {
NSLog(#"Updating base information");
for(MyAnnotation *a in bases)
{
//CLLocationCoordinate2D c;
if([a.type compare:#"friend"] == 0)
{
//c.latitude = a.coordinate.latitude+0.001;
//c.longitude = a.coordinate.longitude+0.001;
//a.coordinate = c;
}
else if([a.type compare:#"enemy"] == 0)
{
//[a setCoordinate:CLLocationCoordinate2DMake(a.coordinate.latitude+0.002, a.coordinate.longitude+0.0012)];
}
}
}
My guess is that I'm accessing the objects that are already accessed somewhere else and that causes the EXC_BAD_ACCESS. I have spent many hours on searching, but without results. Why do I get this error and how should I do in order to make the Annotations move around on the map?
I have uploaded the complete project to (link removed).
Solution
The problem is now solved. The problem was that the array that holds the Annotations was autoreleased. So I changed the allocation from
bases = [NSMutableArray array];
to
bases = [[NSMutableArray array] retain];
Thanks in advance.

My guess is that I'm accessing the objects that are already accessed
somewhere else
You are probably accessing an object that no longer exists in memory - You need to check you are not deallocating an object which you are subsequently accessing. You should turn on Zombies for your scheme which will allow you to see when you are accessing a deallocated object by effectively keeping an object's memory under watch after the object has been deallocated. You can switch them on here: Scheme/edit scheme/enable zombie objects.

Related

NSMutableArray Interaction Troubles With Collisions

I am having trouble getting objects added to my NSMutableArray to log properly (which definitely means they won't process any of the appropriate functions correctly) with Spritebuilder [version 1.4.9, from the Apple App Store]. I am creating several objects using the same class, but each new one is overriding the older objects which exist. I thought an array would help keep things in order (and then on collision, I could call the array to check for which object was collided with), but it simply is not working that way - at all. Here is the relevant code.
Main.h
#property Coven *coven;
#property Nellie *nellie;
#property NSMutableArray *array;
//Physics, other things
Main.m
/Adding other things...
-(void) addCovenMember{
//This function is called on a RANDOM time interval
_array = [[NSMutableArray] alloc]init];
for (i = 0, i < 15, i++){
_coven = (Coven*) [CCBReader load:#"CovenMember"];
[_array addChild:_coven];
}
[_physicNode addChild:_coven];
}
-(BOOL)ccPhysicsCollisionBegin:(CCPhysicsCollisionPair *)pair nellie:(Nellie*)nellie coven:(Coven*)coven{
for (_coven in _array){
NSLog(#"%#",_coven.name)
if (CGRectIntersectsRect(_nellie.boundingBox, _coven.boundingBox){
NSLog(#"We're intersecting!");
}
}
Coven. h
//Nothing Important Here
Coven.m
-(void)didLoadFromCCB{
self.physicsBody.CollisionType = #"coven";
}
Nellie.h
//Nothing Here
Nellie.m
-(void) didLoadFromCCB{
self.physicsBody.CollisionType = #"nellie";
}
The collision is logging with every collision - but only as the name of the LATEST _coven member to be generated, no matter what I am colliding with. This also means that the _coven.boundingBox is solely on the latest _coven member and interaction only occurs when I hit the new member as soon as it generates on to the screen.
Any ideas? Any help?
Note: This is also posted on the Spritebuilder website - I decided to post it here as well because answers can be a little slow on those forums.
The -(void) addCovenMember overwrites (creates a new instance) of _array every time it's called. Thus, when you try to iterate in -ccPhysicsCollisionBegin: you'll only ever see 1 coven.
Add a nil check around your array creation:
if(_array == nil) {
_array = [[NSMutableArray] alloc]init];
}
The for loop in the -addCovenMember method looks broken (at least not a c loop). Reaplace the , with ;:
for (i = 0; i < 15 i++){
Also, using for(_coven in _array) seems wrong, you already have a property self.coven (presumably) with a backing _coven ivar. Try changing it to for(Coven * c in self.array) and use the local c in the loop:
for (Coven * c in _array){
NSLog(#"%#",c.name)
if (CGRectIntersectsRect(_nellie.boundingBox, c.boundingBox){
NSLog(#"We're intersecting!");
}
}
To everyone out in the world struggling with their ccPhysicsCollisions, arrays may not be the answer - this was a simple fix that left me incapacitated for days.
Using the basic ccPhysicsCollisionsBegan that ships with spritebuilder, try this without arrays first:
Scene.m
-(BOOL)ccPhysicsCollisionBegin:(CCPhysicsCollisionPair *)pair nellie:(Nellie*)nellie coven:(Coven*)coven{
[_coven stopAction:coven.path];
}
I initially created the method with:
[_coven stopAction:_coven.path];
Yes, that (underscore) set me back three weeks. Be sure you refer to the object interacting through the physics delegate, and not the object itself, which in my case, was constantly being overwritten by the new ones being generated.
Check your underscores.
Solved! :D
Thanks to #thelaws for your help! I'll get better at Obj C... eventually.

add new object to nsmutablearray replace all objects in array

i try to add new object to my nsmutablearray but every time it replace all object
-(void)addToStack:(Coordinate *)coord{
Coordinate*c = [[Coordinate alloc] init];
c.x=coord.x;
c.y = coord.y;
if (coord.x==0 && coord.y==0) {
c.x=coord.x+1;
[_stack addObject:c];
c.x=coord.x;
c.y=coord.y+1;
[_stack addObject:c];
c.y=coord.y;
}
}
You are not adding a new object but you are changing the old object where the reference will remain the same.
NSMutableArray addObject will not add it because it already exists in the array.
So, when trying to add a new object, first create a copy of the one that you want to change, like this:
Coordinate *newCoordinate = [Coordinate mutableCopy];
// change attributes
// add it to the array
Everybody who said that adding the same object twice deletes the first instance and replaces it, is wrong.
Arrays can contain duplicate references to the same object. However, it's more like saving the same street address in an rolodex twice. If you look up the address in the first entry, go break all the windows in that house, then go back, look up the address in the second slot in your rolodex, and drive to THAT address, you'll find the house has broken windows (Because both addresses point to the same house.)
Similarly, when you add the same object to an array twice, it's two pointers to the same object. When you change values of the object at index 0, you see those changes reflected in the object in index 1 because it's a second pointer to the same object.
Despite saying the wrong thing about what goes wrong with your code, #Shashi3456643 gave you the correct solution, which is to create a new, unique object for every entry in your array.
Make sure to initiate the array:
NSMutableArray *stack=[[NSMutableArray alloc] init];
This is because every time you init the array. Initialize the array once.
For example:
in .h
Coordinate*c;
in .m
- (void)viewDidLoad
{
c = [[Coordinate alloc] init];
}
-(void)addToStack:(Coordinate *)coord{
c.x=coord.x;
c.y = coord.y;
if (coord.x==0 && coord.y==0) {
c.x=coord.x+1;
[_stack addObject:c];
c.x=coord.x;
c.y=coord.y+1;
[_stack addObject:c];
c.y=coord.y;
}
}

Explain recursive call possibly related to scope

I kind of understand recursion. We start on one method and it calls itself until it reaches its base case. Please help me understand how this code works. I know we are popping off an object off stack each time it is called we are returning a double at the end when the base case is reached.Is stack being modified each time it is called? For example: 3 (Enter) 5 (Enter) * would obviously equal 15. However based on the method when I look at it I follow that it goes into multiply if statement sends stack (3,5) returns 5 then on the second call sends(3,5) and returns 5 again? Why is the second one being sent stack(3) instead of (3,5)?
+ (double)popOperandOffProgramStack:(NSMutableArray *)stack
{
double result = 0;
id topOfStack = [stack lastObject];
if (topOfStack) [stack removeLastObject];
if ([topOfStack isKindOfClass:[NSNumber class]])
{
result = [topOfStack doubleValue];
}
else if ([topOfStack isKindOfClass:[NSString class]])
{
NSString *operation = topOfStack;
if ([operation isEqualToString:#"+"]) {
result = [self popOperandOffProgramStack:stack] +
[self popOperandOffProgramStack:stack];
} else if ([#"*" isEqualToString:operation]) {
result = [self popOperandOffProgramStack:stack] *
[self popOperandOffProgramStack:stack];
} else if ([operation isEqualToString:#"-"]) {
double subtrahend = [self popOperandOffProgramStack:stack];
result = [self popOperandOffProgramStack:stack] - subtrahend;
} else if ([operation isEqualToString:#"/"]) {
double divisor = [self popOperandOffProgramStack:stack];
if (divisor) result = [self popOperandOffProgramStack:stack] / divisor;
}
}
return result;
}
You write:
I know we are popping off an object off stack each time it is called we are returning a double at the end when the base case is reached.Is stack being modified each time it is called?
So you know an object is popped off the stack, which means the stack changes. So why would you think the stack as not modified?
Are you maybe confusing the contents of the variable stack, with the object it references? The contents of the variable stack do not change - that contents is a reference to an object (or type NSMutableArray). However the internal state of the referenced object change, each time removeLastObject is called.
Think of it like a house - which has a street address (the reference to the object), and some people in it (the internal state of the object) - as people enter and leave the house (items pushed and popped from the stack) then the internal state keeps changing, but the street address of the house never changes.
HTH.
it goes into multiply if statement sends stack (3,5) returns 5 then on the second call sends(3,5) and returns 5 again?
No. After the first call the stack is reduced. On the second call it sends only (3). Relevant code modifying the stack:
if (topOfStack) [stack removeLastObject];

EXC_BREAKPOINT: Message sent to deallocated instance

I get the above message in XCode 4.6. I've done a pretty thorough search and but nothing seems to match the exact circumstances surrounding my issue. Admittedly, I'm relatively new to iOS dev, and memory-management has never been my strong suit, but this just has me completely miffed.
I have an instance variable theLink which is defined in the class Game as follows:
#interface Game : NSObject
// Class objects
#property(nonatomic,retain) NSMutableArray *queryItems;
#property(nonatomic,retain) NSMutableArray *theArray;
#property(nonatomic,retain) NSString *theLink;
#property(nonatomic,retain) NSString *thePath;
theLink is set in the makeGame method which is called in the method initialiseGame in my view controller:
- (void) initialiseGame
{
bool gameCreated = FALSE;
while (!gameCreated)
{
gameCreated = [theGame makeGame:#"ptl"];
}
[loadingIndicator stopAnimating];
[loading setText:#"Tap to Start"];
[self performSelector:#selector(setLabels) withObject:nil afterDelay:0.0];
}
(Note: the performSelector afterDelay is used to allow the view to update before continuing. Bit of a hack but I couldn't work out a better way!)
The app then loads the game, and when the user taps the screen to start, the next method which is called from the view controller is:
- (void) setupLink
{
...
for(int i=0; i<[theGame.theLink length]; i++) {
...
}
}
It is on this reference to theGame.theLink where I'm am getting the crash.
What has me most confused is that if I call theGame.theLink from inside the initialiseGame method, it is displays correctly, and also calling any other variable from the Game class (such as thePath or theArray works perfectly, so theGame object has not been deallocated in it's entirety, only the variable theLink.
It seems to me that the variable is being deallocated somewhere as the view controller is being updated. I haven't released the variable, and can't work out why only this variable is being deallocated. As I said at the start, memory-management is not my strength!
Any help/ideas would be hugely appreciated. Let me know if you require any more details.
Thanks heaps,
Andrew
EDIT: Setting of theLink within makeGame
- (bool) makeGame:(NSString*)gameType
{
...
[self getLink];
}
- (void) getLink
{
...
if (... && ((arc4random() % 10) > 8))
{
theLink = #"Animals";
}
}
There are many different ways theLink may be set, depending on random numbers and other factors. This is the most basic form which simply sets it to a static string. It doesn't matter how theLink is set or what it is set to, the program always crashes at the same point.
If theLink is being set to the parameter being passed to it ,#"ptl" or some similar temporary string, it will give you a problem, because it is just a pointer pointing at the current location that is holding #"ptl". After the makeGame method is completed, your system will assume that it is all done with #"ptl" and just free it up.
When you make an #"stringwhatever" in your code, it is supposed to be the equivalent of making an NSObject that is an immutable literal instance of #"stringwhataver". It should, in theory handle all the reference counting in a nice way, but when you are doing your own memory management, there are so many ways to lose count of your references.
There's a pretty simple rule to follow. If you've declared properties, access them via the property. To do otherwise (as you are doing above, with theLink = ...) bypasses all of the memory management built into the property accessors.
self.theLink = ...
Would have solved this problem under MRC. Switching to ARC has "solved" your problem without you understanding the root cause.

Implementing a life/score system in cocos2d

I am trying to implement a live/score system using cocos2d and box2d. my bodies are box2d bodies which collide as I want them to but the problem is that I have been trying to implement a score system where on each collision a life is removed or reduced from the lives left and after a certain number of collisions(say 3) the game is supposed to stop. On this occasion it doesn't but from the CCLOG I find out that it actually prints out the message I put in to display when the game manager is called but a weird thing is that it calls it forever(see the debugging window below)also it removes the object, "man" from the scene completely on starting the application.
I have a gameManager(singleton) class where in the .h file I have this declared
#interface GameManager : NSObject {
int lives;
}
-(void)removeLives : (int)val;
and in the gameManager.m file I have this method
-(void)removeLives : (int)val
{
lives -=val;
CCLOG(#"YOU HAVE LOST A LIFE MAN");
}
In my main gameLayer.mm file in the update method I have this code
if(kStateColliding){
if (lives > 0) {
man.visible = TRUE;
} else if (lives <= 0) {
[man stopAllActions];
man.visible = FALSE;
[[GameManager sharedGameManager] removeLives:1];
}
}
and the lives is initialised in gameManager init method thus
-(id)init { // 8
self = [super init];
if (self != nil) {
// Game Manager initialized
CCLOG(#"Game Manager Singleton, init");
lives = 3;
}
This is a screen shot of the debug console
Also note that I have a "Man" class which is Box2d class.
Am I doing the correct thing? Please can anyone help me out with how to go about implementing this system and where and how to make the appropriate calls.
Your call to [[GameManager sharedGameManager] removeLives:1] is within the else if (lives <= 0) block. It should only be called when lives > 0.
You will want to do something after the man has no lives left to prevent the if (kStateColliding) block from being called. Also, you will probably want to reset the mans position away from the object it is colliding with to prevent a single "collision" triggering multiple calls to removeLives.
Where are you declaring lives in gameLayer.mm? Make sure it is being set to the value stored in the singleton because with you current code, I dont see how it could possibly by set to 0 or below unless it is being initialized to 0 or you are changing its value elsewhere.
I would ask cocos2d questions like this in the cocos2d forums: http://www.cocos2d-iphone.org/forum/
There you will get answers more quickly, often within minutes.

Resources