Querying local geodatabase "EXC_BAD_ACCESS" error

3168
3
Jump to solution
05-30-2014 02:56 PM
philwillis
New Contributor
I'm trying to query a local-geodatabase and display the results in a TableView however i'm having a thread error "EXC_BAD_ACCESS". I assume cause i have to be on the main thread to update the UI. I've tried using the performSelectorOnMainThread:@selector(reloadData) on the tableView but no luck!


<property for table array>
@property (nonatomic, strong) NSArray *localGDBQueryResult;



<method to query the database>
-(void) localgeodatabaseSearchForValue:(NSString*)searchString {   NSError *GDBError;   AGSGDBGeodatabase *gdb = [AGSGDBGeodatabase geodatabaseWithName:@"mygeodb" error:&GDBError];         if (gdb) {      AGSGDBFeatureTable *table = [gdb featureTableForLayerName:@"Mileposts"];          NSString *fieldname = @"MPOINT";     AGSQuery *query = [[AGSQuery alloc] init];     query.where = [NSString stringWithFormat:@"%@ = '%@'",fieldname, searchString];          [table queryResultsWithParameters:query           completion:^(NSArray *results, NSError *error) {                              if (!error) {                   self.localGDBQueryResult = results;                   [self.searchDisplayController.searchResultsTableView performSelectorOnMainThread:@selector(reloadData)                                                                                         withObject:nil                                                                                      waitUntilDone:NO];               } else {                   // Log details of the failure                   NSLog(@"Error: %@ %@", error, [error userInfo]);               }           }];   } }




<tableview methods>
 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {  return 1; }  - (NSInteger)tableView:(UITableView *)tableView  numberOfRowsInSection:(NSInteger)section {  return [self.localGDBQueryResult count]; }  - (UITableViewCell *)tableView:(UITableView *)tableView          cellForRowAtIndexPath:(NSIndexPath *)indexPath {  UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"cell"];       if (!cell) {      cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault                                       reuseIdentifier:@"cell"];  }     cell.textLabel.text = [[self.localGDBQueryResult objectAtIndex:indexPath.row] valueForKey:@"RoadName"];  return cell; } 
0 Kudos
1 Solution

Accepted Solutions
philwillis
New Contributor
ended up dumping the results into a dictionary and working the the keys


@property (nonatomic, strong) NSArray *queryArrayResults; @property (nonatomic, strong) AGSGDBFeatureTable *table;


-(void) localgeodatabaseSearchForValue:(NSString*)searchString {     NSError *GDBError;     AGSGDBGeodatabase *gdb = [AGSGDBGeodatabase geodatabaseWithName:@"mygeodb" error:&GDBError];       if (gdb) {                  self.table = [gdb featureTableForLayerName:self.segmentSelection];         NSString *fieldname = @"Mileposts";          AGSQuery *query = [[AGSQuery alloc] init];         query.where = [NSString stringWithFormat:@"%@ = '%@'",fieldname, searchString];                  [self.table queryResultsWithParameters:query                                     completion:^(NSArray *results, NSError *error) {                                                      if (!error) {                 NSArray *arr = results;                 NSMutableArray *mutArr = [[NSMutableArray alloc]init];                 for (int i =0; i<[arr count]; i++) {                     AGSGDBFeature *feat =[arr objectAtIndex:i];                     NSDictionary *dic = [[NSDictionary alloc] initWithDictionary:[feat allAttributes]];                     [mutArr addObject:dic];                                      }                 self.queryArrayResults = [mutArr copy];                  // reload the table                 [self.searchDisplayController.searchResultsTableView performSelectorOnMainThread:@selector(reloadData)                                                                                       withObject:nil                                                                                    waitUntilDone:NO];             } else {                 // Log details of the failure                 NSLog(@"Error: %@ %@", error, [error userInfo]);             }         }];     } }


and finally the tableView
- (NSInteger)tableView:(UITableView *)tableView  numberOfRowsInSection:(NSInteger)section {  return [self.queryArrayResults count]; }  - (UITableViewCell *)tableView:(UITableView *)tableView          cellForRowAtIndexPath:(NSIndexPath *)indexPath {  UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"cell"];       if (!cell) {      cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault                                       reuseIdentifier:@"cell"];  }      cell.textLabel.text = [[self.queryArrayResults objectAtIndex:indexPath.row] objectForKey:@"RoadName"];        return cell; }

View solution in original post

0 Kudos
3 Replies
DirkVandervoort
Occasional Contributor II
Did you ever resolve this issue? My code is virtually identical yours when this issue became apparent.

Another curious affect is when I do a spatial query (a user-defined envelope), when the envelop gets dragged beyond the extent of the AGSMapView, the query is successful and the UITableView gets hydrated (see first screen cap). However, when the user-defined envelope is entirely within the AGSMapView, the query fails and a "EXC_BAD_ACCESS" gets raised (see second screen cap). The results in an NSArray are AGSGDBFeatures, but accessing any of the fields using [gdbFeature attributeAsStringForKey:@"MyFieldName"] pukes the error.

Note that I explicitly use [myQuery setOutFields:outFields]; when creating the AGSQuery. This is on 10.2.1 release.

TIA.
[ATTACH=CONFIG]34317[/ATTACH]
[ATTACH=CONFIG]34318[/ATTACH]
0 Kudos
DirkVandervoort
Occasional Contributor II
Problem solved:

AGSGDBFeatureTable *table = [gdb featureTableForLayerName:@"Mileposts"];

limits the scope of the property *table to the method where the query is executed. Even though the query creates instances of AGSGDBFeature, you cannot fully hydrate the AGSGDBFeature if *table is nil.

Therefore the solution is make *table a @Property of the class. This allows AGSGDBFeature to get its members from its table.
0 Kudos
philwillis
New Contributor
ended up dumping the results into a dictionary and working the the keys


@property (nonatomic, strong) NSArray *queryArrayResults; @property (nonatomic, strong) AGSGDBFeatureTable *table;


-(void) localgeodatabaseSearchForValue:(NSString*)searchString {     NSError *GDBError;     AGSGDBGeodatabase *gdb = [AGSGDBGeodatabase geodatabaseWithName:@"mygeodb" error:&GDBError];       if (gdb) {                  self.table = [gdb featureTableForLayerName:self.segmentSelection];         NSString *fieldname = @"Mileposts";          AGSQuery *query = [[AGSQuery alloc] init];         query.where = [NSString stringWithFormat:@"%@ = '%@'",fieldname, searchString];                  [self.table queryResultsWithParameters:query                                     completion:^(NSArray *results, NSError *error) {                                                      if (!error) {                 NSArray *arr = results;                 NSMutableArray *mutArr = [[NSMutableArray alloc]init];                 for (int i =0; i<[arr count]; i++) {                     AGSGDBFeature *feat =[arr objectAtIndex:i];                     NSDictionary *dic = [[NSDictionary alloc] initWithDictionary:[feat allAttributes]];                     [mutArr addObject:dic];                                      }                 self.queryArrayResults = [mutArr copy];                  // reload the table                 [self.searchDisplayController.searchResultsTableView performSelectorOnMainThread:@selector(reloadData)                                                                                       withObject:nil                                                                                    waitUntilDone:NO];             } else {                 // Log details of the failure                 NSLog(@"Error: %@ %@", error, [error userInfo]);             }         }];     } }


and finally the tableView
- (NSInteger)tableView:(UITableView *)tableView  numberOfRowsInSection:(NSInteger)section {  return [self.queryArrayResults count]; }  - (UITableViewCell *)tableView:(UITableView *)tableView          cellForRowAtIndexPath:(NSIndexPath *)indexPath {  UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"cell"];       if (!cell) {      cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault                                       reuseIdentifier:@"cell"];  }      cell.textLabel.text = [[self.queryArrayResults objectAtIndex:indexPath.row] objectForKey:@"RoadName"];        return cell; }
0 Kudos