How to get lat and long coordinates from address string - mapkit

I have a MKMapView that has a UISearchBar on the top, and I want the user to be able to type a address, and to find that address and drop a pin on it. What I don't know is how to turn the address string into longitude and latitude, so I can make a CLLocation object. Does anyone know how I can do this?

You may find your answer in this question.
iOS - MKMapView place annotation by using address instead of lat / long By User Romes.
NSString *location = #"some address, state, and zip";
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:location
completionHandler:^(NSArray* placemarks, NSError* error){
if (placemarks && placemarks.count > 0) {
CLPlacemark *topResult = [placemarks objectAtIndex:0];
MKPlacemark *placemark = [[MKPlacemark alloc] initWithPlacemark:topResult];
MKCoordinateRegion region = self.mapView.region;
region.center = placemark.region.center;
region.span.longitudeDelta /= 8.0;
region.span.latitudeDelta /= 8.0;
[self.mapView setRegion:region animated:YES];
[self.mapView addAnnotation:placemark];
}
}
];
A Very simple solution. But only applicable on iOS5.1 or later.

I used a similar approach like Vijay, but had to adjust one line of code. region.center = placemark.region.center didn't work for me. Maybe my code helps someone as well:
let location: String = "1 Infinite Loop, CA, USA"
let geocoder: CLGeocoder = CLGeocoder()
geocoder.geocodeAddressString(location,completionHandler: {(placemarks: [CLPlacemark]?, error: NSError?) -> Void in
if (placemarks?.count > 0) {
let topResult: CLPlacemark = (placemarks?[0])!
let placemark: MKPlacemark = MKPlacemark(placemark: topResult)
var region: MKCoordinateRegion = self.mapView.region
region.center.latitude = (placemark.location?.coordinate.latitude)!
region.center.longitude = (placemark.location?.coordinate.longitude)!
region.span = MKCoordinateSpanMake(0.5, 0.5)
self.mapView.setRegion(region, animated: true)
self.mapView.addAnnotation(placemark)
}
})

For swift2
var location: String = "some address, state, and zip"
var geocoder: CLGeocoder = CLGeocoder()
geocoder.geocodeAddressString(location,completionHandler: {(placemarks: [CLPlacemark]?, error: NSError?) -> Void in
if (placemarks?.count > 0) {
var topResult: CLPlacemark = (placemarks?[0])!
var placemark: MKPlacemark = MKPlacemark(placemark: topResult)
var region: MKCoordinateRegion = self.mapView.region
region.center = placemark.region.center
region.span.longitudeDelta /= 8.0
region.span.latitudeDelta /= 8.0
self.mapView.setRegion(region, animated: true)
self.mapView.addAnnotation(placemark)
}
})

func geoCodeUsingAddress(address: NSString) -> CLLocationCoordinate2D {
var latitude: Double = 0
var longitude: Double = 0
let addressstr : NSString = "http://maps.google.com/maps/api/geocode/json?sensor=false&address=\(address)" as NSString
let urlStr = addressstr.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
let searchURL: NSURL = NSURL(string: urlStr! as String)!
do {
let newdata = try Data(contentsOf: searchURL as URL)
if let responseDictionary = try JSONSerialization.jsonObject(with: newdata, options: []) as? NSDictionary {
print(responseDictionary)
let array = responseDictionary.object(forKey: "results") as! NSArray
let dic = array[0] as! NSDictionary
let locationDic = (dic.object(forKey: "geometry") as! NSDictionary).object(forKey: "location") as! NSDictionary
latitude = locationDic.object(forKey: "lat") as! Double
longitude = locationDic.object(forKey: "lng") as! Double
} catch {
}
}
var center = CLLocationCoordinate2D()
center.latitude = latitude
center.longitude = longitude
return center
}

Related

Draw route direction between user's current location to destination in iOS App? [duplicate]

This question already has answers here:
Drawing Route Between Two Places on GMSMapView in iOS
(12 answers)
Closed 5 years ago.
I want to draw route direction from current location to destination using google map direction API.
Try this code Swift 3.0-
var lat = #your latitude#
var lng = #your longitude#
var location = "your title"
let camera = GMSCameraPosition.camera(withLatitude: lat, longitude: lng, zoom: 9.0)
var mapView:GMSMapView = GMSMapView.map(withFrame: CGRect(origin: CGPoint(x: 0, y: 0), size: view.frame.size), camera: camera)
view.addSubview(mapView)
let markerStart = GMSMarker()
markerStart.position = CLLocationCoordinate2D(latitude: lat, longitude: lng)
markerStart.title = location
markerStart.snippet = location
markerStart.map = mapView
var latEnd = #your end latitude#
var lngEnd = #your end longitude#
let markerEnd = GMSMarker()
markerEnd.position = CLLocationCoordinate2D(latitude: latEnd, longitude: lngEnd)
markerEnd.title = location
markerEnd.snippet = location
markerEnd.map = mapView
let bounds = GMSCoordinateBounds(coordinate: markerStart.position, coordinate: markerEnd.position)
let boundUpdate = GMSCameraUpdate.fit(bounds, withPadding: 40)
mapView.animate(with: boundUpdate)
drawPath(currentLocation: markerStart.position, destinationLoc: markerEnd.position)
func drawPath(currentLocation:CLLocationCoordinate2D,destinationLoc:CLLocationCoordinate2D)
{
let origin = "\(currentLocation.latitude),\(currentLocation.longitude)"
let destination = "\(destinationLoc.latitude),\(destinationLoc.longitude)"
let url = "https://maps.googleapis.com/maps/api/directions/json?origin=\(origin)&destination=\(destination)&mode=driving"
Alamofire.request(url).responseJSON { response in
let json = JSON(data: response.data!)
let routes = json["routes"].arrayValue
for route in routes
{
let routeOverviewPolyline = route["overview_polyline"].dictionary
let points = routeOverviewPolyline?["points"]?.stringValue
let path = GMSPath.init(fromEncodedPath: points!)
let polyline = GMSPolyline.init(path: path)
polyline.strokeColor = UIColor.red
polyline.strokeWidth = 3
polyline.map = self.mapView
}
}
}
Objective C
double lat = #your latitude#;
double lng = #your longitude#;
double latEnd = #your end latitude#;
double lngEnd = #your end longitude#;
NSString *directionsUrlString = [NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/directions/json?&origin=%f,%f&destination=%f,%f&mode=driving", lat, lng, latEnd, lngEnd];
NSURL *directionsUrl = [NSURL URLWithString:directionsUrlString];
NSURLSessionDataTask *mapTask = [[NSURLSession sharedSession] dataTaskWithURL:directionsUrl completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error)
{
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
if(error)
{
if(completionHandler)
completionHandler(nil);
return;
}
NSArray *routesArray = [json objectForKey:#"routes"];
GMSPolyline *polyline = nil;
if ([routesArray count] > 0)
{
NSDictionary *routeDict = [routesArray objectAtIndex:0];
NSDictionary *routeOverviewPolyline = [routeDict objectForKey:#"overview_polyline"];
NSString *points = [routeOverviewPolyline objectForKey:#"points"];
GMSPath *path = [GMSPath pathFromEncodedPath:points];
polyline = [GMSPolyline polylineWithPath:path];
}
// run completionHandler on main thread
dispatch_sync(dispatch_get_main_queue(), ^{
if(completionHandler)
completionHandler(polyline);
});
}];
[mapTask resume];
}

How can I use NSArray and NSDictionary with this SQL data?

Couldn't parse JSON data.
Could not cast value of type '__NSArrayI' (0x10f02fc08) to 'NSMutableArray' (0x10f02fcd0).
JSON data here and code here;
echo json_encode($resultArray);
And here is my trial code;
func parseJSON() {
var jsonResult: NSMutableArray = NSMutableArray()
do{
jsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSMutableArray
} catch let error as NSError {
print(error)
}
var jsonElement: NSDictionary = NSDictionary()
let locations: NSMutableArray = NSMutableArray()
for i in 1...jsonResult.count
{
jsonElement = jsonResult[i-1] as! NSDictionary
let location = LocationModel()
if let name = jsonElement["Name"] as? String,
let address = jsonElement["Address"] as? String,
let latitude = jsonElement["Latitude"] as? String,
let longitude = jsonElement["Longitude"] as? String
{
location.name = name
location.address = address
location.latitude = latitude
location.longitude = longitude
}
locations.add(location)
}
DispatchQueue.main.async(execute: { () -> Void in
self.delegate.itemsDownloaded(items: locations)
})
}
NOTE: IT WILL FIX THIS
instead of:
var jsonResult: NSMutableArray = NSMutableArray()
do this:
var jsonResult: NSArray = NSArray()
and instead of:
jsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSMutableArray
do this:
jsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray
full code:
func parseJSON() {
var jsonResult: NSArray = NSArray()
do{
jsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray
} catch let error as NSError {
print(error)
}
var jsonElement: NSDictionary = NSDictionary()
let locations: NSMutableArray = NSMutableArray()
for i in 1...jsonResult.count
{
jsonElement = jsonResult[i-1] as! NSDictionary
let location = LocationModel()
if let name = jsonElement["Name"] as? String,
let address = jsonElement["Address"] as? String,
let latitude = jsonElement["Latitude"] as? String,
let longitude = jsonElement["Longitude"] as? String
{
location.name = name
location.address = address
location.latitude = latitude
location.longitude = longitude
}
locations.add(location)
}
DispatchQueue.main.async(execute: { () -> Void in
self.delegate.itemsDownloaded(items: locations)
})
}
The issue is that JSONSerialization is returning a non-mutable array, and you can't just cast a NSArray to a NSMutableArray. Instead, just declare it to be NSArray:
func parseJSON() {
var jsonResult: NSArray
do {
jsonResult = try JSONSerialization.jsonObject(with: data as Data) as! NSArray
} catch let error as NSError {
print(error)
return
}
...
}
Or, alternatively, use Swift's native collection types rather than falling back on old NSArray and NSDictionary types:
func parseJSON() {
var jsonResult: [[String: Any]] // this is an array of dictionaries
do {
jsonResult = try JSONSerialization.jsonObject(with: data as Data) as! [[String: Any]]
} catch let error as NSError {
print(error)
return
}
for jsonElement in jsonResult {
if let name = jsonElement["Name"] as? String,
let address = jsonElement["Address"] as? String,
let latitude = jsonElement["Latitude"] as? String,
let longitude = jsonElement["Longitude"] as? String
{
let location = LocationModel()
location.name = name
location.address = address
location.latitude = latitude
location.longitude = longitude
locations.add(location) // or, if you defined `locations` to be a Swift array, `locations.append(location)`
}
}
...
}
(Personally, I'd probably also define the data to be a Data rather than a NSData and define locations to be [LocationModel] rather than NSMutableArray.)

How to detect Marker's location after draggable

I'm trying to get Marker's location after draggable in Google Map. Current is I can add Marker in Google Map according to current location of device in snippet. Now, what I want is try to get Marker's location based on draggable position.
placemark = [placemarks lastObject];
CLLocationCoordinate2D position = { [latitude doubleValue], [longitude doubleValue] };
mymarker = [GMSMarker markerWithPosition:position];
mymarker.title = [NSString stringWithFormat:#"%#", placemark.thoroughfare];
mymarker.appearAnimation = YES;
mymarker.flat = YES;
mymarker.snippet = [NSString stringWithFormat:#"%# %#, %# %#", placemark.locality, placemark.administrativeArea, placemark.postalCode, placemark.country];
mymarker.map = _mapView;
mymarker.draggable = true;
Give this a try
-(void)mapView:(GMSMapView *)mapView didEndDraggingMarker:(GMSMarker *)marker{
NSLog(#"New location of marker: Lat: %f, Long: %f", marker.position.latitude, marker.position.longitude);
}

IOS::How to get the MPMediaquery Songsquery Artwork

I'm using this code for getting the Artwork, but it's not workout for me. What's the wrong in this code.Suggest me.
Thanks.
MPMediaQuery *mySongsQuery = [MPMediaQuery songsQuery];
NSArray *SongsList = [mySongsQuery collections];
for (MPMediaItemCollection *SongsArt in SongsList) {
NSArray *songs = [SongsArt items];
for (MPMediaItem *song in songs) {
if ([(MPMediaItem*)item valueForProperty:MPMediaItemPropertyAssetURL] != nil) {
CGSize artworkImageViewSize = CGSizeMake(40, 40);
MPMediaItemArtwork *artwork = [song valueForProperty:MPMediaItemPropertyArtwork];
UIImage * image = [artwork imageWithSize:artworkImageViewSize];
if (image!= nil)
{
imgv_songImageView.image = image;
}
else
{
imgv_songImageView.image = [UIImage imageNamed:#"musicD-jpeg.png"];
}
}
}
I assume you just want to loop through all songs in the music library so I don't see a need for collections:
MPMediaQuery *mySongsQuery = [MPMediaQuery songsQuery];
for (MPMediaItem *item in mySongsQuery.items) {
if (![[item valueForProperty:MPMediaItemPropertyIsCloudItem]boolValue]) {
CGSize artworkImageViewSize = CGSizeMake(40, 40);
MPMediaItemArtwork *artwork = [song valueForProperty:MPMediaItemPropertyArtwork];
UIImage *image = [artwork imageWithSize:artworkImageViewSize];
if (image) {
imgv_songImageView.image = image;
} else {
imgv_songImageView.image = [UIImage imageNamed:#"musicD-jpeg.png"];
}
}
}
I'm not sure why you want to check for the Asset URL but I've left it in.
Here i am posting the code to get the tracks and sorting them alphabetically. Its written in swift3.
/// Get all the songs in the device and display in the tableview
///
func getAllSongs() {
let query: MPMediaQuery = MPMediaQuery.songs()
let allSongs = query.items
allSongItems?.removeAll()
guard allSongs != nil else {
return
}
var index = 0
for item in allSongs! {
let pathURL: URL? = item.value(forProperty: MPMediaItemPropertyAssetURL) as? URL
if pathURL == nil {
print("#Warning!!! Track : \(item) is not playable.")
} else {
let trackInfo = SongItem()
trackInfo.index = index
trackInfo.mediaItem = item
let title = item.value(forProperty: MPMediaItemPropertyTitle) as? String ?? "<Unknown>"
let artistName = item.value(forProperty: MPMediaItemPropertyArtist) as? String ?? "<Unknown>"
trackInfo.songName = title
trackInfo.artistName = artistName
trackInfo.isSelected = false
trackInfo.songURL = item.value(forProperty: MPMediaItemPropertyAssetURL) as? URL
allSongItems?.append(trackInfo)
index += 1
}
}
// Sort the songs alphabetically
let sortedArray: [SongItem]? = allSongItems?.sorted {
$0.songName!.localizedCompare($1.songName!) == .orderedAscending
}
allSongItems?.removeAll()
if let arr = sortedArray {
allSongItems?.append(contentsOf: arr)
}
}

How can I plot addresses in Swift, converting address to longitude and latitude coordinates?

In Objective-C this code works fine to plot an address and it finds the longitude and latitude coordinates:
NSString *address = #"1 Infinite Loop, CA, USA";
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:address
completionHandler:^(NSArray* placemarks, NSError* error){
// Check for returned placemarks
if (placemarks && placemarks.count > 0) {
CLPlacemark *topResult = [placemarks objectAtIndex:0];
// Create a MLPlacemark and add it to the map view
MKPlacemark *placemark = [[MKPlacemark alloc] initWithPlacemark:topResult];
[self.mapView addAnnotation:placemark];
[placemark release];
}
[geocoder release];
}];
I have been searching for days on how to do this with Swift?! Could anyone point me in the right direction? Could you explain if a user needs an internet connection for this to work. Sorry if these questions sounds a bit basic, but I am quite new to this and learning every day.
I understand that I have to use this code, but cannot find a way to implement it
func geocodeAddressString(_ addressString: String!,
completionHandler completionHandler: CLGeocodeCompletionHandler!)
XCode 9 & Swift 3:
import CoreLocation
let address = "1 Infinite Loop, CA, USA"
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(address, completionHandler: {(placemarks, error) -> Void in
if((error) != nil){
print("Error", error)
}
if let placemark = placemarks?.first {
let coordinates:CLLocationCoordinate2D = placemark.location!.coordinate
}
})
Try something like
var address = "1 Infinite Loop, CA, USA"
var geocoder = CLGeocoder()
geocoder.geocodeAddressString(address, {(placemarks: [AnyObject]!, error: NSError!) -> Void in
if let placemark = placemarks?[0] as? CLPlacemark {
self.mapView.addAnnotation(MKPlacemark(placemark: placemark))
}
})
var address = "1 Infinite Loop, CA, USA"
var geocoder = CLGeocoder()
geocoder.geocodeAddressString(address) {
if let placemarks = $0 {
println(placemarks)
} else {
println($1)
}
}