Get the city and country name with latitude and longitude (iOS) - ios

I use this function:
func getDataCity(tmpLat:Double,tmpLong:Double) {
let tmpCLGeocoder = CLGeocoder.init()
let tmpDataLoc = CLLocation.init(latitude: tmpLat, longitude: tmpLong)
tmpCLGeocoder.reverseGeocodeLocation(tmpDataLoc, completionHandler: {(placemarks,error) in
guard let tmpPlacemarks = placemarks else{
return
}
let placeMark = tmpPlacemarks[0] as CLPlacemark
// Country
guard let countryLocality = placeMark.country else{
return
}
// City
guard let cityLocality = placeMark.locality else{
return
}
print(countryLocality)
print(cityLocality)
})
}
When I use coordinates, for example, from Berlin/Germany
getDataCity(tmpLat: 52.52000659999999, tmpLong: 13.404953999999975)
the function works fine, it shows me the city and country. However I use coordinates from small cities or island, for example Djerba (island in Tunisia)
getDataCity(tmpLat: 33.8075978, tmpLong: 10.845146699999987)
the function doesn't print anything. Is there an explanation from Apple? What can I do about it?
To use the function in your own project, add CLLocationManagerDelegate to ViewController and don't forget to add the Privacy - Location When In Use Usage Description in your Info.plist

Apple's maps do not include a city for that location. Your code does recognize the country, but doesn't recognize a city there (in which case you abort).
If you open Apple Maps, you'll note that no cities are marked on that island, and searching for Houmt Arbah, Tunisia (the closest town) doesn't return a result in Apple Maps (it strangely returns Dahmani, which is a mainland town; I don't know why). It does know about Houmt Souq, but that's quite a ways from the given location.
The short and long of it is that Apple's map database doesn't know a lot about Tunisian geography. If you spend a little time looking around in Google Maps vs Apple Maps, you'll see that there are several parts of Tunisia that Apple Maps knows very little about. For example, if you look at Douz in satellite mode and then switch to map mode, you'll see that Apple's satellite imagery includes an entire village (Al-Qalah) that isn't mapped. And the street map of Douz itself (a town of 38k people), is, to put it bluntly, pathetic.
While Apple's maps have dramatically improved over the years, and in some areas they're now better than Google's maps, in most places Google tends to have far better information. If you need the best maps in arbitrary places, Google's maps are today the gold standard.

Related

Offline geocoding using MBTiles with vector tiles

I load an MBTiles Vector Tile data source of my country, using carto-mobile SDK
// Initialize base layer with a bundled styles
let baseLayer = NTCartoOnlineVectorTileLayer(style: NTCartoBaseMapStyle.CARTO_BASEMAP_STYLE_GRAY)
// Use the style for your own vector tile datasource (online, offline etc),
let tileDataSource = NTMBTilesTileDataSource(path: Bundle.main.path(forResource: "estonia_ntvt", ofType: "mbtiles"))
// Initialize offline layer & Grab vector tile layer from our base layer
let offlineLayer = NTVectorTileLayer(tileDataSource, baseLayer?.getTileDecoder())
mapView?.layers?.add(baseLayer)
mapView?.layers?.add(offlineLayer)
and is showing everything ok, so i have my map and all the features.
So now i want to search, for a POI or a street name.
I know that an MBTiles have all the information inside him, but how can i access to that info??
Is this posible?? if it is possible, how i do that??
The latest version (4.1.0) of CARTO mobile SDK has NTVectorTileSearchService using mbtiles. There is no user doc for it yet, but sample code can be found from AdvancedMap.Swift.
// init search service with your mbtiles
searchService = NTVectorTileSearchService(dataSource: baseSource, tileDecoder: baseLayer.getTileDecoder())
// prepare search request, set some conditions.
// This search is to find attractions within 500m from a route geometry
let request = NTSearchRequest()
request?.setProjection(contentView.baseSource.getProjection())
request?.setGeometry(geometry)
request?.setSearchRadius(500.0)
request?.setFilterExpression("class='attraction'")
// actual search
let results = contentView.searchService.findFeatures(request)
let count = Int((results?.getFeatureCount())!)
// go through found items
for i in 0..<count {
let item = results?.getFeature(Int32(i))!
if (item?.getGeometry() is NTPointGeometry) {
contentView.addPOI(feature: item!)
}
}
Note that this Search service is more usable for POI or street geometry search. Also be aware that same street is often duplicated in different tiles, and big polygons are often partial in tiling.
By geocoding we mean a bit different things - search for human-readable addresses or search for address given a location (reverse-geocode). MBTiles/Vector tiles does not have full data for this, it optimized for visual look. For example building or address points may have house number tag, but almost never have streets or city and country data in them, as it would be redundant and not needed for visual maps. Now for literal geocoding CARTO SDK has solution also: NTGeocodingService. You can use this online or offline, just for the offline case SDK has to download special different data packages per country (or city if you want). These data packages have full hierarchical address data, so real geocoding would work with them. So for complete offline data you would need to get two offline packages separately: mbtiles for maps and geocoding database. If you want offline routing also, then third dataset, as this also cannot be done properly from mbtiles/vector tiles alone.
This is very new feature, so you need to use pre-release version of SDK, but your feedback is very welcome.

Cannot apply style to GMSMapView

My code is as below:
/* Map */
mapView = GMSMapView()
mapView.delegate = self
mapView.mapType = .normal
do {
// Set the map style by passing the URL of the local file.
if let styleURL = Bundle.main.url(forResource: "styles", withExtension: "json") {
mapView.mapStyle = try GMSMapStyle(contentsOfFileURL: styleURL)
} else {
NSLog("Unable to find styles.json")
}
} catch {
NSLog("One or more of the map styles failed to load. \(error)")
}
I am following this tutorial on how to customize my Google map.
Above is my code for implementing the styles.json file. I added the file in my build bundle, and the code never throws an exception regarding not being able to parse my json file. It simply does not apply the style effects onto my map.
Any help would be appreciated. I am slowly dying inside!!!
Leaving an answer for anyone in the future that goes down my path:
Google map styling does not work for maps of South Korea. It even works in North Korea, but not South. South Korea's law prohibits map data from being exported to foreign datacenters.
source:
Yes , Korea does not support some features offered by Google Map due to national law. Google Map Korea can not be export map data for data centers abroad or including the ability to dynamically change the map image. Many South Korea Maps and services are limited to the domestic uses and Google is striving to make this a better service. For more details here's the original answer in Korean: original reply from Google Maps Korea

reverseGeocodeLocation returns placemark with some info in arabic and some in english

I have implemented reverseGeocodeLocation to get address from latitude and longitude. It's working fine.
I have change language to arabic like this: NSUserDefaults.standardUserDefaults().setObject(["ar"], forKey: "AppleLanguages")
Now, i'm calling reverseGeocodeLocation function and getting result in arabic language.
But, for some latitude-longitude it's returns some info in arabic and some in english language. For example:
Latitude: 21.1591493
Longitude: 72.6823397
City: Surat
Returns:
placemark.name = 394550
placemark.locality = Surat [English]
placemark.administrativeArea = غوجارات [Arabic]
placemark.country = الهند [Arabic]
So, Question is: why i am getting strange result for some locations?
What is workaround to get all info in arabic?
Note: I'm using Apple CLGeocoder's reverseGeocodeLocation method, NOT Google api. So don't confuse.
Answer for 1 question.
It may be possible that google don't have the name english language that's why its returning in arabic.
btw the default domain for the Geocoding Service is United States.
Answer for 2 question.
You can also set the Geocoding Service to return results biased to a particular region explicitly using the region parameter. This parameter takes a region code, specified as a IANA language region subtag.
you need to pass region code parameter in request.
In your case it will region=ar.
for more info go to documentation.

How to show places like "national parks" using google maps sdk in iOS?

I'm using xcode 6.4, Swift and iOS8. My goal is to show a map using the google maps (and places?) sdk. This map should contain all results google delivers when i search for "national park" on google maps.
What I already did is the following:
Create an API Key for iOS at google (places and maps sdk)
Show the map and the users current position
Now I'm struggling in showing the parks when the user opens the map. I already dived around in googles sdk documentation, and came to the conclusion that I'll need the Places SDK for that. But now I'm a bit lost, all I find are scenarios in which the user either has to choose between different "place types" or the app is calling information for one particular place, knowing its id.
After you have the key and every thing you can get places by calling the map api like this. the parameters (format strings are self explanatory) you have to tell the center location by giving latitude longitude (you can get it from users location if you want to show surrounding places). distance is the area for which you want to query for places. types this mention types of places so it canbe parks, restaurants etc.
When you have run the query you will get a list of places with details and the you have to draw using map annotations
var googleURLString NSString(format:#"https://maps.googleapis.com/maps/api/place/search/json?location=%f,%f&radius=%#&types=%#&sensor=true&key=%#",latitude, longitute, distance, type, apiKey ) as String
let googleURL = NSURL(string: googleURLString)
let locationData = NSData(contentsOfURL: googleURL!, options: nil, error: nil)
let dataToUse = NSJSONSerialization.JSONObjectWithData(locationData, options: NSJSONReadingOptions.AllowFragments, error:&error) as NSDictionary
let locations = dataToUse["results"]

How to route between two addresses using the new iOS 6.0 maps?

I'm using the iOS 6.0 SDK and I would like to route between two different addresses (not latitude and longitude) with Apple's new iOS 6.0 maps. I would like to show the indications too.
How can I do this?
I looked into do doing this last week and did not figure out a way to do it. It appears that you can give a destination, and you can sort of give it more than just coordinates, but it always assumes your starting position is the current location. That is limiting when you may be planning a trip while you are not currently at the starting location. (But perhaps I am just not seeing how it is done and I hope someone can correct me if that is true.)
A while back I looked into routing options for iOS 6 and gathered the results here...
How would you providing routing for directions between points on a map? What are the missing pieces?
You still may not be able to open up Apple Maps with the exact routing that you want, but perhaps you can draw the route with overlays and annotations on your own instance MKMapView. That may be the best you can do for now.
Below is the code that I used to route to a location and provide at least a label for the destination instead of leaving it to only coordinates. I found that simply giving the destination a label with the full address details would not work, so I just provide that one value.
if (flag != DirectionsFlag_PublicTransit && itemClass && [itemClass respondsToSelector:#selector(openMapsWithItems:launchOptions:)]) {
NSDictionary *address = #{ (NSString *)kABPersonAddressStreetKey : location.title };
MKPlacemark *destinationPlacemark = [[MKPlacemark alloc] initWithCoordinate:location.coordinate addressDictionary:address];
MKMapItem *destinationMapItem = [[MKMapItem alloc] initWithPlacemark:destinationPlacemark];
if (flag == DirectionsFlag_Driving) {
[destinationMapItem openInMapsWithLaunchOptions:#{MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeDriving}];
}
else if (flag == DirectionsFlag_Walking) {
[destinationMapItem openInMapsWithLaunchOptions:#{MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeWalking}];
}
}
This code specifically does not handle Public Transit directions since Apple Maps does not do that. I instead have it open up Google Maps with the URL that I was using previously which now opens up Safari for those directions. The flag is an enum value of Driving, Walking or Public Transit. The location is a model which contains various details including title and coordinates.

Resources