Traffic is not shown with custom tiles - iOS Google maps - ios

I have a map in my app, implemented with Google Maps iOS SDK. Traffic is perfectly works with Google tiles (normal, hybrid, satellite, etc.), but nothing happens when i set my custom tiles. What can be wrong?
Code for custom tiles (tiles itself loads correctly):
let urls: GMSTileURLConstructor = {(x, y, zoom) in
let url = "http://a.tile.openstreetmap.org/\(zoom)/\(x)/\(y).png"
return URL(string: url)
}
let layer = GMSURLTileLayer(urlConstructor: urls)
layer.map = mapView
Code for trigging traffic:
func toggleShowTraffic(status: Bool) {
mapView.isTrafficEnabled = status
}

Related

custom icon from url, not from assets - nativescript google maps ios

I try a lot but not success to find a way to show icon of marker from url.
addMarker(mark, index): void {
const marker = new Marker();
marker.position = Position.positionFromLatLng(mark.latitude, mark.longitude);
marker.icon = 'iconsdb.com/icons/preview/red/map-marker-2-xxl.png'; // default pin
this.mapView.addMarker(marker);
}
Using this for icons image from assets was working fine. now I have icons stored on cloud and I need to use them as per record.
Since loading image from assets works with an ImageSource, I believe you should be able to do a similar thing for images from URL. Also see documentation
The ImageSource has a 'fromUrl' you can call. So this should work for you (borrowing part of the code from your linked question)
let imgSrc = new ImageSource();
imgSrc.fromUrl("iconsdb.com/icons/preview/red/map-marker-2-xxl.png");
let image = new Image();
image.imageSource = imgSrc;
marker.icon = image;
You should probably cache the image so it won't be downloaded x times.

iOS Simulators doesnt render layer as real device

On my iOS app I use a Google Maps view with a GMSLayer, the transparency renders correctly on a real device but the background is white on Simulator, I can't make the screenshots for the App Store...
And this is the code I use :
// Implement GMSTileURLConstructor
// Returns a Tile based on the x,y,zoom coordinates, and the requested floor
let urls: GMSTileURLConstructor = {(x, y, zoom) in
let url = "http://wxs.ign.fr/[KEY]/geoportail/wmts?LAYER=TRANSPORTS.DRONES.RESTRICTIONS&FORMAT=image/png&SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&STYLE=normal&TILEMATRIXSET=PM&TILEMATRIX=" + String(zoom) + "&TILEROW="+String(y)+"&TILECOL="+String(x)
return URL(string: url)
}
// Create the GMSTileLayer
let layer = GMSURLTileLayer(urlConstructor: urls)
layer.zIndex = 0
layer.map = mapView
class TestTileLayer: GMSSyncTileLayer {
override func tileFor(x: UInt, y: UInt, zoom: UInt) -> UIImage {
let url = URL(string : "http://wxs.ign.fr/[KEY]/geoportail/wmts?LAYER=TRANSPORTS.DRONES.RESTRICTIONS&FORMAT=image/png&SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&STYLE=normal&TILEMATRIXSET=PM&TILEMATRIX=" + String(zoom) + "&TILEROW="+String(y)+"&TILECOL="+String(x))
return UIImage(data: try! Data(contentsOf: url!))!
}
}
I'm sure the image given by the URL uses transparency and I tried to manually change the white pixel to transparent but it doesn't change anything...
This is a simulator problem only it has been mentioned here.
However as #a.munzer suggested some work around you can take a screenshot from a real device and just edit it, shouldn't be that much of a problem.

MapView with Polyline or Annotation losing tile on zoom

I have a MKMapView in an IOS app using cached local tiles that works great. Can zoom, move around, etc...
When, however, I add either annotation or a polyline, it still works great until zoom gets to a certain zoom level, then the tiles under the annotations and polylines don't show up, but all others do fine.
zoomed out at the right level
Zoomed in one two many levels.
If I remove the annotations/lines, the map zooms in correctly and works great for the area the annotations/lines would have been in.
Any ideas?
I reduced this to the smallest test case. This runs fine until you zoom in, then any tiles under the polyline disappear. Zoom out and they re-appear.
import Foundation
import UIKit
import MapKit
class MyController: UIViewController, MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
var overlay:MKTileOverlay = MKTileOverlay(URLTemplate: "https://services.arcgisonline.com/ArcGIS/rest/services/USA_Topo_Maps/MapServer/tile/{z}/{y}/{x}.jpg");
override func viewDidLoad() {
mapView.delegate = self
mapView.showsUserLocation = true;
overlay.maximumZ = 15;
overlay.minimumZ = 12;
overlay.canReplaceMapContent = true
mapView.addOverlay(overlay)
var points: [CLLocationCoordinate2D] = [CLLocationCoordinate2D]()
points.append(CLLocationCoordinate2D(latitude: 40.7608, longitude: -111.8910));
points.append(CLLocationCoordinate2D(latitude: 40.8894, longitude: -111.8808));
var polyline = MKPolyline(coordinates: &points, count: points.count)
mapView.addOverlay(polyline)
let region = MKCoordinateRegion(center: points[0], span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05))
mapView.setRegion(region, animated: false)
}
func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
if overlay is MKPolyline {
var polylineRenderer = MKPolylineRenderer(overlay: overlay)
polylineRenderer.strokeColor = UIColor.blueColor()
polylineRenderer.lineWidth = 5
return polylineRenderer
} else if (overlay is MKTileOverlay) {
let renderr = MKTileOverlayRenderer(overlay: overlay)
return renderr
}
return nil
}
}
I see that it's been three months since you posed this question, but in case it's still of interest I'll share what I've found.
I've added the capability to download map tiles from Apple using an MKMapSnapshotter and store them into a set of tiles directories for use when you're out of cellular service areas, which works pretty well. The directories cover 3 to 6 different zoom levels depending on a user selection, with the tile images arranged in sub-directories under directories named after their zoom levels, per the iOS standard.
When displaying these using an MKTileOverlayRenderer, it switches appropriately among the images for zoom levels between the min and max zoom levels specified in the MKMapRectMake that I used to set up for the MKTileOverlay object.
The map displays all of the tiles appropriately at all of the specified zoom levels, repainting the tiles as sizes change. When the display goes above the max or below the min zoom levels, it continues to display the tiles from either the max or the min zoom levels for a while since it has no tile images for the new sizes. This works OK when there are no polylines, but the system redraws the squares that lie under polylines to resize the lines and when it does so it clears the tile images and looks for the tiles for the new zoom level. Since it doesn't have those tiles, those squares wind up empty on the tiles level, though squares not overlapped by polylines are not cleared and so retain the old images.
BTW, you may have already run into this but in case you haven't, you need to subclass MKTileOverlay so that you can set the location and size of the area mapped by the tiles.
Hope all of this helps explain things, even if it doesn't necessarily solve the problem of what you'll want to do about it.

How can I know what tiles will be rendered in Google Map?

So initially I want to render a color for each tile on Google Map according to air pollution level.
I have learned how to customize tile layer from Google's documentation about Tile Layer, with which mine looks similar to the following code:
class TestTileLayer: GMSSyncTileLayer {
override func tileForX(x: UInt, y: UInt, zoom: UInt) -> UIImage! {
// On every odd tile, render an image.
if (x % 2 == 0) {
return UIImage(named: "australia")
} else {
return kGMSTileLayerNoTile;
}
}
}
Basically, I want to avoid making one request to server for every tile. I would like to know which tiles will be rendered so I may make one request to get air pollution level for all of the tiles at once.
How do I know which tiles will be rendered in Google Maps, given user's current position, zoom level? Is there an API that does this already? I can't seem to find a direct one.
Thank you!

Any way to automate SFSafariViewController in UI tests?

Is there any way to automate SFSafariViewController? I like the Xcode 7 UI test feature, but it seems it does not support SFSafariViewController automation. Some of the UI flows I am testing require a web browser so the app uses SFSafariViewController to make it safer vs a web view.
If it's similar to launching extensions (currently broken with direct interactions), try tapping the screen at the point where the element you're looking for is:
Example of tapping an action sheet which launches an extension:
func tapElementInActionSheetByPosition(element: XCUIElement!) {
let tableSize = app.tables.elementBoundByIndex(0).frame.size
let elementFrame = element.frame
// get the frame of the cancel button, because it has a real origin point
let CancelY = app.buttons["Cancel"].frame.origin.y
// 8 is the standard apple margin between views
let yCoordinate = CancelY - 8.0 - tableSize.height + elementFrame.midY
// tap the button at its screen position since tapping a button in the extension picker directly is currently broken
app.coordinateWithNormalizedOffset(CGVectorMake(elementFrame.midX / tableSize.width, yCoordinate / app.frame.size.height)).tap()
}
Note: You must tap at the XCUIApplication query layer. Tapping the element by position doesn't work.
For now Xcode 9.3 has support for that, but it doesn't work properly because of annoying Xcode bug.
In test you can print app.webViews.buttons.debugDescription or app.webViews.textFields.debugDescription, and it prints correct information, but after tap or typeText you have crash.
To workaround you can parse debugDescription, extract coordinates and tap by coordinate. For text field you can insert text via "Paste" menu.
private func coordinate(forWebViewElement element: XCUIElement) -> XCUICoordinate? {
// parse description to find its frame
let descr = element.firstMatch.debugDescription
guard let rangeOpen = descr.range(of: "{{", options: [.backwards]),
let rangeClose = descr.range(of: "}}", options: [.backwards]) else {
return nil
}
let frameStr = String(descr[rangeOpen.lowerBound..<rangeClose.upperBound])
let rect = CGRectFromString(frameStr)
// get the center of rect
let center = CGVector(dx: rect.midX, dy: rect.midY)
let coordinate = XCUIApplication().coordinate(withNormalizedOffset: .zero).withOffset(center)
return coordinate
}
func tap(onWebViewElement element: XCUIElement) {
// xcode has bug, so we cannot directly access webViews XCUIElements
// as workaround we can check debugDesciption, find frame and tap by coordinate
let coord = coordinate(forWebViewElement: element)
coord?.tap()
}
Article about that: https://medium.com/#pilot34/work-with-sfsafariviewcontroller-or-wkwebview-in-xcode-ui-tests-8b14fd281a1f
Full code is here: https://gist.github.com/pilot34/09d692f74d4052670f3bae77dd745889

Resources