How to share longitude and latitude using UIActivityViewController
Here is a complete answer in Swift 3.1 which I put together after getting pieces of information from several places. I hope it helps someone.
@IBAction func didTapShareLocation(_ sender: UIButton) {
guard let carAddress = self.adressLabel.text, let lat = self.carCoordinates?.latitude, let lon = self.carCoordinates?.longitude else {
return
}
guard CLLocationCoordinate2DIsValid(self.carCoordinates!) else {
print("Location not valid!")
return
}
let carAddressString = "My car is at this address: \n\(carAddress)\n"
let vcardString = [
"BEGIN:VCARD",
"VERSION:3.0",
"N:;Shared Location;;;",
"FN:Shared Location",
"item1.URL;type=pref:http://maps.apple.com/?ll=\(lat),\(lon)",
"item1.X-ABLabel:map url",
"END:VCARD"
].joined(separator: "\n")
let directory = FileManager().urls(for: .cachesDirectory, in: .userDomainMask)
let path = directory.first!.path + "_vcard_for_location_sharing.loc.vcf"
do {
try vcardString.write(toFile: path, atomically: true, encoding: .ascii)
let url = NSURL(fileURLWithPath: path)
let objectsToShare = [url, carAddressString] as [Any]
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
activityVC.popoverPresentationController?.sourceView = sender
self.present(activityVC, animated: true, completion: nil)
}
catch {
print("problem saving vcard: \(error.localizedDescription)")
}
}
How to share user location from UIActivityViewController in Xcode
@IBAction func shareLocation(sender: UIBarButtonItem) {
// print(receivedDictionary)
let postalAdress = CNMutablePostalAddress()
postalAdress.street = receivedDictionary["Name"] as! String
postalAdress.city = receivedDictionary["City"] as! String
postalAdress.state = receivedDictionary["State"] as! String
postalAdress.postalCode = receivedDictionary["ZIP"] as! String
postalAdress.country = receivedDictionary["Country"] as! String
postalAdress.ISOCountryCode = receivedDictionary["CountryCode"] as! String
let streetName = receivedDictionary["Name"] as! String
let urlAddress = receivedDictionary["FormattedAddressLines"] as! [String]
// print(urlAddress)
let postalContact = CNLabeledValue(label: streetName, value: postalAdress)
let urlAddressContact = CNLabeledValue(label: "map url", value: "http://maps.apple.com/maps?address=\(urlAddress.description)")
let contact = CNMutableContact()
contact.contactType = .Organization
contact.organizationName = streetName
contact.departmentName = streetName
contact.postalAddresses = [postalContact]
contact.urlAddresses = [urlAddressContact]
// create path
let directory = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
let path = directory.first!.path!.stringByAppendingString("/\(streetName).loc.vcf")
// print(path)
do {
let contactData = try CNContactVCardSerialization.dataWithContacts([contact])
contactData.writeToFile(path, atomically: true)
let url = NSURL(fileURLWithPath: path)
// print(url)
let activityViewController = UIActivityViewController(activityItems: [url], applicationActivities: nil)
presentViewController(activityViewController, animated: true, completion: nil)
} catch {
print("CNContactVCardSerialization cannot save address")
}
}
Swift 5 - Sharing location using vCardURL
Forget all this stuff. The only thing you need is to share the Apple Maps URL with the coordinates... That's it! Tested on iOS 14 with UIKit and SwiftUI.
if let url = URL(string: "https://maps.apple.com?ll=\(latitude),\(longitude)") {
let activity = UIActivityViewController(activityItems: [url], applicationActivities: nil)
}
And then show the View Controller...
Converting address to apple maps link to share with others
You need to do 2 things
- Get current location
- use the lat, long to open the UIActivityController
To get the current location as lat, long you can use CLCoordinate
First add these to your info.plist you can modify the text as your will
<key>NSLocationAlwaysUsageDescription</key>
<string>Will you allow this app to always know your location?</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Do you allow this app to know your current location?</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Do you allow this app to know your current location?</string>
Now in your class create an object of CLLocationManager and implement it's delegate, since CLLocationManager is in CoreLocation we need to import it
import CoreLocation
Now create an object of locationManager
let locationManager = CLLocationManager()
Now in viewDidload or you may even create a separate method add the below code to setup locationManager
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
if CLLocationManager.locationServicesEnabled(){
locationManager.startUpdatingLocation()
}
Now implements its delegate and get the coordinate
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation :CLLocation = locations[0] as CLLocation
let coordinates = userLocation!.coordinate
print("locations = \(coordinates.latitude) \(coordinates.longitude)")
}
Now you can invoke the below function to open action Sheet
if let shareObject = self.activityItems(latitude: lat, longitude: long) {
//open UIActivityViewController
}
Use this method to construct vCard to share
func activityItems(latitude: Double, longitude: Double) -> [AnyObject]? {
var items = [AnyObject]()
let locationTitle = "Shared Location"
let URLString = "https://maps.apple.com?ll=\(latitude),\(longitude)"
if let url = NSURL(string: URLString) {
items.append(url)
}
let locationVCardString = [
"BEGIN:VCARD",
"VERSION:3.0",
"PRODID:-//Joseph Duffy//Blog Post Example//EN",
"N:;\(locationTitle);;;",
"FN:\(locationTitle)",
"item1.URL;type=pref:\(URLString)",
"item1.X-ABLabel:map url",
"END:VCARD"
].joinWithSeparator("\n")
guard let vCardData = locationVCardString.dataUsingEncoding(NSUTF8StringEncoding) else {
return nil
}
let vCardActivity = NSItemProvider(item: vCardData, typeIdentifier: kUTTypeVCard as String)
items.append(vCardActivity)
items.append(locationTitle)
return items
}
Reference link: https://josephduffy.co.uk/posts/ios-share-sheets-the-proper-way-locations
Related Topics
Uitableviewcell Textlabel Color Not Changing
Can the -Objc Flag Be Applied Selectively to Static Libraries
Fbsession.Activesession.Isopen Returns No Even Though the User Logged-In
Convert Nsattributedstring into Data for Storage
Avaudiosession .Defaulttospeaker Changes Mic Input
Remove Next/Previous Buttons (Inputaccessoryview) for Custom Keyboard in iOS8 Webview
Multiple Uicollectionview in One Controller
How to Update Data in Tableview Without the Delay Using Cloudkit When Creating New Records
How to Dynamically Add Rows to a Specific Uitableview Section
How to Get Touchid Information and Compare to a Fingerprint Database
Native Zlib Inflate/Deflate for Swift3 on iOS
Ios9: Alternative to Uidevice.Currentdevice().Setvalue(...) to Force Orientation
Get Each Line of Text in a Uilabel
Xcode iOS App Development Code Signing
Launchd_Sim Crashing: Could Not Create Temporary State Directory