-
Notifications
You must be signed in to change notification settings - Fork 603
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Google Maps not loading on iOS (physical device) #1366
Comments
This issue may need more information before it can be addressed. In particular, it will need a reliable Code Reproduction that demonstrates the issue. Please see the Contributing Guide for how to create a Code Reproduction. Thanks! |
can you change the id to const newMap = await GoogleMap.create({
id: 'main-map', // <--
forceCreate: true,
element: mapRef,
apiKey: apiKey,
config: {
center: {
lat: 33.6,
lng: -117.9,
},
zoom: 8,
},
}); I was able to render map on ios using this snippet |
Hi @DwieDima , |
Hi @judge , Did you found any work around for this issue? |
Unfortunetaly not. I would add "needs reply" and remove "needs reproduction" labels to the issue but I cannot do that. :( |
Hi @judge , Did you enabled Maps SDK for iOS ? |
Hi @akeeee , Yes it is enabled for both JavaScript and iOS. The JavaScript API works perfectly, it even shows request count but there is no request count for iOS. |
It seems that the ScrollView the plugin is searching for is sometimes not existing yet when the map is initialized. I worked around this by changing Map.swift like this: if let target = self.targetViewController {
target.tag = 1
target.removeAllSubview()
self.mapViewController.view.frame = target.bounds
target.addSubview(self.mapViewController.view)
self.mapViewController.GMapView.delegate = self.delegate
} else { // add this else case
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
self.render(callback)
}
return;
} If you also need your callbacks to wait until the map is created you need to call the resolve at the point that onMapReady is signaled. |
I'm also facing this issue exactly. On first use of the map, the "box" and the marker loads, but there's no actual map. If I navigate to another screen — even if that screen is using maps — I get nothing. It does work on web; I get the same logs @judge is getting from XCode. Using: 💊 Capacitor Doctor 💊 Latest Dependencies: @capacitor/cli: 4.6.3 Installed Dependencies: @capacitor/android: not installed |
@judge where you able to find a solution? |
@Simon54 thank you - that sorted it out for me. I'll now have to make sure this "patch" gets applied when this is deployed to CI. |
Bump! |
Ok... I think I found a better solution than patching What I'm doing and is consistently working is:
<template>
<div class="map-wrapper">
<capacitor-google-map id="map"></capacitor-google-map>
</div>
</template>
<style scoped>
.map-wrapper {
position: relative;
flex: 1;
}
capacitor-google-map {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
</style> (I use this component within another that uses
<script setup lang="ts">
import { GoogleMap } from '@capacitor/google-maps';
import { onBeforeUnmount } from 'vue';
import { onMounted } from 'vue';
const apiKey = import.meta.env.VITE_GOOGLE_MAPS_API_KEY;
let map: GoogleMap | null = null;
onMounted(async () => {
await new Promise(res => setTimeout(res, 300));
const mapRef = document.getElementById('map')!;
const newMap = await GoogleMap.create({
id: `my-map`, // Unique identifier for this map instance
element: mapRef!, // reference to the capacitor-google-map element
apiKey: apiKey, // Your Google Maps API Key
config: {
center: { lat: 33.6, lng: -117.9 },
zoom: 8,
},
});
map = newMap;
});
onBeforeUnmount(() => {
if (map) {
map.destroy();
map = null;
}
}) I did so many... many, many, many iterations with just a single change and this is the only solution without any changes to the plugin itself that worked! Key findings:
That's it form me and good luck. |
@judge I know this finding is some five months late, but to make my solution work in your context, since I use Vue and you do not - add a timeout before calling I personally wasn't able to make it work with the styles suggested in the official "documentation" - I had to use a wrapper DIV, so in your case I would suggest you do: this.innerHTML = `
<style>
#map-wrapper {
display: inline-block;
width: 200px;
height: 400px;
position: relative;
}
capacitor-google-map {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
</style>
<div id="map-wrapper" style="border: 1px solid red;">
<capacitor-google-map id="main-map"></capacitor-google-map>
</div>
`; I tested the above wrapper styles within my Vue app and it worked for me, but I had to move the red border to the wrapper - otherwise the dodgy logic in |
Can you give full example please? |
@metinjakupi The Unfortunately if the I did patch the swift file in the hope that would be enough of a fix, but it wasn't and I felt it is pretty bad - patching and all. |
I think is actually along the correct lines of what the fix should be. The issue is that the web view is loaded before the map view component is even available, which confuses the JS code that executes after. Any subsequent calls into the Google Maps component will 100% yield a null reference exception because the map controller is simply not initialized. This completely screams lifecycle issue, to me, honestly. Currently the code just invokes the resolve callback without any concern for if the map view controller is active or not. It just assumes so. The reason why the fix I linked above works is because it creates effectively a spinlock which ensures that the map view is always initialized before proceeding with invoking the resolve callback. I'm honestly not sure how the Google Maps plugin shipped in 5.0 considering how easy it is to reproduce this bug. |
any solution for this? |
I believe the latest alpha version of the plugin does address the delay requirement, but I haven't tested it: To be honest - I had to switch to a JS version for mapping, since this plugin proved to be less useful in several cases that we needed - like annotations (aka popups), marker SVG images and marker animation. I had to use Leaflet (+MapBox for tiles), since GoogleMaps JS requires a realtime download to import their JS libraries, which is not something we wanted. It was also such a nuisance to setup and use - no Vue (or any JS framework) support at all - just bare-bone procedural JS - a loaded foot-gun on every corner. |
Still not a fix? I am tired of trying everyhting and couldn't make it load. Only the google logo is loading inside a gray area. :( |
This doesn't fix the issue - because the issue is that the native code seems to fire off before the page is fully ready to have the map container injected/overlayed, hence why the fix suggested by #1366 (comment) works so well. Particularly this bit of code: else { // add this else case
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
self.render(callback)
}
return;
} Though, I do not believe this to be the actual fix as I believe this is merely pushing the chance of this bug happening to a condition that's pretty much never going to happen. I think the issue is that some of the code for the Map Controller just simply executes too early. |
I think this was a good hint. I spent some time now debugging some issues of this plugin but I can also now create the map with this help. I used this styling for my map which did the fix for me. It worked without a wrapper. I noticed that
A workaround might be to render the map with a styling of 200vh and when the map is initialised to reduce it again to 100vh. EDIT: I noticed that after page transitions, the map doesn't reappear anymore... (with the fix with the styling) |
I have tested the solution of @gm112 but I didn't resolve my issue. I added some extra logs and it seems to be an infinite loop where the reference to the google maps was lost by the ViewControler. What works for me now is to set the width and height to |
@ngmiduc It seems that using this component is required for iOS: "The Google Maps Capacitor plugin ships with a web component that must be used to render the map in your application as it enables us to embed the native view more effectively on iOS" (from the readme) It looks like the component implements the style hack with the height. I currently managed to get it shown, but only for a few seconds, until I'm starting to fill up the map, and for some reason it disappears (that might be related to something else in my project though) |
I found out why the map disappeared. It seems to be related to dynamically adding a new element to the page where the map is created. Could someone explain why would that happen? Would the map binding break or how can this be avoided? |
@yoaquim, I am also facing the exact same problem. Did you find any solution? |
The spinlock issue I noted will propagate as null exceptions coming from the native plugin, which you would visually see as the Google Maps component not rendering at all. So regarding the styling fix, I believe people are having another issue that is unrelated. I hope that clears things up. |
For the angular gang, I had the same issue on the iphone 16 but not the iphone 16 pro (was working properly for w.e. reason). I found a simple solution, forcing the angular lifecycle to detect changes seems to fix my issue:
Let me know if this fix yours also EDIT: Making the map too high is apparently recreating the same issue -.- this is so frustrating to work with and I assume it will also be clunky from device to device so more testing is needed. 40vh-60vh is fine 70vh map refuse to appear... |
Bug Report
Plugin(s)
Google Maps
Capacitor Version
Platform(s)
iOS
Current Behavior
Empty box is appearing instead of Google Maps. Web works perfectly.
Expected Behavior
Show the map.
Code Reproduction
Sample webcomponent (apiKey deleted):
Other Technical Details
When I load the page on web it works fine, on iOS (physical device) I can see an empty box (with the red border I added).
Additional Context
There is no error at all, I can see the following in XCode:
The text was updated successfully, but these errors were encountered: