Confused: AGSMapViewCalloutDelegate and Graphic's InfoTemplateDelegate

501
2
Jump to solution
04-03-2013 11:43 AM
AaronConnolly
Occasional Contributor
I am confused as to how the AGSMapViewCalloutDelegate and the Graphics's infoTemplateDelegate work together.

I use a unique value renderer and a graphics layer in my map. The UVR symbolizes my graphics correctly, however when I add a simple info template delegate to each of my graphics in it's initializer tapping (or clicking) in simulator does not fire:

mapView:shouldShowCalloutForGraphic:

Why?

In my map view controller's viewDidLoad I hook up the map's calloutDelegate:

self.mapView.calloutDelegate = self;


I add the info template like this to my graphics. Record is a simple object I use to encapsulate data. Note that my template is added to a local mutable array of template object so as to be retained. When the app starts up the points are displayed correctly, but tapping on the graphics doesn't do anything. What am I doing wrong?

 Record *record = (Record*)[pointArray objectAtIndex:0];               NSMutableDictionary *attributeDictionary = [record mutableDictionaryForRecord];                 // Create attributes dictionary from record object  [attributeDictionary setObject:record.legendID forKey:legendAttribute];                         // Add legendID for legend attribute to be used by renderer               AGSPoint *point = [AGSPoint pointWithX:record.x y:record.y spatialReference:_sourceMapManager.map.spatialReference];              AGSCalloutTemplate* template = [[AGSCalloutTemplate alloc] init]; template.titleTemplate = @"${legendLabel}"; template.detailTemplate = @"${address}";              // Create graphic AGSGraphic *graphic = [AGSGraphic graphicWithGeometry:point                                                            symbol:nil                                                        attributes:attributeDictionary                                              infoTemplateDelegate:template];              [_sourceGraphicsLayer addGraphic:graphic]; [_graphicTemplates addObject:template];


Does this have anything to do with passing in a nil symbol and allowing the renderer to symbolize the graphics? I've read the docs and it doesn't appear to say anything about this.

Thanks,
- Aaron
0 Kudos
1 Solution

Accepted Solutions
DanaMaher
Occasional Contributor

I use a unique value renderer and a graphics layer in my map. The UVR symbolizes my graphics correctly, however when I add a simple info template delegate to each of my graphics in it's initializer tapping (or clicking) in simulator does not fire:
...

I add the info template like this to my graphics. Record is a simple object I use to encapsulate data. Note that my template is added to a local mutable array of template object so as to be retained. When the app starts up the points are displayed correctly, but tapping on the graphics doesn't do anything. What am I doing wrong?


Apologies for asking the obvious, but are you sure you are instantiating the NSMutableArray that retains your templates before it is being used? XCode gives you no instant, compile, or run time warning if you are attempting to call a nil object, and calling addObject: on an uninitialized NSMutableArray will not cause a crash, but will cause the same memory management issues that would arise from not adding the object to the array.

I ask because I recently had to solve the issue you describe (callouts not displaying and callout-related callbacks not occurring). I had initially missed the weak property assign on infoTemplateDelegate, so my first attempted fix was to retain the template objects in an array, like you are doing. On my first test of this fix, the problem persisted for one possible workflow, which was perplexing until I realized that my overarching class had two initialization methods and I was only initializing the retainer array in one of them.

I am confused as to how the AGSMapViewCalloutDelegate and the Graphics's infoTemplateDelegate work together.

Does this have anything to do with passing in a nil symbol and allowing the renderer to symbolize the graphics? I've read the docs and it doesn't appear to say anything about this.



I don't think the use of a renderer vs. an assigned symbol has any effect other than how the symbol is eventually drawn in the OpenGL layer. This is based on the knowledge that that graphics are all rendered flat to one layer; to the OpenGL kit and Cocoa Touch processing, they are all part of a flat sheet. Presumably, some other code, independent of the rendering code, is checking whether the geometries of the AGSGraphic objects fall within the current touch.

View solution in original post

0 Kudos
2 Replies
DanaMaher
Occasional Contributor

I use a unique value renderer and a graphics layer in my map. The UVR symbolizes my graphics correctly, however when I add a simple info template delegate to each of my graphics in it's initializer tapping (or clicking) in simulator does not fire:
...

I add the info template like this to my graphics. Record is a simple object I use to encapsulate data. Note that my template is added to a local mutable array of template object so as to be retained. When the app starts up the points are displayed correctly, but tapping on the graphics doesn't do anything. What am I doing wrong?


Apologies for asking the obvious, but are you sure you are instantiating the NSMutableArray that retains your templates before it is being used? XCode gives you no instant, compile, or run time warning if you are attempting to call a nil object, and calling addObject: on an uninitialized NSMutableArray will not cause a crash, but will cause the same memory management issues that would arise from not adding the object to the array.

I ask because I recently had to solve the issue you describe (callouts not displaying and callout-related callbacks not occurring). I had initially missed the weak property assign on infoTemplateDelegate, so my first attempted fix was to retain the template objects in an array, like you are doing. On my first test of this fix, the problem persisted for one possible workflow, which was perplexing until I realized that my overarching class had two initialization methods and I was only initializing the retainer array in one of them.

I am confused as to how the AGSMapViewCalloutDelegate and the Graphics's infoTemplateDelegate work together.

Does this have anything to do with passing in a nil symbol and allowing the renderer to symbolize the graphics? I've read the docs and it doesn't appear to say anything about this.



I don't think the use of a renderer vs. an assigned symbol has any effect other than how the symbol is eventually drawn in the OpenGL layer. This is based on the knowledge that that graphics are all rendered flat to one layer; to the OpenGL kit and Cocoa Touch processing, they are all part of a flat sheet. Presumably, some other code, independent of the rendering code, is checking whether the geometries of the AGSGraphic objects fall within the current touch.
0 Kudos
AaronConnolly
Occasional Contributor
Apologies for asking the obvious, but are you sure you are instantiating the NSMutableArray that retains your templates before it is being used? XCode gives you no instant, compile, or run time warning if you are attempting to call a nil object, and calling addObject: on an uninitialized NSMutableArray will not cause a crash, but will cause the same memory management issues that would arise from not adding the object to the array.


You're right. At run time my NSMutableArray was nil. Previously the SDK would throw an error when you tapped a symbol that had a nil pointer to a template. I guess I was hoping to use *that* crash as a sign that my array hadn't been allocated. Should have just debugged the array.

Thanks. I've made this mistake several times before 🙂
0 Kudos