Trouble storing user location in Swift3 - ios

What I want to do is pass the user location to complete my JSON URL. But the way I do it, it prints "optional(coordinate)" and I just want the coordinate wihtout the optional. I tried to erase ? but it would mark error at the moment to build.
I tried to get the user location in the func locationManager and I try to use them in the func loadGas. Any help could be of use.
import UIKit
import MapKit
import CoreLocation
class MapViewController: UIViewController,MKMapViewDelegate, CLLocationManagerDelegate,UICollectionViewDelegate, UICollectionViewDataSource {
let manager = CLLocationManager()
public let sMAGNA = "magna"
public let sPREMIUM = "premium"
public let sDIESEL = "diesel"
public let MIN_TIME: CLong = 400
private let MIN_DISTANCE: Float = 1000
private var ubicaciones_selected: [Ubicacion] = []
private var ubicaciones_magna: [Ubicacion] = []
private var ubicaciones_premium: [Ubicacion] = []
private var ubicaciones_diesel: [Ubicacion] = []
private let REQUEST_LOCATION = 1
private var latlon: String = ""
private var mType: String = "magna"
var ubicaciones:[Ubicacion] = []
var Ubigaspin = MKPointAnnotation()
#IBAction func MapType(_ sender: Any) {
if mapa.mapType == MKMapType.standard{
mapa.mapType = MKMapType.satellite
} else { mapa.mapType = MKMapType.standard
}
}
#IBOutlet var mapa: MKMapView!
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations[0]
let span:MKCoordinateSpan = MKCoordinateSpanMake(0.01, 0.01)
let myLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
print(myLocation)
let region:MKCoordinateRegion = MKCoordinateRegionMake(myLocation, span)
mapa.setRegion(region, animated: true)
self.mapa.showsUserLocation = true
manager.stopUpdatingLocation()
}
override func viewDidLoad() {
super.viewDidLoad()
//con esto obtendremos la ubicacion del usuario
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
mapa.showsUserLocation = true
manager.startUpdatingLocation()
//se cargan los pines y las gasolinas
loadGas(tipo: mType)
}
func loadGas(tipo:String){
mType = tipo
var ubicaciones:[Ubicacion] = []
switch tipo {
case sMAGNA:
ubicaciones = ubicaciones_magna
case sPREMIUM:
ubicaciones = ubicaciones_premium
case sDIESEL:
ubicaciones = ubicaciones_diesel
default:
ubicaciones = ubicaciones_magna
}
if ubicaciones.count == 0 {
let lat = String(describing: manager.location?.coordinate.latitude)
let long = String(describing: manager.location?.coordinate.longitude)
let url = URL(string: "http://192.241.214.56/api/ubicacion/?format=json&sub="+lat+","+long)
print (url)
// let url = URL(string: "http://192.241.214.56/api/ubicacion/?format=json&sub=29.08919%2C-110.96133")
// let url = URL(string: "http://192.241.214.56/api/"+tipo+"/?format=json")
URLSession.shared.dataTask(with: url!, completionHandler: {
(data, response, error) in
if(error != nil){
print("error")
}else{
do{
let ubicaciones_json = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [[String : AnyObject]]
for ubicacion in ubicaciones_json{
let nombre:String = ubicacion["nombre"] as! String
let direccion:String = ubicacion["direccion"] as! String
let precio_magna:Float = ubicacion["precio_magna"] as! Float
let precio_premium:Float = ubicacion["precio_premium"] as! Float
let precio_diesel:Float = ubicacion["precio_diesel"] as! Float
let ubicacion:String = ubicacion["ubicacion"] as! String
let p = Ubicacion()
p.ubicacion = ubicacion
p.setLatLng()
p.nombre = nombre
p.direccion = direccion
p.precio_magna = precio_magna
p.precio_premium = precio_premium
p.precio_diesel = precio_diesel
ubicaciones.append(p)
}
self.ubicaciones = ubicaciones
OperationQueue.main.addOperation({
self.updatePins(ubicaciones: ubicaciones)
})
}catch let error as NSError{
print(error)
}
}
}).resume()
}else{
self.ubicaciones = ubicaciones
self.updatePins(ubicaciones: ubicaciones)
}
}

Instead of
let lat = String(describing: manager.location?.coordinate.latitude)
you should do something like this:
guard let location = manager.location else {
return
}
let lat = String(format: "%f", location.coordinate.latitude)

Related

Making independent class with functionality and make usage of it in InterfaceController class

I have tried to make a separate class for the location functionality (separate swift file in the Watchkit Exension folder) and I want to use the location instance of that class in the InterfaceController class to track the location of the user. But, xcode gets stuck and I also cannot deploy and test the application. I do not know what the reason is.
Here is the location code and the InterfaceController class:
The whole project is here: https://filebin.net/s40xlqzeukfwc39w
I hope you can help me out since I am still a beginner in terms of Swift and WatchKit. Thank you very much.
import WatchKit
import Foundation
import CoreLocation
class LocationOutside{
var locationManager: CLLocationManager = CLLocationManager()
init(){
locationManager.requestWhenInUseAuthorization()
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters
locationManager.delegate = (self as! CLLocationManagerDelegate)
locationManager.requestLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let currentLoc = locations[0]
let lat = currentLoc.coordinate.latitude
let long = currentLoc.coordinate.longitude
print(lat)
print(long)
}
func locationManager(_manager: CLLocationManager,didFailWithError error: Error){
if let locationErr = error as? CLError{
switch locationErr{
case CLError.locationUnknown:
print("unknown location")
case CLError.denied:
print("denied")
default:
print("another type of location error")
}
}else{
print("other error: ", error.localizedDescription)
}
}
}
import WatchKit
import Foundation
import CoreLocation
import HealthKit
import AVFoundation
import CoreMotion
let hrType:HKQuantityType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRate)!
// Date will be constructed in database --> server side
class InterfaceController: WKInterfaceController,AVAudioRecorderDelegate{
var saveUrl: URL?
var outDoorLocation = LocationOutside.init()
// to conduct permission to retrieve location data
var locationManager: CLLocationManager = CLLocationManager()
// Outlets for testing
#IBOutlet weak var button: WKInterfaceButton!
#IBOutlet weak var furtherSigLabels: WKInterfaceLabel!
var recordingSession : AVAudioSession!
var audioRecorder : AVAudioRecorder!
var settings = [String : Any]()
// distinguish start recording heartbeat
var isRecording = false
//For workout session
let healthStore = HKHealthStore()
var session: HKWorkoutSession?
var currentQuery: HKQuery?
var filename: String?
let motionManager = CMMotionManager()
let queue = OperationQueue()
var gravityStr = ""
var userAccelerStr = ""
var rotationRateStr = ""
var attitudeStr = ""
var movement = ""
var manualLat: Double = 0.0
var manualLong: Double = 0.0
var heartRateVal: Double = 0.0
var prev_grav_z: Double = 0.0
var prev_acc_z: Double = 0.0
var grav_x:Double = 0.0
var grav_y:Double = 0.0
var grav_z:Double = 0.0
var acc_x:Double = 0.0
var acc_y:Double = 0.0
var acc_z:Double = 0.0
var sendOrNot:Bool = false
override func awake(withContext context: Any?) {
super.awake(withContext: context)
/**
locationManager.requestWhenInUseAuthorization()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.delegate = self
locationManager.requestLocation()
*/
// managing authorization
let healthService:HealthDataService = HealthDataService()
healthService.authorizeHealthKitAccess { (success, error) in
if success {
print("HealthKit authorization received.")
} else {
print("HealthKit authorization denied!")
if error != nil {
print("\(String(describing: error))")
}
}
}
motionManager.deviceMotionUpdateInterval = 0.5
}
/**
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let currentLoc = locations[0]
let lat = currentLoc.coordinate.latitude
let long = currentLoc.coordinate.longitude
manualLat = lat
manualLong = long
/**
let request = NSMutableURLRequest(url: NSURL(string: "http://147.46.242.219/addgps.php")! as URL)
request.httpMethod = "POST"
let postString = "a=\(lat)&b=\(long)"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if error != nil {
print("error=\(error)")
return
}
print("response = \(response)")
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("responseString = \(responseString)")
}
task.resume()
*/
}
*/
/**
func locationManager(_: CLLocationManager, didFailWithError error: Error) {
let err = CLError.Code(rawValue: (error as NSError).code)!
switch err {
case .locationUnknown:
break
default:
print(err)
}
}
*/
override func willActivate() {
// This method is called when watch view controller is about to be visible to user
super.willActivate()
motionManager.startDeviceMotionUpdates(to: queue) { (deviceMotion: CMDeviceMotion?, error: Error?) in
if error != nil {
print("Encountered error: \(error!)")
}
if deviceMotion != nil {
self.grav_x = (deviceMotion?.gravity.x)!
self.grav_y = (deviceMotion?.gravity.y)!
self.grav_z = (deviceMotion?.gravity.z)!
self.gravityStr = String(format: "grav_x: %.2f, grav_y: %.2f, grav_z: %.2f" ,
self.grav_x,
self.grav_y,
self.grav_z)
if self.prev_grav_z == 0.0 {
self.prev_grav_z = self.grav_z
self.sendOrNot = true
}
else{
if (self.grav_z - self.prev_grav_z) <= -0.25{
//print("Gravity: ",self.grav_z, self.prev_grav_z)
self.sendOrNot = true
}
else{
self.sendOrNot = false
}
self.prev_grav_z = self.grav_z
}
//self.sendData(x: self.gravityStr)
// print(self.gravityStr)
self.acc_x = (deviceMotion?.userAcceleration.x)!
self.acc_y = (deviceMotion?.userAcceleration.y)!
self.acc_z = (deviceMotion?.userAcceleration.z)!
self.userAccelerStr = String(format: "acc_x: %.2f, acc_y: %.2f, acc_z: %.2f" ,
self.acc_x,
self.acc_y,
self.acc_z)
if (self.acc_z - self.prev_acc_z) <= -0.2{
//print("Accelero_z: ",self.acc_z, self.prev_acc_z)
self.sendOrNot = true
}
else{
self.sendOrNot = false
}
self.prev_acc_z = self.acc_z
self.rotationRateStr = String(format: "rota_x: %.2f, rota_y: %.2f, rota_z: %.2f" ,
(deviceMotion?.rotationRate.x)!,
(deviceMotion?.rotationRate.y)!,
(deviceMotion?.rotationRate.z)!)
//self.sendData(x: self.rotationRateStr)
//print(self.rotationRateStr)
self.attitudeStr = String(format: "atti_roll: %.1f, atti_pitch: %.1f, atti_yaw: %.1f" ,
(deviceMotion?.attitude.roll)!,
(deviceMotion?.attitude.pitch)!,
(deviceMotion?.attitude.yaw)!)
//self.sendData(x: self.attitudeStr)
//print(self.attitudeStr)
//self.movement = self.gravityStr + self.userAccelerStr + self.rotationRateStr + self.attitudeStr
if self.sendOrNot{
//print("Falling motion detected!")
self.movement = "\(self.gravityStr), \(self.userAccelerStr), \(self.rotationRateStr), \(self.attitudeStr), \("_1")"
}
else{
self.movement = "\(self.gravityStr), \(self.userAccelerStr), \(self.rotationRateStr), \(self.attitudeStr), \("_0")"
}
//print(self.movement)
self.sendOrNot = false
}
}
}
override func didDeactivate() {
// This method is called when watch view controller is no longer visible
super.didDeactivate()
motionManager.stopDeviceMotionUpdates()
}
/**
func sendData(x:String){
let request = NSMutableURLRequest(url: NSURL(string: "http://147.46.242.219/addgyro2.php")! as URL)
request.httpMethod = "POST"
let postString = "a=\(x)"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if error != nil {
print("error=\(error)")
return
}
print("response = \(response)")
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("responseString = \(responseString)")
}
task.resume()
}
*/
/**
func getDocumentsDirectory() -> URL
{
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}
func getFileUrl() -> URL
{
let filePath = getDocumentsDirectory().appendingPathComponent(filename!)
return filePath
}
func startRecording(){
let audioSession = AVAudioSession.sharedInstance()
do{
audioRecorder = try AVAudioRecorder(url: getFileUrl(),
settings: settings)
audioRecorder.delegate = self
audioRecorder.prepareToRecord()
audioRecorder.record(forDuration: 5.0)
}
catch {
finishRecording(success: false)
}
do {
try audioSession.setActive(true)
audioRecorder.record()
} catch {
}
}
func finishRecording(success: Bool) {
audioRecorder.stop()
audioRecorder = nil
if success {
print(success)
} else {
audioRecorder = nil
print("Somthing Wrong.")
}
}
func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
if !flag {
finishRecording(success: false)
}
}
*/
// generate a short unique id
struct ShortCodeGenerator {
private static let base62chars = [Character]("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
private static let maxBase : UInt32 = 62
static func getCode(withBase base: UInt32 = maxBase, length: Int) -> String {
var code = ""
for _ in 0..<length {
let random = Int(arc4random_uniform(min(base, maxBase)))
code.append(base62chars[random])
}
return code
}
}
// Getting the address from longitude and latitude
func getAddressFromLatLon(pdblLatitude: String, withLongitude pdblLongitude: String) {
var center : CLLocationCoordinate2D = CLLocationCoordinate2D()
let lat: Double = Double("\(pdblLatitude)")!
//21.228124
let lon: Double = Double("\(pdblLongitude)")!
//72.833770
let ceo: CLGeocoder = CLGeocoder()
center.latitude = lat
center.longitude = lon
let loc: CLLocation = CLLocation(latitude:center.latitude, longitude: center.longitude)
ceo.reverseGeocodeLocation(loc, completionHandler:
{(placemarks, error) in
if (error != nil)
{
//print("reverse geodcode fail: \(error!.localizedDescription)")
}
let pm = placemarks! as [CLPlacemark]
if pm.count > 0 {
let pm = placemarks![0]
//print(pm.country)
//print(pm.locality)
//print(pm.subLocality)
//print(pm.thoroughfare)
//print(pm.postalCode)
//print(pm.subThoroughfare)
var addressString : String = ""
if pm.subLocality != nil {
addressString = addressString + pm.subLocality! + ", "
}
if pm.thoroughfare != nil {
addressString = addressString + pm.thoroughfare! + ", "
}
if pm.locality != nil {
addressString = addressString + pm.locality! + ", "
}
if pm.country != nil {
addressString = addressString + pm.country! + ", "
}
if pm.postalCode != nil {
addressString = addressString + pm.postalCode! + " "
}
//print(addressString)
}
})
}
#IBAction func manualBtnPressed() {
// manual reporting functionality
// generating 6 character long unique id
let uniqueId = ShortCodeGenerator.getCode(length: 6)
let txtMsg = "I am student \(uniqueId). I need help!"
print(txtMsg)
// Getting the address
if manualLat != 0.0 && manualLong != 0.0 {
var latStr = String(format:"%.2f",manualLat)
var longStr = String(format:"%.2f",manualLong)
getAddressFromLatLon(pdblLatitude: latStr, withLongitude: longStr)
let request = NSMutableURLRequest(url: NSURL(string: "http://147.46.242.219/addmanual.php")! as URL)
request.httpMethod = "POST"
let postString = "a=\(manualLat)&b=\(manualLong)&c=\(txtMsg)"
print(postString)
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if error != nil {
//print("error=\(error)")
return
}
//print("response = \(response)")
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
//print("responseString = \(responseString)")
}
task.resume()
}
}
// when button clicked label is shown
#IBAction func btnPressed() {
if(!isRecording){
let stopTitle = NSMutableAttributedString(string: "Stop Recording")
stopTitle.setAttributes([NSAttributedString.Key.foregroundColor: UIColor.red], range: NSMakeRange(0, stopTitle.length))
button.setAttributedTitle(stopTitle)
isRecording = true
startWorkout() //Start workout session/healthkit streaming
}else{
let exitTitle = NSMutableAttributedString(string: "Start Recording")
exitTitle.setAttributes([NSAttributedString.Key.foregroundColor: UIColor.red], range: NSMakeRange(0, exitTitle.length))
button.setAttributedTitle(exitTitle)
isRecording = false
healthStore.end(session!)
}
}
}
extension InterfaceController: HKWorkoutSessionDelegate{
func workoutSession(_ workoutSession: HKWorkoutSession, didChangeTo toState: HKWorkoutSessionState, from fromState: HKWorkoutSessionState, date: Date) {
switch toState {
case .running:
//print(date)
if let query = heartRateQuery(date){
self.currentQuery = query
healthStore.execute(query)
}
//Execute Query
case .ended:
//Stop Query
healthStore.stop(self.currentQuery!)
session = nil
default:
print("Unexpected state: \(toState)")
}
}
func workoutSession(_ workoutSession: HKWorkoutSession, didFailWithError error: Error) {
//Do Nothing
}
func startWorkout(){
// If a workout has already been started, do nothing.
if (session != nil) {
return
}
// Configure the workout session.
let workoutConfiguration = HKWorkoutConfiguration()
workoutConfiguration.activityType = .running
workoutConfiguration.locationType = .outdoor
do {
session = try HKWorkoutSession(configuration: workoutConfiguration)
session?.delegate = self
} catch {
fatalError("Unable to create workout session")
}
healthStore.start(self.session!)
//print("Start Workout Session")
// Here audio?
/**
if audioRecorder == nil {
print("Pressed")
filename = NSUUID().uuidString+".wav"
self.startRecording()
} else {
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let url = URL(fileURLWithPath: path)
print("Filename\(filename!)")
let pathPart = url.appendingPathComponent(filename!)
let filePath = pathPart.path
let request = NSMutableURLRequest(url: NSURL(string: "http://147.46.242.219/addsound.php")! as URL)
request.httpMethod = "POST"
let audioData = NSData(contentsOfFile: filePath)
print("Result is\(getFileUrl().path)")
print("Binary data printing")
print(audioData)
let postString = "a=\(audioData)"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest){
data, response, error in
if error != nil {
print("error=\(error)")
return
}
print("response = \(response)")
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("responseString = \(responseString)")
}
task.resume()
print("Pressed2")
self.finishRecording(success: true)
}
*/
}
func heartRateQuery(_ startDate: Date) -> HKQuery? {
let datePredicate = HKQuery.predicateForSamples(withStart: startDate, end: nil, options: .strictEndDate)
let predicate = NSCompoundPredicate(andPredicateWithSubpredicates:[datePredicate])
let heartRateQuery = HKAnchoredObjectQuery(type: hrType, predicate: predicate, anchor: nil, limit: Int(HKObjectQueryNoLimit)) { (query, sampleObjects, deletedObjects, newAnchor, error) -> Void in
//Do nothing
}
heartRateQuery.updateHandler = {(query, samples, deleteObjects, newAnchor, error) -> Void in
guard let samples = samples as? [HKQuantitySample] else {return}
DispatchQueue.main.async {
guard let sample = samples.first else { return }
// after extraction of bpm value conversion to double
let value = sample.quantity.doubleValue(for: HKUnit(from: "count/min"))
//print("Type of value is +\(type(of:value))")
let request = NSMutableURLRequest(url: NSURL(string: "http://147.46.242.219/addall.php")! as URL)
request.httpMethod = "POST"
//print(self.movement)
//let randomStr = 42.0
let postString = "gps_x=\(self.manualLat)&gps_y=\(self.manualLong)&a=\(self.movement)&hr=\(value)"
//print(postString)
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if error != nil {
//print("error=\(error)")
return
}
//print("response = \(response)")
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
//print("responseString = \(responseString)")
}
task.resume()
//print("This line is executed!")
//print(String(UInt16(value)))
}
}
return heartRateQuery
}
}
class HealthDataService {
internal let healthKitStore:HKHealthStore = HKHealthStore()
init() {}
func authorizeHealthKitAccess(_ completion: ((_ success:Bool, _ error:Error?) -> Void)!) {
let typesToShare = Set([hrType])
let typesToSave = Set([hrType])
healthKitStore.requestAuthorization(toShare: typesToShare, read: typesToSave) { (success, error) in
completion(success, error)
}
}
}
After I tried running your project in Xcode on Apple Watch, it crashed and the console said Could not cast value of type 'BullyingDetection_WatchKit_Extension.LocationOutside' (0x92ca0) to 'CLLocationManagerDelegate' (0x6b433f84).
On line 20 of your LocationOutside class, locationManager.delegate = (self as! CLLocationManagerDelegate) will have to be locationManager.delegate = self and the class will need to conform to the CLLocationManagerManagerDelegate protocol which also requires inheriting from NSObject:
class LocationOutside: NSObject, CLLocationManagerDelegate {
}
This should lead you in the right direction.
It may help to also read about delegation here https://docs.swift.org/swift-book/LanguageGuide/Protocols.html#ID276.

upload MapKit region to firebase

I try to save a map with the users location to a post, but I get Value of type 'MKMapView?' has no member 'MKMapView' as an error all the time...
The following shows my code but I leave out any background code to the images and labels as everything there works fine, I just include them in here so you know how I save the post informations... Do you know what my error is and how I can solve it?
var takenMap: MKMapView!
#IBAction func postPressed(_ sender: Any) {
if textView.text != "" && takenImage != nil && userLocation.text != "" {
// Create and save a new job
let newJob = Job(text: textView.text, jobImage: takenImage!, addedByUser: (userLabel?.text)!, userImage: UserImage, location: userLocation.text, map: takenMap.MKMapView)
newJob.save()
}
//MARK:- CLLocationManager Delegates
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let lastLocation = locations.last {
let geoCoder = CLGeocoder()
let center = CLLocationCoordinate2D(latitude: lastLocation.coordinate.latitude, longitude: lastLocation.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
map.setRegion(region, animated: true)
self.map = takenMap
geoCoder.reverseGeocodeLocation(lastLocation) { (placeMarks, error) in
if error == nil {
if let firstLocation = placeMarks?[0] {
self.locationManager.stopUpdatingLocation()
if let cityName = firstLocation.locality,
let street = firstLocation.thoroughfare {
self.scanLocation = "\(street), \(cityName)"
print("This is the current city name", cityName)
print("this is the current street address", street)
self.takenLocation = self.scanLocation!
self.userLocation.text = self.takenLocation
}
}
}
}
}
}
Job.swift:
var map: String?
init(map: String? = nil) {
self.map = map
ref = Database.database().reference().child("jobs").childByAutoId()
}
init(snapshot: DataSnapshot){
ref = snapshot.ref
if let value = snapshot.value as? [String : Any] {
map = value["location"] as? String
}
}
func save() {
let newPostKey = ref.key
// save jobImage
if let imageData = jobImage?.jpegData(compressionQuality: 0.5) {
let storage = Storage.storage().reference().child("jobImages/\(newPostKey)")
storage.putData(imageData).observe(.success, handler: { (snapshot) in
self.downloadURL = snapshot.metadata?.downloadURL()?.absoluteString
let postDictionary = [
"map" : self.map!
] as [String : Any]
self.ref.setValue(postDictionary)
})
}
}
I left out any code for labels or whatever out so the snippet won't be too long
The code takenMap.MKMapView should probably just be takenMap.

Showing multiple location using 'MKMapView'

I am trying to show multiple locations which saved in Mysql using the code below. The data is loading but I have no idea how to show multiple locations depending on latitude and longitude.
Mysql is connected to application via PHP file.
Here is my code, the part which I called from NSObject:
func downloadItems() {
// the download function
// return the nsuserdefaults which hold the lati and longi from the notification table
UserDefaults.standard.string(forKey: "test");
let myUrl = UserDefaults.standard.string(forKey: "test");
let urlPath: String = myUrl!
let url: URL = URL(string: urlPath)!
let defaultSession = Foundation.URLSession(configuration: URLSessionConfiguration.default)
let task = defaultSession.dataTask(with: url) { (data, response, error) in
if error != nil {
print("Failed to download data")
}else {
print("Data downloaded")
self.parseJSON(data!)
}
}
task.resume()
}
func parseJSON(_ data:Data) {
var jsonResult = NSArray()
do{
jsonResult = try JSONSerialization.jsonObject(with: data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray
} catch let error as NSError {
print(error)
}
var jsonElement = NSDictionary()
let locations = NSMutableArray()
for i in 0 ..< jsonResult.count
{
jsonElement = jsonResult[i] as! NSDictionary
let location = LocationModel()
//the following insures none of the JsonElement values are nil through optional binding
if let evIdL = jsonElement["id"] as? String,
let evUserNameL = jsonElement["username"] as? String,
let evNotikindL = jsonElement["notikind"] as? String,
let evLatiL = jsonElement["lati"] as? String,
let evLongiL = jsonElement["longi"] as? String,
let evLocatL = jsonElement["locat"] as? String,
let evTimedateL = jsonElement["timedate"] as? String,
let evDistanceL = jsonElement["distance"] as? String
{
location.evId = evIdL
location.evUsername = evUserNameL
location.evNotikind = evNotikindL
location.evLati = evLatiL
location.evLongi = evLongiL
location.evLocat = evDistanceL
location.evTimedate = evTimedateL
location.evDisatnce = evDistanceL
location.evLocat = evLocatL
}
locations.add(location)
}
DispatchQueue.main.async(execute: { () -> Void in
self.delegate.itemsDownloaded(items: locations)
})
}
}
I have no idea how to show few location on map.
try this code....
var locations = NSMutableArray()
var mapView = GMSMapView()
for i in 0..< location.count{
let obj = location[i]
lat = obj["lati"] as? Double
lng = obj["longi"] as? Double
let markerPoint = GMSMarker()
markerPoint.position = CLLocationCoordinate2D(latitude: lat!, longitude: lng!)
markerPoint.iconView = self.avtarImage() // Your image name
markerPoint.map = mapView // your mapview object name
markerPoint.zIndex = Int32(i)
markerPoint.infoWindowAnchor = CGPoint(x: 0, y: 0)
markerPoint.accessibilityLabel = String(format: "%d", i)
}

UICollectionViewFlowLayoutBreakForInvalidSizes to catch this in the debugger

I am trying to create a seat map layout functionality that takes the coordinates and create a map i want to provide the value of the sections that the map contains. I am using custom collectionViewLayout to create the cells but i am getting that error in the title .
Here is my protocol-
protocol SeatMapDelegate: class {
func getSectionCoordinates() -> [Int]
}
Definition -
func getSectionCoordinates() -> [Int] {
return sectionHeader
}
and then i am assigning the values to the array
var sectionHeader = [Int]()
sectionHeader=(delegate?.getSectionCoordinates())!
below code is my project for search and find coordinate on the map:
Maybe help you
// ViewController.swift
// MapKit Starter
//
// Created by Ehsan Amiri on 10/25/16.
// Copyright © 2016 Ehsan Amiri. All rights reserved.
//
import UIKit
import MapKit
import Foundation
class ViewController: UIViewController {
#IBOutlet var mapView: MKMapView?
#IBOutlet weak var text: UITextField!
var index = 0
var indexx = 0
let locationManager = CLLocationManager()
var picName:String?
var place :MKAnnotation?
var places = [Place]()
var place1 :MKAnnotation?
var places1 = [Place]()
override func viewDidLoad() {
super.viewDidLoad()
//downpic()
self.requestLocationAccess()
}
override func viewWillAppear(_ animated: Bool) {
let defaults = UserDefaults.standard
let age = defaults.integer(forKey: "maptype")
switch (age) {
case 0:
mapView?.mapType = .standard
case 1:
mapView?.mapType = .satellite
case 2:
mapView?.mapType = .hybrid
default:
mapView?.mapType = .standard
}
}
#IBAction func info(_ sender: Any) {
}
override var prefersStatusBarHidden: Bool {
return true
}
func requestLocationAccess() {
let status = CLLocationManager.authorizationStatus()
switch status {
case .authorizedAlways, .authorizedWhenInUse:
return
case .denied, .restricted:
print("location access denied")
default:
locationManager.requestWhenInUseAuthorization()
}
}
#IBAction func textField(_ sender: Any) {
mapView?.removeOverlays((mapView?.overlays)!)
mapView?.removeAnnotations((mapView?.annotations)!)
self.server()
_ = Timer.scheduledTimer(timeInterval: 10.0, target: self, selector: #selector(self.server), userInfo: nil, repeats: true)
let when = DispatchTime.now() + 1.5
DispatchQueue.main.asyncAfter(deadline: when) {
if self.indexx != 0 {
self.addAnnotations()
self.addPolyline()
}
}
}
#objc func server() {
place = nil
places = [Place]()
place1 = nil
places1 = [Place]()
indexx = 0
let id = text.text
print("id=\(id!)")
let url = URL(string: "my server")!
var request = URLRequest(url: url)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
let postString = "id=\(id!)"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else { // check for fundamental networking error
print("error=\(String(describing: error))")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(String(describing: response))")
}
let responseString = String(data: data, encoding: .utf8)
print("responseString = \(String(describing: responseString))")
let stringgg = "notFound\n\n\n\n"
if responseString == stringgg {
print(stringgg)
}else{
let json = try! JSONSerialization.jsonObject(with: data, options: [])
let betterJSON = json as! NSArray
let jsonCount = betterJSON.count
print(betterJSON)
for item in betterJSON {
self.indexx += 1
let dictionary = item as? [String : Any]
let title = dictionary?["title"] as? String
let subtitle = dictionary?["description"] as? String
let latitude = dictionary?["latitude"] as? Double ?? 0, longitude = dictionary?["longitude"] as? Double ?? 0
self.place = Place(title: title, subtitle: subtitle, coordinate: CLLocationCoordinate2DMake(latitude , longitude ))
self.places.append(self.place as! Place)
print("latttt",longitude)
if self.indexx == 1{
let shipid = UserDefaults.standard
shipid.set(title, forKey: "origin")
shipid.set(subtitle, forKey: "date")
}
if jsonCount == self.indexx{
let shipid = UserDefaults.standard
shipid.set(title, forKey: "location")
self.place1 = Place(title: title, subtitle: subtitle, coordinate: CLLocationCoordinate2DMake(latitude , longitude ))
self.places1.append(self.place1 as! Place)
}
}
}
}
task.resume()
let when = DispatchTime.now() + 1.5
DispatchQueue.main.asyncAfter(deadline: when) {
if self.indexx != 0 {
self.addAnnotations()
self.addPolyline()
}
}
}
func addAnnotations() {
print("hhhh",places)
mapView?.delegate = self
mapView?.removeAnnotations((mapView?.annotations)!)
mapView?.addAnnotations(places1)
let overlays = places1.map { MKCircle(center: $0.coordinate, radius: 100) }
mapView?.addOverlays(overlays)
}
func addPolyline() {
var locations = places.map { $0.coordinate }
let polyline = MKPolyline(coordinates: &locations, count: locations.count)
// print("Number of locations: \(locations.count)")
index = locations.capacity
mapView?.add(polyline)
}
}
extension ViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
else {
let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "annotationView") ?? MKAnnotationView()
annotationView.image = UIImage(named:"place icon")
annotationView.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
annotationView.canShowCallout = true
return annotationView
}
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if overlay is MKCircle {
let renderer = MKCircleRenderer(overlay: overlay)
renderer.fillColor = UIColor.black.withAlphaComponent(0.5)
renderer.strokeColor = UIColor.blue
renderer.lineWidth = 2
return renderer
} else if overlay is MKPolyline {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = UIColor.orange
renderer.lineWidth = 2
return renderer
}
return MKOverlayRenderer()
}
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
//guard let annotation = view.annotation as? Place, let title = annotation.title else { return }
let shipidname = text.text
let shipid = UserDefaults.standard
shipid.set(shipidname, forKey: "shipid")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let secondViewController = storyboard.instantiateViewController(withIdentifier: "shipinfo")
self.present(secondViewController, animated: true, completion: nil)
}
}

Trouble at reloading map annotations

I'm making an app that should load all the gas stations and their prices on the state.
The map should reload the prices if the user selects a diferent type of gas (Magna, Premium and Diesel). This is made through a UISegment control.
The trouble is that when I reload the map it doesn't print the correct price (the default one is magna, and when I select the other type of gas it doesn't load the new prices).
This is my code.
class MapViewController: UIViewController,MKMapViewDelegate, CLLocationManagerDelegate,UICollectionViewDelegate, UICollectionViewDataSource {
let manager = CLLocationManager()
public let sMAGNA = "magna"
public let sPREMIUM = "premium"
public let sDIESEL = "diesel"
public let MIN_TIME: CLong = 400
private let MIN_DISTANCE: Float = 1000
private var ubicaciones_selected: [Ubicacion] = []
private var ubicaciones_magna: [Ubicacion] = []
private var ubicaciones_premium: [Ubicacion] = []
private var ubicaciones_diesel: [Ubicacion] = []
private let REQUEST_LOCATION = 1
private var latlon: String = ""
private var mType: String = "magna"
var ubicaciones:[Ubicacion] = []
var Ubigaspin = MKPointAnnotation()
#IBAction func MapType(_ sender: Any) {
if mapa.mapType == MKMapType.standard{
mapa.mapType = MKMapType.satellite
} else {
mapa.mapType = MKMapType.standard
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.mapa.delegate = self
//con esto obtendremos la ubicacion del usuario
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
mapa.showsUserLocation = true
manager.startUpdatingLocation()
//se cargan los pines y las gasolinas
loadGas(tipo: mType)
}
func loadGas(tipo:String){
mType = tipo
var ubicaciones:[Ubicacion] = []
switch tipo {
case sMAGNA:
ubicaciones = ubicaciones_magna
case sPREMIUM:
ubicaciones = ubicaciones_premium
case sDIESEL:
ubicaciones = ubicaciones_diesel
default:
ubicaciones = ubicaciones_magna
}
if ubicaciones.count == 0 {
let url = URL(string: "http://192.241.214.56/api/"+tipo+"/?format=json")
URLSession.shared.dataTask(with: url!, completionHandler: {
(data, response, error) in
if(error != nil){
print("error")
}else{
do{
let ubicaciones_json = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [[String : AnyObject]]
for ubicacion in ubicaciones_json{
let nombre:String = ubicacion["nombre"] as! String
let direccion:String = ubicacion["direccion"] as! String
let precio_magna:Float = ubicacion["precio_magna"] as! Float
let precio_premium:Float = ubicacion["precio_premium"] as! Float
let precio_diesel:Float = ubicacion["precio_diesel"] as! Float
let ubicacion:String = ubicacion["ubicacion"] as! String
let p = Ubicacion()
p.ubicacion = ubicacion
p.setLatLng()
p.nombre = nombre
p.direccion = direccion
p.precio_magna = precio_magna
p.precio_premium = precio_premium
p.precio_diesel = precio_diesel
ubicaciones.append(p)
}
self.ubicaciones = ubicaciones
OperationQueue.main.addOperation({
self.updatePins(ubicaciones: ubicaciones)
})
}catch let error as NSError{
print(error)
}
}
}).resume()
}else{
self.ubicaciones = ubicaciones
self.updatePins(ubicaciones: ubicaciones)
}
}
func updatePins(ubicaciones:[Ubicacion]){
mapa.removeAnnotations(mapa.annotations)
for ubicacion in ubicaciones{
let anno = CustonAnno(ubicacion:ubicacion, image: #imageLiteral(resourceName: "icon"))
anno.coordinate = CLLocationCoordinate2D(latitude: ubicacion.latitude!, longitude: ubicacion.longitude!)
anno.title=ubicacion.nombre
//anno.subtitle="$\(ubicacion.getPrecio(tipo: mType))"
self.mapa.addAnnotation(anno)
}
}
#IBAction func changeSegment(_ sender: UISegmentedControl) {
print(sender.selectedSegmentIndex)
switch sender.selectedSegmentIndex {
case 0:
loadGas(tipo: sMAGNA)
case 1:
loadGas(tipo: sPREMIUM)
case 2:
loadGas(tipo: sDIESEL)
default:
loadGas(tipo: sMAGNA)
}
}
}
I think your problem is with your ubicaciones vars, you have a local var and a instance var with the same name, you need work all the time with your instance var instead of create another, you are also losing your information over and over again making your network calls needed every time you change your gas type
Try replacing your loadGas method
by this one
func loadGas(tipo:String){
mType = tipo
switch tipo {
case sMAGNA:
if(ubicaciones_magna.count > 0){
self.ubicaciones = ubicaciones_magna
self.updatePins(ubicaciones: self.ubicaciones)
return
}
case sPREMIUM:
if(ubicaciones_premium.count > 0){
self.ubicaciones = ubicaciones_premium
self.updatePins(ubicaciones: self.ubicaciones)
return
}
case sDIESEL:
if(ubicaciones_diesel.count > 0){
self.ubicaciones = ubicaciones_diesel
self.updatePins(ubicaciones: self.ubicaciones)
return
}
default:
if(ubicaciones_magna.count > 0){
self.ubicaciones = ubicaciones_magna
self.updatePins(ubicaciones: self.ubicaciones)
return
}
}
let url = URL(string: "http://192.241.214.56/api/"+tipo+"/?format=json")
URLSession.shared.dataTask(with: url!, completionHandler: {
(data, response, error) in
if(error != nil){
print("error")
}else{
do{
let ubicaciones_json = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [[String : AnyObject]]
var newUbications:[Ubicacion] = []
for ubicacion in ubicaciones_json{
let nombre:String = ubicacion["nombre"] as! String
let direccion:String = ubicacion["direccion"] as! String
let precio_magna:Float = ubicacion["precio_magna"] as! Float
let precio_premium:Float = ubicacion["precio_premium"] as! Float
let precio_diesel:Float = ubicacion["precio_diesel"] as! Float
let ubicacion:String = ubicacion["ubicacion"] as! String
let p = Ubicacion()
p.ubicacion = ubicacion
p.setLatLng()
p.nombre = nombre
p.direccion = direccion
p.precio_magna = precio_magna
p.precio_premium = precio_premium
p.precio_diesel = precio_diesel
newUbications.append(p)
}
switch tipo {
case sMAGNA:
self.ubicaciones_magna = newUbications
self.ubicaciones = self.ubicaciones_magna
case sPREMIUM:
self.ubicaciones_premium = newUbications
self.ubicaciones = self.ubicaciones_premium
case sDIESEL:
self.ubicaciones_diesel = newUbications
self.ubicaciones = ubicaciones_diesel
default:
self.ubicaciones_magna = newUbications
self.ubicaciones = self.ubicaciones_magna
}
OperationQueue.main.addOperation({
self.updatePins(ubicaciones: self.ubicaciones)
})
}catch let error as NSError{
print(error)
}
}
}).resume()
}

Resources