I am using a custom map annotation class for map view in iPhone. Whenever I pop my map view from navigation bar stack I usually see some warnings in console.
MapAnnotation was deallocated while key value observers were still registered with it. Observation info was leaked, and may even become mistakenly attached to some other object. Set a breakpoint on NSKVODeallocateBreak to stop here in the debugger. Here's the current observation info:
I am not using KVO in my code hence not able to understand why I am receiving these warnings
Latitude and Longitude have differing bounds:
(-90, 90) for Lat
(-180, 180) for Long
Passing a value outside of those bounds will cause the custom class to be deallocated and therefore giving you the error that you're receiving. Make sure that you are passing the correct values for both Latitude and Longitude.
It would be really nice if Apple passed a bounding error for this instead of an early release error. That would've saved me roughly 5 hours worth of time
I was getting the same error as you:
An instance 0xa975400 of class xxxxxx was deallocated while key value observers were still registered with it. Observation info was leaked, and may even become mistakenly attached to some other object. Set a breakpoint on NSKVODeallocateBreak to stop here in the debugger. Here's the current observation info:
<NSKeyValueObservationInfo 0xa980eb0> (
<NSKeyValueObservance 0xa980e70: Observer: 0xa94f8a0, Key path: coordinate, Options: <New: NO, Old: NO, Prior: YES> Context: 0x0, Property: 0xa980ef0>
As pointed here it was caused because I was adding a MKAnnotation with an invalid coordinate to a MKMapView.
My solution was to create a function to check the coordinate valid.
Place+MKAnnotation.m
I created a category of my Place class and
#import "Place.h"
#import <MapKit/MapKit.h>
#interface Place (MKAnnotation) <MKAnnotation>
- (BOOL)coordinateIsValid;
...
#end
Place+MKAnnotation.m
#implementation Place (MKAnnotation)
- (BOOL)coordinateIsValid
{
return CLLocationCoordinate2DIsValid(CLLocationCoordinate2DMake([self.latitude doubleValue],[self.longitude doubleValue]));
}
...
#end
I only add the annotation in my ViewController if the coordinate is valid.
if([p coordinateIsValid]) {
[self.mapView addAnnotation:p];
}
Fixed it. I was using a wrong pair of latitude and longitude in annotations, I have changed the same and now everything seems to be perfect and warning has been disappeared as well.
Are you autoreleasing your annotation before adding it to the MapView?
If so, try just allocating it, add it to the MapView, then release it.
Related
I have added a button on my .xib file with which I want to delete the last annotation that has been added.
So on the Touch-Down action I have implemented this:
-(IBAction)DeleteAnnotation:(id)sender {
[mapview removeAnnotation:[mapview.annotations lastObject]];
}
and I have even tried it this way:
-(IBAction)DeleteAnnotation:(id)sender {
[self.mapview removeAnnotation:self.mapview.annotations.lastObject]];
}
where mapview is my MKMapView Outlet.
The problem I encounter with both ways is that I have to press this specific button quite a few times before an annotation is removed.
Furthermore, the annotations remove themselves in a quite random way.
Is there something I am doing wrong or is it a software and simulator matter?
The annotations property of MKMapView is not guaranteed to return the annotations in the same order that you added them.
Making the assumption that the annotations array property will return the annotations in the same order that you added them is most likely the reason for the "strange" behavior you see. Please see these related answers for some more details:
MKMapView annotations changing/losing order?
How to reorder MKMapView annotations array
To get the behavior you want (which I assume is simply "remove the last annotation that was added explicitly by my code"), here are three possible approaches (there may be others):
Simplest approach is to keep a reference in a strong property to the last annotation you add (update the reference when you call addAnnotation). When you want to remove the "last annotation added", pass that saved reference to removeAnnotation. For example:
//in the interface...
#property (nonatomic, strong) id<MKAnnotation> lastAnnotationAdded;
//in the implementation...
//when you add an annotation:
[mapview addAnnotation:someAnnotation];
self.lastAnnotationAdded = someAnnotation; //save the reference
//when you want to remove the "last annotation added":
if (self.lastAnnotationAdded != nil)
{
[mapview removeAnnotation:self.lastAnnotationAdded];
self.lastAnnotationAdded = nil;
}
Another option is to loop through the map view's annotations array and search for the "last" annotation (or whatever attribute you're interested in). Once you have a reference to the "last" one (which may not necessarily be the last object in the array), you can call removeAnnotation on it. This approach assumes you have some property in the annotation objects themselves that let you identify an annotation as the "last" one. This may not always be possible.
Another option is to keep your own array of annotations and add annotation objects to this array whenever you call addAnnotation. This is similar to keeping the single reference to just the "last annotation added" except you keep track of the entire list in an order you can rely on. To remove the "last" one, you would get lastObject from your array instead of the map view's (assuming you keep the array in that order). You have to make sure to keep your array in sync as you add/remove annotations from the map.
today I got an error with an explanation :) There's only one problem: I don't understand it :( So what am I doing wrong when I get this error?
2012-04-30 03:04:35.737 Barz[21961:11903] An instance 0x7491960 of class BarAnnotation was deallocated while key value observers were still registered with it. Observation info was leaked, and may even become mistakenly attached to some other object. Set a breakpoint on NSKVODeallocateBreak to stop here in the debugger. Here's the current observation info:
<NSKeyValueObservationInfo 0x74a18b0> (
<NSKeyValueObservance 0x74a1700: Observer: 0x747f2b0, Key path: coordinate, Options: <New: NO, Old: NO, Prior: YES> Context: 0x0, Property: 0x74a11c0>
)
Not that I did NOT add any observer manually, I just remove and add "BarAnnotation" (my custom MKAnnotation) to my mapView in the method viewWillAppear?
I'm also not quite sure if I understood who is observing whom: Is my mapView observing all of the MKAnnotations? Or is my mapViewController (== mapView's delegate) observing? And why does it behave like that if I disabled dragging?
Hope someone can help me and answer some of these questions :)
I've seen this happen when the annotation's coordinates are invalid. Have you checked that?
I am trying to use the mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated method to limit the region of my mapview but whenever I make a call to my mapview's region ([self.userMapView setRegion:regionLimit] ), it gives me a EXC_BAD_ACCESS error.
This error is thrown no matter what property I try to call from my mapView. I have my mapview set to the mapview with a proper outlet, and I was even able to call the set region in the viewDidLoad message.
How can I keep these properties from throwing the bad access error? If no can answer, can anyone direct me to a resource explaining how to debug something like this? Thanks.
See here for his to debug EXC_BAD_ACCESS errors and common mistakes that cause them. In your case, I'll bet your property is long dead and recycled, or was never initialized in the first place.
I have an object that is interested in knowing when the region of a MKMapView is changed. This object is not the delegate of the map view, however. I'm trying the following, where map is a MKMapView:
[map addObserver:self forKeyPath:#"region" options:0 context:nil];
However, observeValueForKeyPath:ofObject:change:context: isn't being called back.
As an interim solution, I have the map's delegate letting this other object know when the map region is changed, but I'd like to uncouple the two objects as they aren't really related.
In Cocoa (Touch), properties of framework objects are only guaranteed to be KVO-compliant if the documentation says so. The docs for -[MKMapView region] make no such claim, so you shouldn't try to use KVO upon it. Even if it happened to work, you'd have no guarantee of complete compliance, or of continued success.
Instead, you'll have to use the delegate method and message other objects from there. Possibly your delegate could broadcast an NSNotification to achieve a similar effect to KVO.
i want to write my own photogallery like the original "Photos.app" from apple.
I´ve created a UITabbarcontroller in the AppDelegate and then an "ImageViewController" and a "VideoViewController".
In the "ImageViewController" i´ve added an UIScrollView and then made an instance of my own "PhotoGallery" with different properties like imagePerRow, images, paddings etc.
For the "PhotoGallery" i´ve created a new objective-c class as a subclass of "NSObject", where i´m positioning all the different images as UIButtons.
Then i´ve added another function which describes the arrangement for all the images when the device orientation has changed. And the dealloc-function. Thats all.
This class works great, also the rearrangement when the device orientation has changed. The problem is, if i simulate a memory warning in the ios-simulator, the first time the PhotoGallery gets correctly dealloc but if i simulate a warning again, i get a error-message: "[PhotoGallery release]: message sent to deallocated instance ".
I thought its because of the subclass as NSObject, right?
Then i´ve tested it as a UIView. With the same error. So know i don´t know what to do anymore. Hope you understand what´s the problem and you would give me some hints on that..
Think about calling the init-function again? How? Need "drawRect"? I´ve no idea.
Thanks for your time and help,
G.
You're probably not setting the property which holds a reference to the PhotoGallery to nil.
ie. You're keeping a reference to a deallocated instance, and attempting to call release on it.
bad example:
- (void) didReceiveMemoryWarning
{
[photoGallery release];
}
safe(r) example:
- (void) didReceiveMemoryWarning
{
[photoGallery release];
photoGallery = nil;
// or combine both actions if your property attributes are set up to accommodate it:
// self.photoGallery = nil;
}
In the bad example, photoGallery still holds a reference to a now-deallocated instance, and the second memory warning will attempt to send a message to it.
In the safe(r) example, photoGallery is nil, and sending a message to nil is safe.