What I do in my app is following:
I load some data into the core data and when that is finished app needs to segue to the next view (google map)
[self performSegueWithIdentifier:#"loadMap" sender:self];
but I get this error
Terminating app due to uncaught exception 'GMSThreadException', reason: 'All calls to the Google Maps SDK for iOS must be made from the UI thread'
If I do all of this but make a segue with tap on a button everything works fine.
Google map view controller in storyboard has one GMSMapView view outlet with init code
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:45.331875
longitude:14.450455
zoom:14];
self.mapView.camera = camera;
GMSMarker *marker = [[GMSMarker alloc] init];
marker.position = camera.target;
marker.title = #"Test title";
marker.snippet = #"Lorem ipsum...";
marker.map = self.mapView;
Can anybody help me here? How can I load view controller with google maps programmatically using storyboard?
The exception seems to be indicating that you're trying to perform a segue in the background thread. To stop it from crashing, you need to use the main thread instead. Wrap your performSegueWithIdentifier:sender: as follows to use the main thread:
dispatch_async(dispatch_get_main_queue(), ^{
[self performSegueWithIdentifier:#"loadMap" sender:self];
});
For Swift:
dispatch_async(dispatch_get_main_queue(), {})
Toss the code in those curlies...
Related
In my app I'm downloading the location data and showing them on the map. There are some scenarios which I cannot understand why they are happening. Sometimes, my mapView(Google map) class dealloc is getting called and I'm unable to see the markers on my map(I can still see my current location).
This is how my mapView is setUp in the storyBoard:
[ContainerVc] -embedSegue->[MapView]
Container Vc is the root Vc.
and in my rootVc class:
#property (weak, nonatomic) MapVc *mapVc;
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString: #"embeddedMapVc"]) {
self.mapVc = [segue destinationViewController];
self.mapVc.delegate = self;
}
}
and in my mapVC class(all the properties are strong,nonatomic):
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
[self setupMapView];
}
- (void)setupMapView{
MyLog(#"Map view just refreshed/setup");
//set map view
self.infoWindow = [[MyMapInfoWindow alloc] initWithFrame:CGRectMake(0, 0, 210, 47)];
self.infoWindow.delegate = self;
CLLocation *center = [[MyLocationMonitor sharedInstance] getLocation];
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:center.coordinate.latitude longitude:center.coordinate.longitude zoom:18];
self.mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
self.mapView.camera=camera;
[self.mapView setMapType:kGMSTypeNormal];
[self.mapView setMinZoom:14 maxZoom:18];
[self.mapView setDelegate:self];
self.mapView.myLocationEnabled=YES;
self.mapView.settings.rotateGestures = NO;
self.mapView.settings.myLocationButton = YES;
[self.mapView setPadding:UIEdgeInsetsMake(0, 0, 62, 0)];
self.view = self.mapView;
[self setupMarkers];
}
- (void)setupMarkers{
MyLog(#"setting up markers");
self.annotations = nil;
[self.mapView clear];
[[MyLocationMonitor sharedInstance] getBuildingsWithCompletion:^(BOOL success, NSArray *buildings) {
self.buildings = buildings;
MyLog(#"_buildings_: %#", self.buildings);
if (success) {
GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] init];
self.annotations = [[NSMutableArray alloc] init];
for (NSDictionary *location in buildings) {
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake([[location objectForKey:#"Latitude"] doubleValue], [[location objectForKey:#"Longitude"] doubleValue]);
bounds = [bounds includingCoordinate:coordinate];
GMSMarker *marker = [GMSMarker markerWithPosition:coordinate];
marker.title = [location objectForKey:#"name"];
marker.map = self.mapView;
marker.icon = [UIImage imageNamed:#"Boost-BuildingMarkerIcon"];
marker.userData = #{#"building":location};
marker.infoWindowAnchor = CGPointMake(1.0f, -0.1f);
marker.opacity = 1.0;
[self.annotations addObject:marker];
}
[self.mapView animateWithCameraUpdate:[GMSCameraUpdate fitBounds:bounds withPadding:50.0]];
}
}];
}
-(void)dealloc{
MyLog(#"MApVC dealloc called");
}
So, from the rootVc I move to another controller and after I finish a network call I comeback to rootVc, where the prepareForSegue gets triggered and the call goes to mapVc class, and it setups the mapView(In this process mapVc dealloc gets called sometimes in that case, I'm unable to see the markers on the map).
I couldn't get much info from stacktrace. I would like to know why my mapVc is getting deallocated sometimes ? How to make sure my mapVc is not deallocated at any time ?
Edit:
I logged the mapVc self in the dealloc case:
<MapVc: 0x7ff83f2883c0> On didAppear
<MapVc: 0x7ff83f2883c0> on dealloc (why is this happening ?)
<MapVc: 0x7ff84475b6f0> new instance again on viewDidAppear
How to make sure my mapVc is not deallocated at any time ?
If you require a VC to exist at a time when it is not onscreen (or at least in a navigation stack), then you have broken MVC. I don't think that's quite what's happening here, but it's important to keep in mind. Network operations should happen in your Model layer, and your view layer should observe the model. View controllers are responsible for managing views that are currently visible, not network operations. You likely have organized your view controllers incorrectly.
That said, that probably isn't the actual problem in this case. The problem is that nothing is retaining mapVc. It's weak in the root view controller so it's probably being released as soon as the segue is complete (the segue retains it while it is running). If mapVc is embedded in the root view controller, it should almost certainly be strong.
I have a splitviewcontroller application where the master view controller is a UITableView and the detail view controller contains a MKMapView and a single annotation. When I make a selection in the UITableView the secondary view segues to a different map view with a single annotation.
When I select an annotation and then immediately afterwards (before the annotation popover appears) select a cell I receive an EXC_BAD_ACCESS crash. I used the Zombies tool to try and gather further information and I received this message.
An Objective-C message was sent to a deallocated 'MKPopoverBasedAnnotationCalloutController' object (zombie)
I believe the issue here is that the map view is still trying to display the annotations popover but the annotation has been deallocated.
So far I have tried:
•Setting MKMapView delegate nil on dealloc
Note: I am not using any custom popovers for the annotation. I also had a similar problem when calling [mapView selectAnnotation:mp animated:YES]; and then selecting another cell. I fixed this by just not calling it. This is obviously not an ideal solution.
Any suggestions on how to solve this? Or any insight on whether it is an issue with MapKit or an Issue with my application specifically?
Thanks in Advance,
Chris
I've been able to reproduce the issue consistently and it indeed looks like a bug with Apple's mapkit code. The only way i've been able to fix it was to create a singleton for MKMapView
-(MKMapView*)mapview{
static MKMapView *_mapview = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_mapview = [[MKMapView alloc] initWithFrame:[UIScreen mainScreen].bounds];
_mapview.showsPointsOfInterest = NO;
_mapview.pitchEnabled = NO;
});
return _mapview;
}
An important note, when you remove the map don't clear the annotations yet, wait until you initialize it..
so not here...
-(void)viewDidDisappear:(BOOL)animated{
[super viewDidDisappear:animated];
[self.mapview removeFromSuperview];
self.mapview.delegate = nil; //AND OR IN DEALLOC
}
but here ...
- (void)viewDidLoad{
[super viewDidLoad];
[self.view addSubview:self.mapview];
self.mapview.delegate = self;
[self.mapview removeAnnotations:[self.mapview annotations]];
//RECREATE THOSE ANNOTATIONS
}
I use google maps iOS SDK with storyboard. Application starting with Navigation View Controller that has a Root View Controller with map.
#implementation MyViewController
#synthesize btnMyLock;
#synthesize btnNearby;
GMSMapView *mapView_;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:20
longitude:20
zoom:0];
mapView_ = [GMSMapView mapWithFrame:CGRectZero camera:camera];
mapView_.myLocationEnabled = YES;
self.view = mapView_;
// Creates a marker in the center of the map.
GMSMarker *marker = [[GMSMarker alloc] init];
[marker setIcon:[UIImage imageNamed:#"pin"]];
marker.position = CLLocationCoordinate2DMake(-33.86, 151.20);
marker.title = #"Sydney";
marker.snippet = #"Australia";
marker.map = mapView_;
mapView_.settings.compassButton = YES;
[mapView_ addSubview:btnMyLock];
[mapView_ addSubview:btnNearby];
}
Button btnMyLock push the Table View Controller. In iOS 7 it's ok. But iOS 6 my app crashes. Sometimes crash with EXC_BAD_ACCESS (code=1) or code=2
Problem that I used Autolayout view.
you forgot step 4: "Drag the GoogleMaps.bundle" from the Resources folder to your project.
I suggest putting it in the Frameworks group. When prompted, ensure "Copy items into destination group’s folder" is not selected. i encountered the same problem, and this fixed it.
I don't know if it's causing the problem, but I wouldn't do:
self.view = mapView_;
Just add the mapView_ as a subview, like:
[self.view addSubview:mapView_];
In general EXC_BAD_ACCESS crashes are caused when you are mismanaging memory (e.g. an object is being deallocated prematurely). Try to find out what object the crash is happening on.
Create your buttons in code, not from the xib as IBOutlets. Otherwise they are not loaded since you are not using the xib.
Use this code when you use Google map and then check its not crash when you navigate to another screen.
- (void)dealloc {
[super dealloc];
[mapView_ removeObserver:self
forKeyPath:#"myLocation"
context:NULL];
}
I am using Google Maps SDK in my Iphone app.
Now I want to drop marker when user touch and hold on map more than 2 sec on touched place, but I can't find any solution.
Thank you...
I have found solution.
You should implement GMSMapViewDelegate protocol on the view controller that displays the map and listen to didLongPressAtCoordinate event.
#interface MapViewController : UIViewController<GMSMapViewDelegate>
and
-(void) mapView:(GMSMapView *)mapView didLongPressAtCoordinate:(CLLocationCoordinate2D)coordinate{
GMSMarker *marker3 = [[GMSMarker alloc] init];
marker3.position = coordinate;
marker3.title = #"170 Asbury Anderson Rd";
marker3.snippet = #"US";
marker3.map = mapView_;
}
Protocol GMS Map View Delegate
Hi I am trying to show camera controls using zbar in ios for scanning.
i have written following code
ZBarReaderViewController *readerController = [[ZBarReaderViewController alloc] init];
readerController.sourceType = UIImagePickerControllerSourceTypeCamera;
readerController.tracksSymbols = YES;
readerController.showsCameraControls = YES;
readerController.showsZBarControls = YES;
[readerController release];
But application crash every time when i show zbar controller.
and app work fine if i remove this line
readerController.showsCameraControls = YES;
But then i can not see any control on scan view
"BOOL showsCameraControls Raises an exception if anything other than NO is set."
Check the following link for details: ZBarReaderViewController Class Reference. Cheers