Load KML marks on map using Google Maps SDK - ios

I'm working on a iOS project with Swift on Xcode, and i need to show a map with some routes drawn on it. I created the map view using Google Maps SDK for iOS and it works well. I use KML.swift to parse the KML file.
The problem is that i want to load the routes for the map from a KML and i don't see how to do it. On Android, the SDK allows you to add a layer from a KML and add that layer to the map easy (more or less), but i can't find the way to do something like that on the iOS SDK.
Is there any way to do it?
Thanks in advance.

You can now do so with GoogleMapsUtils. The KML file can be parsed using GMUKMLParser and rendered with GMSMapView.
Create instances of GMSMapView and GMUKMLParser
let mapView: GMSMapView!
let kmlParser: GMUKMLParser!
func renderKml() {
guard let path = Bundle.main.path(forResource: "uae_map", ofType: "kml") else {
print("Invalid path")
return
}
let url = URL(fileURLWithPath: path)
kmlParser = GMUKMLParser(url: url)
kmlParser.parse()
let renderer = GMUGeometryRenderer(
map: mapView,
geometries: kmlParser.placemarks,
styles: kmlParser.styles,
styleMaps: kmlParser.styleMaps
)
renderer.render()
}

Related

Unable to load custom tile on google map using iOS swift

I'm trying to use custom tiles as overlay for google maps.
"https://tile.example.com/hot/{z}/{x}/{y}.png"
I used "GMSTileURLConstructor", but unable to load map on mobile app. I cannot seem to find anything online. Thanks in advance.
I used the following lines.
class ViewController: UIViewController, GMSMapViewDelegate{
let urls: GMSTileURLConstructor = {z,x,y in
let url = "https://tile.example.com/hot/{z}/{x}/{y}.png"
print(url)
return URL(string: url)
}

SCNParticleSystem load from document Directory

I am trying load SCNParticleSystem from download bundle which i am not able to load.
Path for the resource.
file:///var/mobile/Containers/Data/Application/A91E9970-CDE1-43D8-B822-4B61EFC6149B/Documents/so/solarsystem.bundle/Contents/Resources/
let objScene = SCNParticleSystem(named: "stars", inDirectory: directory)
This object is nil.
This is a legitimate problem since SceneKit does not provide an out-of-the-box solution for initializing particle systems from files that are outside of the main bundle (the only init method SCNParticleSystem.init(named:inDirectory:) implies that SCNParticleSystem.scnp files are in the main bundle).
Luckily for us .scnp files are just encoded/archived SCNParticleSystem instances that we can easily decode/unarchive using NSKeyedUnarchiver:
extension SCNParticleSystem {
static func make(fromFileAt url: URL) -> SCNParticleSystem? {
guard let data = try? Data(contentsOf: url),
let object = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data),
let system = object as? SCNParticleSystem else { return nil }
return system
}
}
If you do not need to support iOS 9 and iOS 10 you can use NSKeyedUnarchiver.unarchivedObject(ofClass: SCNParticleSystem.self, from: data) instead of NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(_:) and type casting, which was introduced in iOS 11.0.
Another issue that you're most likely to encounter is missing particle images. That is because by default SceneKit will look for them in the main bundle. As of current versions of iOS (which is iOS 12) and Xcode (Xcode 10) particle images in .scnp files (particleImage property) are String values which are texture filenames in the main bundle (that might change, but probably won't, however there's not much else we could use).
So my suggestion is to take that filename and look for the texture file with the same name in the same directory where the .scnp file is:
extension SCNParticleSystem {
static func make(fromFileAt url: URL) -> SCNParticleSystem? {
guard let data = try? Data(contentsOf: url),
let object = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data),
let system = object as? SCNParticleSystem else { return nil }
if let particleImageName = system.particleImage as? String {
let particleImageURL = url
.deletingLastPathComponent()
.appendingPathComponent(particleImageName)
if FileManager.default.fileExists(atPath: particleImageURL.path) {
system.particleImage = particleImageURL
}
}
return system
}
}
You can just set the URL of the image file and SceneKit will handle it from there.
As a little side-note, the recommended directory for downloadable content is Application Support directory, not Documents.
Application Support: Use this directory to store all app data files except those associated with the user’s documents. For example, you might use this directory to store app-created data files, configuration files, templates, or other fixed or modifiable resources that are managed by the app. An app might use this directory to store a modifiable copy of resources contained initially in the app’s bundle. A game might use this directory to store new levels purchased by the user and downloaded from a server.
(from File System Basics)
Don't have enough reps to add the comment so adding it as the answer.
The answer by Lësha Turkowski works for sure but was had issues with loading the particle images using only NSURL.
All particles were appearing square which meant,
If the value is nil (the default), SceneKit renders each particle as a
small white square (colorized by the particleColor property).
SCNParticleSystem particleImage
In the documentation it says You may specify an image using an
NSImage (in macOS) or UIImage (in iOS) instance, or an NSString or
NSURL instance containing the path or URL to an image file.
Instead of using the NSURL, ended up using the UIImage and it loaded up fine.
extension SCNParticleSystem {
static func make(fromFileAt url: URL) -> SCNParticleSystem? {
guard let data = try? Data(contentsOf: url),
let object = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data),
let system = object as? SCNParticleSystem else { return nil }
if let particleImageName = system.particleImage as? String {
let particleImageURL = url
.deletingLastPathComponent()
.appendingPathComponent(particleImageName)
if FileManager.default.fileExists(atPath: particleImageURL.path) {
// load up the NSURL contents in UIImage
let particleUIImage = UIImage(contentsOfFile: particleImageURL.path)
system.particleImage = particleUIImage
}
}
return system
}
}
I found out, that sometimes when dragging a SCNParticleSystem file into your project (probably form a different project) a silent error can happen due to some bugs in Xcode. As a result you can't get a reference to an instance of your SCNParticleSystem.
Solution: Check your BuildSettings in your target. The SCNPaticleSystem AND the associated ImageFile should be listed there and then you should get it right. (see screenShot below)

Integrate KML on offline Google Map iOS

I want to create a kml file programmatically in iOS Swift4. I surfed a lot regarding offline GoogleMaps & saving data in kml file, but I haven't found any relevant material regarding this. In short, I just want to store some POI in kml & display it in offline Googlemap!!
KML is an XML document scheme. You can write it in any way you see fit. Use a dedicated XML encoder or brute force using strings.
The full spec is documented at https://developers.google.com/kml/documentation/kmlreference
You may find examining existing KML files useful to show example structures.
Here is an example brute force encoder to encode a set of labeled placemarks…
Raw strings will need to be XML escaped before writing to file.
You may find Google Toolbox for Mac useful here.
class KMLWriter {
func createKMLFormat(_ logs:[DDBLogEntry])->String {
var kml = preamble()
for log in logs {
kml += placemarkForLog(log)
}
terminate(&kml)
return kml
}
func placemarkForLog(_ log:DDBLogEntry)->String {
let name = log.userContent ?? "empty"
let time = log.dateCreated ?? Date()
let timeStamp = Date.UTCDateFormatter.string(from: time)
return "<Placemark>\n<name>\(name)</name>\n<Point><coordinates>\(log.longitude ?? 0),\(log.latitude ?? 0),\(log.elevation ?? 0)</coordinates></Point>\n<TimeStamp><when>\(timeStamp)</when></TimeStamp>\n</Placemark>\n"
}
func preamble()->String {
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n<Document>\n"
}
func terminate(_ kml:inout String) {
kml += "</Document>\n</kml>\n"
}
}

How to change the colors of MapKit Swift

In my app i used mapKit, the problem is the map should be in specific color like this :
i try to change the type of map, but nothing match with this picture, so i thought if i can change the color of the mapKit.
anyone faced like this problem ?
any help please ?
thanks
Try using the Mapbox API. I currently have the same problem and this library has come in-handy.
You can apply a mask by adding an Overlay betwen the map and Label/Road:
let path = NSBundle.mainBundle().pathForResource("overlay", ofType: "png")
let fileURL = NSURL(fileURLWithPath: path!)
self.overlay = MKTileOverlay(URLTemplate: fileURL.absoluteString)
self.overlay!.canReplaceMapContent = false
self.mapView.addOverlay(self.overlay!, level: MKOverlayLevel.AboveRoads)

Any api in iOS6 to get static map image of a gps location

I want a static map image from a location. I have the latitude and longitude of that location. Is there any api in iOS 6 to get the apple map static image of a gps location.
MKMapView has two properties to achieve this functionality: scrollEnabled and zoomEnabled. Set both to NO and you'll have a non-scrolling and non-zooming (thus static) map image.
I believe Google Static Maps is what you're looking for. Send it the parameters of location and it will return the image you want.
On iOS 7+ Apple MapKit allows displaying static images of a map using MKMapSnapshotter class. It is detailed in Creating a Snapshot of a Map section of MapKit documentation:
// Takes a snapshot and calls back with the generated UIImage
static func takeSnapshot(mapView: MKMapView, withCallback: (UIImage?, NSError?) -> ()) {
let options = MKMapSnapshotOptions()
options.region = mapView.region
options.size = mapView.frame.size
options.scale = UIScreen.mainScreen().scale
let snapshotter = MKMapSnapshotter(options: options)
snapshotter.startWithCompletionHandler() { snapshot, error in
guard snapshot != nil else {
withCallback(nil, error)
return
}
withCallback(snapshot!.image, nil)
}
}
just use MKMapView to display map ,you will have to use MapKit.framework for that
this link will help you...
https://github.com/kviksilver/MKMapview-annotation-grouping
Happy Coding!!!

Resources