iOS app freezes after dismiss view in swift - ios

My issue is this I have two viewControllers connected with a modal segue like normal A--->B, A has the controls like textFields, switches, buttons and a mapView where I get the userLocation. B hast only a button, and a mapView at the moment, but when I tap the exit button it does successfully dismisses viewController B and shows A only controls are frozen, can't tap anything anymore, I don't know why. Any help?
B code
import UIKit
import MapKit
import Parse
import CoreLocation
class MapaMososViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var mapMozosFollow: MKMapView!
var totlaAutomozo: String!
var fechaRegistro: String!
override func viewDidLoad() {
super.viewDidLoad()
mapMozosFollow.delegate = self
mapMozosFollow.showsUserLocation = true
mapMozosFollow.showsTraffic = false
mapMozosFollow.showsScale = false
print(mapMozosFollow.userLocation.location)
}
override func viewDidAppear(_ animated: Bool) {
self.displayError(error: "Exito", message: "Tu pago ha sido procesado, en unos momentos atenderemos tu orden. Total es de $\(totlaAutomozo!) la fecha registrada \(fechaRegistro!)")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func viewWillDisappear(_ animated: Bool) {
}
#IBAction func salirTapped(_ sender: UIButton) {
self.dismiss(animated: true, completion: {
print("here dismissing")
})
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print(locations.last!.coordinate)
centerMapOnLocation(locations.last!)
}
let regionRadius: CLLocationDistance = 2000
func centerMapOnLocation(_ location: CLLocation) {
let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate,
regionRadius * 2.0, regionRadius * 2.0)
mapMozosFollow.setRegion(coordinateRegion, animated: true)
}
}
EDIT 1: A ViewController code.
import UIKit
import Parse
import MapKit
import BraintreeDropIn
import Braintree
class ViewController: UIViewController, PayPalPaymentDelegate, PayPalFuturePaymentDelegate, PayPalProfileSharingDelegate, CLLocationManagerDelegate, UITextFieldDelegate, MKMapViewDelegate, BTDropInViewControllerDelegate {
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var mapaLugar: MKMapView!
#IBOutlet weak var numeroExteriorTextField: UITextField!
#IBOutlet weak var telefonoTextField: UITextField!
#IBOutlet weak var lavadoSwitch: UISwitch!
#IBOutlet weak var lavadoYAspiradSwitch: UISwitch!
#IBOutlet weak var numeroCarrosTextField: UITextField!
#IBOutlet weak var numeroMinivanTextField: UITextField!
#IBOutlet weak var numeroPickUpsTextField: UITextField!
#IBOutlet weak var numeroVansTextField: UITextField!
#IBOutlet weak var numeroAspiradoCarrosTextField: UITextField!
#IBOutlet weak var numeroAspiradoMinivanTextField: UITextField!
#IBOutlet weak var numeroAspiradoPickUpsTextField: UITextField!
#IBOutlet weak var numeroAspiradoVansTextField: UITextField!
#IBOutlet weak var botonRealizarPedido: UIButton!
#IBOutlet weak var botonInstrucciones: UIButton!
#IBOutlet weak var totalLabel: UILabel!
var showAlertFirstTime: Bool = true
var locationManager: CLLocationManager = CLLocationManager()
var ubicacion: CLLocationCoordinate2D!
var environment:String = PayPalEnvironmentSandbox {
willSet(newEnvironment) {
if (newEnvironment != environment) {
PayPalMobile.preconnect(withEnvironment: newEnvironment)
}
}
}
var braintreeClient: BTAPIClient?
let defaults = UserDefaults.standard
var resultText = "" // empty
var payPalConfig = PayPalConfiguration() // default
var total: NSDecimalNumber!
var vistaDeMozos: Bool = false
var fechaRegistro: String!
var totalToSend: String!
#IBOutlet weak var constrainSizeMap: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
botonInstrucciones.backgroundColor = UIColor(colorLiteralRed: (200.0/255.0), green: 0.0, blue: 0.0, alpha: 1.0)
botonInstrucciones.layer.cornerRadius = 3
botonInstrucciones.layer.borderWidth = 2
botonInstrucciones.layer.borderColor = UIColor.clear.cgColor
botonInstrucciones.layer.shadowColor = UIColor(colorLiteralRed: (100.0/255.0), green: 0.0, blue: 0.0, alpha: 1.0).cgColor
botonInstrucciones.layer.shadowOpacity = 1.0
botonInstrucciones.layer.shadowRadius = 1.0
botonInstrucciones.layer.shadowOffset = CGSize(width: 0, height: 3)
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.requestAlwaysAuthorization()
self.locationManager.startUpdatingLocation()
NotificationCenter.default.post(name: Notification.Name(rawValue: "keyPressed"), object: nil)
numeroCarrosTextField.delegate = self
numeroMinivanTextField.delegate = self
numeroPickUpsTextField.delegate = self
numeroVansTextField.delegate = self
numeroAspiradoCarrosTextField.delegate = self
numeroAspiradoMinivanTextField.delegate = self
numeroAspiradoPickUpsTextField.delegate = self
numeroAspiradoVansTextField.delegate = self
do {
if defaults.object(forKey: "clientId") == nil || clientId == "000" {
let idTest = try PFCloud.callFunction("newCutomer", withParameters: nil)
print(idTest)
clientId = idTest as! String
defaults.set(clientId, forKey: "clientId")
} else {
print(self.clientId)
}
} catch let error {
print(error)
}
if defaults.object(forKey: "clientId") == nil {
} else {
clientId = defaults.string(forKey: "clientId")!
print(clientId)
}
fetchClientToken()
NotificationCenter.default.addObserver(
self,
selector: #selector(ViewController.keyboardWillShow(notification:)),
name: NSNotification.Name.UIKeyboardWillShow,
object: nil
)
NotificationCenter.default.addObserver(
self,
selector: #selector(ViewController.keyboardWillHide(notification:)),
name: NSNotification.Name.UIKeyboardWillHide,
object: nil
)
scrollView.keyboardDismissMode = UIScrollViewKeyboardDismissMode.interactive
let touch = UITapGestureRecognizer(target: self, action: #selector(ViewController.singleTapGestureCaptured(gesture:)))
scrollView.addGestureRecognizer(touch)
}
func singleTapGestureCaptured(gesture: UITapGestureRecognizer){
self.view.endEditing(true)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if showAlertFirstTime {
showAlertFirstTime = false
} else {
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
PayPalMobile.preconnect(withEnvironment: environment)
print("stop test")
}
#IBAction func realizarPedidoTapped(_ sender: UIButton) {
let numeroExterior = numeroExteriorTextField.text!
let numeroMotosLavado = numeroCarrosTextField.text!
let numeroDeportivosLavado = numeroMinivanTextField.text!
let numeroCarroLavado = numeroPickUpsTextField.text!
let numeroCamionLavado = numeroVansTextField.text!
let numeroMotoLavadoAspirado = numeroAspiradoCarrosTextField.text!
let numeroDeportivoLavadoAspirado = numeroAspiradoMinivanTextField.text!
let numeroCarroLavadoAspirado = numeroAspiradoPickUpsTextField.text!
let numeroCamionLavadoAspirado = numeroAspiradoVansTextField.text!
let numeroTelefono = telefonoTextField.text!
if numeroExterior == "" || numeroTelefono == "" {
displayError("Error", message: "Te falto llenar tu numero exterior y/o telefono")
} else {
//Braintree init
self.braintreeClient = BTAPIClient(authorization: clientToken)
let items = [item1]
let subtotal = PayPalItem.totalPrice(forItems: items)
//var subtotal = PayPalItem.totalPrice(forItems: items)
let shipping = NSDecimalNumber(string: "0.00")
let tax = NSDecimalNumber(string: "0.00")
//details ???
let paymentDetails = PayPalPaymentDetails(subtotal: subtotal, withShipping: shipping, withTax: tax)
self.total = subtotal.adding(shipping).adding(tax)
let payment = PayPalPayment(amount: total, currencyCode: "MXN", shortDescription: "Automozo inc", intent: .sale)
payment.items = items
payment.paymentDetails = paymentDetails
print("\(payment.localizedAmountForDisplay)")
self.showDropIn(clientTokenOrTokenizationKey: clientToken)
if (payment.processable) {
let paymentViewController = PayPalPaymentViewController(payment: payment, configuration: payPalConfig, delegate: self)
}
else {
print("Payment not processalbe: \(payment.description)")
print("payment not processable \(payment)")
displayError("Error", message: "Hubo un error al procesar tu pago, por favor intenta de nuevo.")
}
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
if segue.identifier == "MapaMozosSegue" {
let mapaMozosVC = segue.destination as! MapaMososViewController
mapaMozosVC.totlaAutomozo = totalToSend!
mapaMozosVC.fechaRegistro = fechaRegistro
locationManager.stopUpdatingLocation()
}
}
func textFieldDidEndEditing(_ textField: UITextField) {
textField.resignFirstResponder()
print("test text field ended")
if textField.text == "" {
textField.text = "0"
}
var numeroCarrosLavadoVar = numeroCarrosTextField.text!
var numeroMinivansLavadoVar = numeroMinivanTextField.text!
var numeroPickUpsLavadoVar = numeroPickUpsTextField.text!
var numeroVansLavadoVar = numeroVansTextField.text!
var numeroCarrosLavadoAspiradoVar = numeroAspiradoCarrosTextField.text!
var numeroMinivansLavadoAspiradoVar = numeroAspiradoMinivanTextField.text!
var numeroPickUpsLavadoAspiradoVar = numeroAspiradoPickUpsTextField.text!
var numeroVansLavadoAspiradoVar = numeroAspiradoVansTextField.text!
if numeroCarrosLavadoVar == "" {
numeroCarrosLavadoVar = "0"
numeroCarrosTextField.text = "0"
}
if numeroMinivansLavadoVar == "" {
numeroMinivansLavadoVar = "0"
numeroMinivanTextField.text = "0"
}
if numeroPickUpsLavadoVar == "" {
numeroPickUpsLavadoVar = "0"
numeroPickUpsTextField.text = "0"
}
if numeroVansLavadoVar == "" {
numeroVansLavadoVar = "0"
numeroVansTextField.text = "0"
}
if numeroCarrosLavadoAspiradoVar == "" {
numeroCarrosLavadoAspiradoVar = "0"
numeroAspiradoCarrosTextField.text = "0"
}
if numeroMinivansLavadoAspiradoVar == "" {
numeroMinivansLavadoAspiradoVar = "0"
numeroMinivanTextField.text = "0"
}
if numeroPickUpsLavadoAspiradoVar == "" {
numeroPickUpsLavadoAspiradoVar = "0"
numeroAspiradoPickUpsTextField.text = "0"
}
if numeroVansLavadoAspiradoVar == "" {
numeroVansLavadoAspiradoVar = "0"
numeroVansTextField.text = "0"
}
let priceOfLavadoCarro = Int(numeroCarrosLavadoVar)! * pricesLavado["LavadoCarro"]!
let priceOfLavadoMinivan = Int(numeroMinivansLavadoVar)! * pricesLavado["LavadoMinivan"]!
let priceOfLavadoPickUp = Int(numeroPickUpsLavadoVar)! * pricesLavado["LavadoPickUp"]!
let priceOfLavadoVan = Int(numeroVansLavadoVar)! * pricesLavado["LavadoVan"]!
//Lavado y Aspirado
let priceOfLavadoYAspiradoCarro = Int(numeroCarrosLavadoAspiradoVar)! * pricesLavadoYAspirado["LavadoYAspiradoCarro"]!
let priceOfLavadoYAspiradoMinivan = Int(numeroMinivansLavadoAspiradoVar)! * pricesLavadoYAspirado["LavadoYAspiradoMinivan"]!
let priceOfLavadoYAspiradoPickUp = Int(numeroPickUpsLavadoAspiradoVar)! * pricesLavadoYAspirado["LavadoYAspiradoPickUp"]!
let priceOfLavadoYAspiradoVan = Int(numeroVansLavadoAspiradoVar)! * pricesLavadoYAspirado["LavadoYAspiradoVan"]!
let totalAutomozo = priceOfLavadoCarro + priceOfLavadoMinivan + priceOfLavadoPickUp + priceOfLavadoVan + priceOfLavadoYAspiradoCarro + priceOfLavadoYAspiradoMinivan + priceOfLavadoYAspiradoPickUp + priceOfLavadoYAspiradoVan
print(totalAutomozo)
totalLabel.text = "\(totalAutomozo).00"
textField.resignFirstResponder()
}
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
if (textField.text?.characters.count)! == 1 {
print("text quota meet")
textField.resignFirstResponder()
self.view.endEditing(true)
return true
} else {
textField.text = "0"
}
return true
}
let regionRadius: CLLocationDistance = 100
func centerMapOnLocation(_ location: CLLocation) {
let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate,
regionRadius * 2.0, regionRadius * 2.0)
mapaLugar.setRegion(coordinateRegion, animated: true)
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
centerMapOnLocation(locations.last!)
ubicacion = locations.last!.coordinate
}
// Mark - Braintree methods
func showDropIn(clientTokenOrTokenizationKey: String) {
var value: Bool = false
var totlaAutomozo = self.totalLabel.text
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM dd YYYY HH:mm"
dateFormatter.timeZone = NSTimeZone.local
fechaRegistro = dateFormatter.string(from: Date())
let request = BTDropInRequest()
request.amount = "\(total)"
request.currencyCode = "MXN"
print(request.description)
BTUIKAppearance.darkTheme()
BTUIKAppearance.sharedInstance().activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
// request.
let dropIn = BTDropInController(authorization: clientTokenOrTokenizationKey, request: request)
{ (controller, result, error) in
if (error != nil) {
print("ERROR")
} else if (result?.isCancelled == true) {
print("CANCELLED")
} else if let result = result {
// Use the BTDropInResult properties to update your UI
print(result.paymentOptionType)
print("payment method: \(result.paymentMethod?.nonce)")
print("ppayment desc \(result.paymentDescription)")
print(result.paymentIcon.description)
value = self.postNonceToServer(paymentMethodNonce: (result.paymentMethod?.nonce)!)
}
controller.dismiss(animated: true, completion: nil)
if value {
self.locationManager.stopUpdatingLocation()
self.performSegue(withIdentifier: "MapaMozosSegue", sender: self)
self.vistaDeMozos = true
} else {
self.displayError("Alerta", message: "El pedido ha sido cancelado exitosamente.")
//top row
self.numeroCarrosTextField.text = "0"
self.numeroMinivanTextField.text = "0"
self.numeroPickUpsTextField.text = "0"
self.numeroVansTextField.text = "0"
//bottom row
self.numeroAspiradoCarrosTextField.text = "0"
self.numeroAspiradoMinivanTextField.text = "0"
self.numeroAspiradoPickUpsTextField.text = "0"
self.numeroAspiradoVansTextField.text = "0"
//data
self.telefonoTextField.text = ""
self.telefonoTextField.text = ""
}
}
self.present(dropIn!, animated: true, completion: nil)
}
func userDidCancelPayment() {
self.dismiss(animated: true, completion: nil)
}
func postNonceToServer(paymentMethodNonce: String) -> Bool {
var val = true
do {
var response = try PFCloud.callFunction("checkout", withParameters: ["payment_method_nonce":paymentMethodNonce, "amount":"\(total!).00", "customerId": clientId])
print(response)
} catch let error {
print(error.localizedDescription)
}
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM. dd, YYYY HH:mm"
dateFormatter.timeZone = NSTimeZone.local
fechaRegistro = dateFormatter.string(from: Date())
let usuarioPagado: PFObject = PFObject(className: "Ordenes")
let location: PFGeoPoint = PFGeoPoint(latitude: ubicacion.latitude, longitude: ubicacion.longitude)
usuarioPagado["Ubicacion"] = location
usuarioPagado["NumeroExterior"] = numeroExteriorTextField.text!
usuarioPagado["NumeroDeTelefono"] = telefonoTextField.text!
usuarioPagado["LavadoCarro"] = numeroCarrosTextField.text!
usuarioPagado["LavadoMiniVan"] = numeroMinivanTextField.text!
usuarioPagado["LavadoPickUp"] = numeroPickUpsTextField.text!
usuarioPagado["LavadoDeVan"] = numeroVansTextField.text!
usuarioPagado["LavadoAspiradoCarro"] = numeroAspiradoCarrosTextField.text!
usuarioPagado["LavadoAspiradoMiniVan"] = numeroAspiradoMinivanTextField.text!
usuarioPagado["LavadoAspiradoPickUp"] = numeroAspiradoPickUpsTextField.text!
usuarioPagado["LavadoAspiradoDeVan"] = numeroAspiradoVansTextField.text!
usuarioPagado["Monto"] = totalLabel.text!
usuarioPagado["NumeroDeTelefono"] = telefonoTextField.text!
usuarioPagado["TipoDeCelular"] = "iPhone"
usuarioPagado["FechaDeOrden"] = fechaRegistro
self.totalToSend = self.totalLabel.text!
usuarioPagado.saveInBackground() {
(success: Bool, error: Error?) -> Void in
if error == nil {
//done
print("saved object")
val = false
} else {
//not done
print("not saved because \(error?.localizedDescription)")
}
}
numeroCarrosTextField.text = "0"
numeroMinivanTextField.text = "0"
numeroPickUpsTextField.text = "0"
numeroVansTextField.text = "0"
numeroAspiradoCarrosTextField.text = "0"
numeroAspiradoMinivanTextField.text = "0"
numeroAspiradoPickUpsTextField.text = "0"
numeroAspiradoVansTextField.text = "0"
totalLabel.text = "00.00"
self.lavadoSwitch.isOn = false
self.lavadoYAspiradSwitch.isOn = false
self.numeroExteriorTextField.text = ""
self.telefonoTextField.text = ""
self.numeroCarrosTextField.isHidden = true
self.numeroMinivanTextField.isHidden = true
self.numeroPickUpsTextField.isHidden = true
self.numeroVansTextField.isHidden = true
self.numeroAspiradoCarrosTextField.isHidden = true
self.numeroAspiradoMinivanTextField.isHidden = true
self.numeroAspiradoPickUpsTextField.isHidden = true
self.numeroAspiradoVansTextField.isHidden = true
return val
}
func drop(inViewControllerDidLoad viewController: BTDropInViewController) {
print("did load view drop")
}
func drop(inViewControllerDidCancel viewController: BTDropInViewController) {
print("did cancel drop payment")
}
func drop(inViewControllerWillComplete viewController: BTDropInViewController) {
print("drop will complete payment")
}
func drop(_ viewController: BTDropInViewController, didSucceedWithTokenization paymentMethodNonce: BTPaymentMethodNonce) {
var totlaAutomozo = totalLabel.text
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM dd YYYY HH:mm"
dateFormatter.timeZone = NSTimeZone.local
fechaRegistro = dateFormatter.string(from: Date())
print("did succeeded with tokenization")
print(" \(paymentMethodNonce.nonce)")
var value = postNonceToServer(paymentMethodNonce: paymentMethodNonce.nonce)
self.dismiss(animated: true, completion: nil)
if value {
displayError("Exito", message: "Tu pago ha sido procesado, en unos momentos atenderemos tu orden. Total es de $\(totlaAutomozo ?? "00.00") la fecha registrada \(fechaRegistro)")
} else {
self.displayError("Error", message: "Hubo un error al guardar tu informacion, ponte en contacto con nosotros.")
}
}
func fetchClientToken() {
do {
let response = try PFCloud.callFunction("generateToken", withParameters: ["clientId": clientId])
self.clientToken = response as! String
} catch let error {
print(error)
}
}
func keyboardWillShow(notification:NSNotification){
var userInfo = notification.userInfo!
var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
keyboardFrame = self.view.convert(keyboardFrame, from: nil)
var contentInset:UIEdgeInsets = self.scrollView.contentInset
contentInset.bottom = keyboardFrame.size.height
self.scrollView.contentInset = contentInset
}
func keyboardWillHide(notification:NSNotification){
let contentInset:UIEdgeInsets = UIEdgeInsets.zero
self.scrollView.contentInset = contentInset
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
self.view.endEditing(true)
}
func showFullMap() {
if vistaDeMozos {
self.telefonoTextField.isHidden = true
self.botonRealizarPedido.isHidden = true
self.lavadoSwitch.isHidden = true
self.lavadoYAspiradSwitch.isHidden = true
self.botonRealizarPedido.isHidden = true
self.numeroExteriorTextField.isHidden = true
self.numeroCarrosTextField.isHidden = true
self.numeroMinivanTextField.isHidden = true
self.numeroPickUpsTextField.isHidden = true
self.numeroVansTextField.isHidden = true
self.numeroAspiradoCarrosTextField.isHidden = true
self.numeroAspiradoMinivanTextField.isHidden = true
self.numeroAspiradoPickUpsTextField.isHidden = true
self.numeroAspiradoVansTextField.isHidden = true
self.view.layoutSubviews()
} else {
}
}
}

Did you try pausing the app with the debugger to inspect the stack frames? Sometimes that can help you spot deadlocks or infinite loops. You'll find the pause button in the bar between the code editor and the debugger (or at the bottom if the debugger is hidden):
Look at the stack frames in the Debug Navigator on the left-hand side of the Xcode window. Can you see anything suspicious? Here is a stack frame that indicates the app is idling on the main run loop:
That's usually perfectly normal as the app is waiting for user input. If you see something like the following you are likely dealing with a deadlock:
The semaphore stops the thread from continuing until some other thread opens the semaphore again. You are dealing with a deadlock if two or more threads are stopped waiting for each other. If the main thread is involved the app will be frozen.
The third possibility I can think of is an infinite loop on the main thread:
Of course this one is pretty easy to spot :)
The darker entries in stack frames are from your own code. You can click on those entries to find the exact locations and use the debugger to inspect variables. The other entries will show you assembly.
If you could not find anything suspicious by pausing the debugger I would start to remove those parts of code bit by bit, trying to reproduce the problem each time. There are two possible results:
You remove some harmless looking code and suddenly it works as expected. You can then take a closer look at the code you removed, making it easier to figure the issue out.
You end up with a minimal project exhibiting the issue. This is now much easier to debug and reason about because there is nothing else distracting you from the problem. You also have a much higher probability of getting help from coworkers or here on Stack Overflow when your code sample is as small as possible.
A third attack vector is checking the View Debugger:
Are there any transparent views above the frozen view controller blocking user events?
Is user interaction enabled on the controls and views involved? Select a view and check the Object Inspector on the right-hand side:

Try to remove DispatchQueue.main.async or the A viewController won't get notified. It's interaction has been disabled because the segue
//DispatchQueue.main.async {
self.dismiss(animated: true, completion: {
print("here dismissing")
})
//}

Make sure to check if any NSDelayedPerforming methods are blocking the main thread (Foundation > NSRunloop). i.e. performSelector afterDelay...
In my case (Objective-C) I had to use cancelPreviousPerformRequestsWithTarget in the viewDidDisappear instance method of the ViewController.
[NSObject cancelPreviousPerformRequestsWithTarget:self];
I think the same applies when using NSTimer.scheduledTimerWithTimeInterval (Swift) without invalidating the timer in the proper life cycle method.

Related

dropdown array becomes empty for few cells after adding cells in tableview and scroll up

Initially when I tap of hierarchy button and parentLocationLevelTwoBtnAction at that time parentLocationNameArr is not empty but after adding few more cells and I scroll up parentLocationNameArr is empty
import UIKit
import DropDown
import ObjectMapper
//Stock Btn Cell Delegate
protocol AddStorageLocationMasterBtnCellDelegate : AnyObject {
func didPressButton(_ tag: Int)
func didPressHierachyButton(_ tag: Int)
func didPressHierachytext(_ tag: Int,sender:String)
func didPressParenttext(_ tag: Int,sender:String, id:String)
func didPressParentTwotext(_ tag: Int,sender:String, id:String)
}
class AddStorageLocationMasterTVCell: UITableViewCell {
#IBOutlet var parentLTextLHeight: NSLayoutConstraint!
#IBOutlet weak var bgView: UIView!
#IBOutlet weak var deleteBtn: UIButton!
#IBOutlet weak var storageLocationNameView: UIView!
#IBOutlet var warnDescriptionbtn: UIButton!
#IBOutlet weak var storageLocationNameTF: UITextField!
#IBOutlet var warnNamebtn: UIButton!
#IBOutlet weak var descriptionView: UIView!
#IBOutlet weak var descriptionTextView: UITextView!
#IBOutlet weak var hierachyView: UIView!
#IBOutlet weak var hierachyTF: UITextField!
#IBOutlet weak var hierachyBtn: UIButton!
#IBOutlet weak var parentLocationView: UIView!
#IBOutlet weak var parentLocationTF: UITextField!
#IBOutlet weak var parentBgView: UIView!
#IBOutlet weak var parentHeightConstant: NSLayoutConstraint!
#IBOutlet weak var parentLocationLevelOneBtn: UIButton!
#IBOutlet weak var parentLocationLevelTwoView: UIView!
#IBOutlet weak var parentLocationLevelTwoTF: UITextField!
#IBOutlet weak var parentLocationTextLabel: UILabel!
#IBOutlet weak var stackView: UIStackView!
#IBOutlet weak var stackViewHeight: NSLayoutConstraint!
#IBOutlet weak var parentLcationLabel: UILabel!
var cellDelegate: AddStorageLocationMasterBtnCellDelegate?
let dropDown = DropDown() //2
var selectedId = 0
var accountID = ""
var storageLocationArr = NSMutableArray()
var storageLocationLevelThreeArr = NSMutableArray()
var serviceVC = ServiceController()
var parentLocationDict = [String]()
var parentLocationId = [String]()
var parentLocationArr = [NSArray]()
var parentLocationNameArr = [String]()
var parentLocationNameIdsArr = [String]()
var parentLocationDetailsDict = NSMutableArray()
var parentLocationNameLevethreeArr = [String]()
var parentLocationNameLevethreeIdsArr = [String]()
var parentLocationDetailsLevethreeDict = NSMutableArray()
var levelValue = 0
var idLevelThree = ""
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
self.parentBgView.isHidden = true
self.parentHeightConstant.constant = 0
storageLocationNameView.layer.borderColor = UIColor.gray.cgColor
storageLocationNameView.layer.borderWidth = 0.5
storageLocationNameView.layer.cornerRadius = 3
storageLocationNameView.clipsToBounds = true
descriptionView.layer.borderColor = UIColor.gray.cgColor
descriptionView.layer.borderWidth = 0.5
descriptionView.layer.cornerRadius = 3
descriptionView.clipsToBounds = true
hierachyView.layer.borderColor = UIColor.gray.cgColor
hierachyView.layer.borderWidth = 0.5
hierachyView.layer.cornerRadius = 3
hierachyView.clipsToBounds = true
parentLocationView.layer.borderColor = UIColor.gray.cgColor
parentLocationView.layer.borderWidth = 0.5
parentLocationView.layer.cornerRadius = 3
parentLocationView.clipsToBounds = true
parentLocationLevelTwoView.layer.borderColor = UIColor.gray.cgColor
parentLocationLevelTwoView.layer.borderWidth = 0.5
parentLocationLevelTwoView.layer.cornerRadius = 3
parentLocationLevelTwoView.clipsToBounds = true
bgView.backgroundColor = .white
bgView.layer.cornerRadius = 5.0
bgView.layer.shadowColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)
bgView.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
bgView.layer.shadowRadius = 6.0
bgView.layer.shadowOpacity = 0.7
hierachyTF.text = "Level 1"
selectedId = 1
}
#IBOutlet var parentButton: UIButton!
// override func setSelected(_ selected: Bool, animated: Bool) {
// super.setSelected(selected, animated: animated)
//
// // Configure the view for the selected state
// }
#IBAction func deleteBtnAction(_ sender: UIButton) {
cellDelegate?.didPressButton(sender.tag)
}
var tagVal=Int()
#IBAction func hierachyBtnAction(_ sender: UIButton) {
let selectedTagHierachy = sender.tag
cellDelegate?.didPressHierachyButton(selectedTagHierachy)
dropDown.dataSource = ["Level 1","Level 2","Level 3"]//4
dropDown.anchorView = sender //5
dropDown.bottomOffset = CGPoint(x: 0, y: sender.frame.size.height) //6
dropDown.show() //7
dropDown.selectionAction = { (index: Int, item: String) in //8
// guard let _ = self else { return }
// sender.setTitle(item, for: .normal) //9
self.selectedId = index
self.hierachyTF.text = item
self.cellDelegate?.didPressHierachytext(selectedTagHierachy, sender: item)
print(self.levelValue)
if index == 0 {
self.parentBgView.isHidden = true
self.parentHeightConstant.constant = 0
}
else if index == 1{
self.levelValue = index+1
self.get_StorageLocationMaster_API_Call(level: index+1, tag: selectedTagHierachy)
self.parentBgView.isHidden = false
self.parentHeightConstant.constant = 120
self.parentLcationLabel.text = "Parent Location L1"
self.parentLocationLevelTwoView.isHidden = true
}
else if index == 2{
self.levelValue = index+1
self.get_StorageLocationMaster_API_Call(level: index+1, tag: selectedTagHierachy)
self.parentBgView.isHidden = false
self.parentHeightConstant.constant = 120
self.parentLcationLabel.text = "Parent Location L2 and L1"
self.parentLocationLevelTwoView.isHidden = false
}
}
}
#IBAction func parentLocationBtnAction(_ sender: UIButton) {
let selectedTagParentLocation = sender.tag
// cellDelegate?.didPressParenttext(<#T##tag: Int##Int#>, sender: sender, id: <#T##String#>)
dropDown.dataSource = parentLocationNameLevethreeArr//4
dropDown.anchorView = sender //5
dropDown.bottomOffset = CGPoint(x: 0, y: sender.frame.size.height) //6
dropDown.show() //7
dropDown.selectionAction = { (index: Int, item: String) in //8
// guard let _ = self else { return }
// sender.setTitle(item, for: .normal) //9
self.parentLocationLevelTwoTF.text = item
self.cellDelegate?.didPressParentTwotext(selectedTagParentLocation, sender: item, id:self.parentLocationNameLevethreeIdsArr[index] )
}
}
#IBAction func parentLocationLevelTwoBtnAction(_ sender: UIButton)
{
let selectedTagParentLocation = sender.tag
dropDown.dataSource = parentLocationNameArr//4
dropDown.anchorView = sender //5
dropDown.bottomOffset = CGPoint(x: 0, y: sender.frame.size.height) //6
dropDown.show() //7
dropDown.selectionAction = { (index: Int, item: String) in //8
// guard let _ = self else { return }
// sender.setTitle(item, for: .normal) //9
// if self?.parentLocationNameLevethreeArr.count ?? 0>0
// {
// self?.parentLocationLevelTwoTF.text = self?.parentLocationNameLevethreeArr[0]
// self?.cellDelegate?.didPressParentTwotext(sender.tag, sender: self?.parentLocationNameLevethreeArr[0] ?? "", id: self?.parentLocationNameLevethreeIdsArr[0] ?? "")
// }
self.parentLocationTF.text = item
self.idLevelThree = self.parentLocationNameIdsArr[index]
self.cellDelegate?.didPressParenttext(selectedTagParentLocation, sender: item, id: self.parentLocationNameIdsArr[index] )
print(self.levelValue)
if self.levelValue==3
{
self.get_StorageLocationByParentLocation_API_Call(level: 2, tag: selectedTagParentLocation)
}
}
}
// MARK: Get Storage Location Master API Call
func get_StorageLocationByParentLocation_API_Call(level:Int,tag:Int) {
let defaults = UserDefaults.standard
accountID = (defaults.string(forKey: "accountId") ?? "")
// let newString = parentLocation.replacingOccurrences(of: " ", with: "%20")
if idLevelThree != ""
{
let urlStr = Constants.BaseUrl + getAllStorageLocationByParentUrl + "\(2)/" + "\(idLevelThree)/" + accountID
serviceVC.requestGETURL(strURL: urlStr, success: {(result) in
let respVo:GetStorageLocationMasterRespVo = Mapper().map(JSON: result as! [String : Any])!
DispatchQueue.main.async { [self] in
let status = respVo.STATUS_CODE
let message = respVo.STATUS_MSG
if status == 200 {
if message == "SUCCESS" {
if respVo.result != nil {
if respVo.result!.count > 0 {
let resultObj:[String:Any]=result as? [String:Any] ?? [String:Any]()
let resultArr:NSMutableArray=resultObj["result"]as? NSMutableArray ?? NSMutableArray()
self.storageLocationLevelThreeArr = NSMutableArray()
self.storageLocationLevelThreeArr = resultArr
self.parentLocationNameLevethreeArr.removeAll()
self.parentLocationNameLevethreeIdsArr.removeAll()
for obj in self.storageLocationLevelThreeArr {
let sDict=obj as? NSDictionary
let isCanEd:Bool = sDict?.value(forKey: "canEdit") as? Bool ?? false
// sDict(sDict?[i] as AnyObject).value(forKey: "canEdit") as? Bool
if isCanEd == true {
let slocName = sDict?.value(forKey: "slocName") as? String ?? ""
let idsStr = sDict?.value(forKey: "_id") as? String ?? ""
self.parentLocationNameLevethreeIdsArr.append(idsStr)
self.parentLocationNameLevethreeArr.append(slocName)
print("level 2 : \(parentLocationNameLevethreeArr)")
}
}
if self.parentLocationNameLevethreeArr.count > 0 {
self.parentLocationLevelTwoTF.text = self.parentLocationNameLevethreeArr[0]
self.cellDelegate?.didPressParentTwotext(tag, sender: self.parentLocationNameLevethreeArr[0], id: self.parentLocationNameLevethreeIdsArr[0])
}
// else{
// self.parentLocationLevelTwoTF.text = ""
// }
self.parentLTextLHeight.constant=0
self.parentLocationTextLabel.isHidden=true
self.parentLocationTextLabel.text=""
}
else {
self.parentLTextLHeight.constant=40
self.parentLocationTextLabel.isHidden=false
self.parentLocationTextLabel.text="No parent storage location is created currently. Pls create a parent storage location before creating the storage location when use creates a storage location without a custom parent storage location"
self.parentLocationTextLabel.numberOfLines = 0
self.parentLocationTextLabel.lineBreakMode = .byWordWrapping
self.parentLocationLevelTwoTF.text = ""
self.parentLocationNameLevethreeArr=[String]()
self.parentLocationNameLevethreeIdsArr=[String]()
}
}
}
}
else {
// self.view.makeToast(message)
}
}
}) { (error) in
// self.view.makeToast("app.SomethingWentToWrongAlert".localize())
print("Oops, your connection seems off... Please try again later")
}
}
else
{
self.parentLTextLHeight.constant=40
self.parentLocationTextLabel.isHidden=false
self.parentLocationTextLabel.text="No level 2 storage location exists currently. Pls create a level 2 storage location before creating levele 3 storage location"
}
}
// MARK: Get AddressBook API Call
func get_StorageLocationMaster_API_Call(level:Int,tag:Int) {
let defaults = UserDefaults.standard
accountID = (defaults.string(forKey: "accountId") ?? "")
let urlStr = Constants.BaseUrl + getAllStorageLocationByHierachyLevelUrl + "\(1)/" + accountID
serviceVC.requestGETURL(strURL: urlStr, success: {(result) in
let respVo:GetStorageLocationMasterRespVo = Mapper().map(JSON: result as! [String : Any])!
DispatchQueue.main.async {
let status = respVo.STATUS_CODE
let message = respVo.STATUS_MSG
if status == 200 {
if message == "SUCCESS" {
if respVo.result != nil {
if respVo.result!.count > 0 {
let resultObj:[String:Any]=result as? [String:Any] ?? [String:Any]()
let resultArr:NSMutableArray=resultObj["result"]as? NSMutableArray ?? NSMutableArray()
print(resultArr)
self.storageLocationArr = NSMutableArray()
self.storageLocationArr = resultArr
if self.storageLocationArr.count==0
{
self.parentLTextLHeight.constant=40
self.parentLocationTextLabel.isHidden=false
}
else
{
self.parentLTextLHeight.constant=0
self.parentLocationTextLabel.isHidden=true
let ddict=self.storageLocationArr[0] as? NSDictionary
self.parentLocationNameArr = [String]()
self.parentLocationNameIdsArr = [String]()
for obj in self.storageLocationArr {
let sDict=obj as? NSDictionary
let isCanEd:Bool = sDict?.value(forKey: "canEdit") as? Bool ?? false
// sDict(sDict?[i] as AnyObject).value(forKey: "canEdit") as? Bool
if isCanEd == true {
let slocName = sDict?.value(forKey: "slocName") as? String ?? ""
let idsStr = sDict?.value(forKey: "_id") as? String ?? ""
self.parentLocationNameIdsArr.append(idsStr)
self.parentLocationNameArr.append(slocName)
print(self.parentLocationNameArr)
self.parentLocationDetailsDict.addObjects(from: sDict?.value(forKey: "parentLocationDetails") as? NSMutableArray as! [Any])
}
}
let parentLocationDetails=ddict?.value(forKey: "parentLocationDetails")as? NSArray
print(self.levelValue)
if self.levelValue==3
{
if self.parentLocationNameArr.count>0
{
self.idLevelThree = self.parentLocationNameIdsArr[0] ?? ""
self.parentLocationTF.text = self.parentLocationNameArr[0]
self.cellDelegate?.didPressParenttext(tag, sender: self.parentLocationNameArr[0], id: self.parentLocationNameIdsArr[0])
}
else{
self.parentLTextLHeight.constant=40
self.parentLocationTextLabel.isHidden=false
self.parentLocationTextLabel.text="No level 2 storage location exists currently. Pls create a level 2 storage location before creating levele 3 storage location"
}
// if self.parentLocationDetailsDict.count > 0
// {
self.get_StorageLocationByParentLocation_API_Call(level: 2, tag:tag)
print("parent level 2 :\(self.parentLocationNameLevethreeArr)")
// }
}
else
{
if self.parentLocationNameArr.count>0
{
self.parentLocationTF.text = self.parentLocationNameArr[0]
self.cellDelegate?.didPressParenttext(tag, sender: self.parentLocationNameArr[0], id: self.parentLocationNameIdsArr[0])
}
else{
self.parentLTextLHeight.constant=40
self.parentLocationTextLabel.isHidden=false
self.parentLocationTextLabel.text="No level 1 storage location exists currently. Pls create a level 1 storage location before creating levele 3 storage location"
}
}
}
}
else {
}
}
}
}
else {
// self.view.makeToast(message)
}
}
}) { (error) in
// self.view.makeToast("app.SomethingWentToWrongAlert".localize())
print("Oops, your connection seems off... Please try again later")
}
}
}
Thanks in advance🙏

Want to map pin with title from another view controller in google map sdk on button click

I have a detailviewcontroller in which i have an imageview, a textfield,a textview and save button on navigation bar. Now when i fill the details and click on the save button, it should mark a map pin on map in the first controller i.e Homeviewcontroller. dont know where i am wrong
my storyboard image:
Some code that i have tried..
My HomeViewcontroller.swift file:
import UIKit
import GoogleMaps
import CoreLocation
class HomeViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate{
var arrData = [[String:Any]]()
#IBOutlet weak var mapView: GMSMapView!
#IBOutlet weak var mapCenterPinImage: UIImageView!
#IBOutlet weak var tabBar: UITabBar!
let locationManager = CLLocationManager()
var zoom: Float = 15
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
mapView.delegate = self
mapView.settings.compassButton = true
tabBar.delegate = self
}
func pinMarker()
{
if self.arrData.count != 0
{
mapView.clear()
for item in self.arrData {
let data = item as NSDictionary
mapView.delegate = self
if let lat = data.value(forKey: "lati") as? Double, let lng = data.value(forKey: "longi") as? Double
{
let places: CLLocationCoordinate2D = CLLocationCoordinate2DMake(lat,lng)
let marker_places = GMSMarker(position: places)
marker_places.title = (data.value(forKey: "title") as! String)
marker_places.map = mapView
}
}
}
}
#IBAction func imgPickerBtn(_ sender: Any) {
if(UIImagePickerController .isSourceTypeAvailable(UIImagePickerControllerSourceType.camera))
{
let picker = UIImagePickerController()
picker.delegate = self
picker.allowsEditing = true
picker.sourceType = .camera
self.present(picker, animated: true, completion: nil)
}
else
{
let picker = UIImagePickerController()
picker.delegate = self
picker.allowsEditing = true
picker.sourceType = .photoLibrary
self.present(picker, animated: true, completion: nil)
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
tabBar.selectedItem = self.tabBar.items?.first
let data = Defaults[.userDataResult]
self.arrData = data as! [[String:Any]]
print(self.arrData)
self.pinMarker()
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let pickedImg = info[UIImagePickerControllerOriginalImage] as? UIImage {
let objDetailVC = self.storyboard?.instantiateViewController(withIdentifier: "DetailsViewController") as! DetailsViewController
self.dismiss(animated: false, completion: nil)
objDetailVC.transferedImage = pickedImg
self.navigationController?.pushViewController(objDetailVC, animated: true)
}
}
#IBAction func ZoomInBtn(_ sender: Any) {
zoom = zoom + 1
self.mapView.animate(toZoom: zoom)
}
#IBAction func zoomOutBtn(_ sender: Any) {
zoom = zoom - 1
self.mapView.animate(toZoom: zoom)
}
}
extension HomeViewController: UITabBarDelegate {
func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
//This method will be called when user changes tab.
if tabBar.selectedItem?.tag == 2 {
print("tag=2")
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ListTableViewController") as! ListTableViewController
self.navigationController?.pushViewController(vc, animated: false)
}
}
}
//MARK: CLLocationManager Delegate
extension HomeViewController: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
guard status == .authorizedWhenInUse else {
return
}
locationManager.startUpdatingLocation()
mapView.isMyLocationEnabled = true
mapView.settings.myLocationButton = true
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location: CLLocation = locations.last!
print("Location: \(location)")
let camera = GMSCameraPosition.camera(withLatitude: location.coordinate.latitude,
longitude: location.coordinate.longitude,
zoom: zoom)
if mapView.isHidden {
mapView.isHidden = false
mapView.camera = camera
} else {
mapView.animate(to: camera)
}
}
// Handle location manager errors.
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
locationManager.stopUpdatingLocation()
print("Error: \(error)")
}
}
my detailviewcontroller.swift file:
import UIKit
import GoogleMaps
import CoreLocation
class DetailsViewController: UIViewController{
var picker : UIDatePicker = UIDatePicker()
#IBOutlet weak var selectedDate: UIButton!
#IBOutlet weak var detailsVCImage: UIImageView!
#IBOutlet weak var geoAddressLabel: UILabel!
#IBOutlet weak var titleTF: UITextField!
#IBOutlet weak var notesTextView: UITextView!
var imgPath = String()
var imgname = String()
let locationManager = CLLocationManager()
var currentLatitude = Double()
var currentLongitude = Double()
var mapView:GMSMapView!
var transferedImage:UIImage!
override func viewDidLoad() {
super.viewDidLoad()
notesTextView.text = "Enter Notes here...."
notesTextView.textColor = .lightGray
notesTextView.returnKeyType = .done
detailsVCImage.image = transferedImage
hideKeyboardWhenTapped()
let paddingView = UIView(frame: CGRect(x: 0,y: 0,width: 15,height: self.titleTF.frame.height))
titleTF.leftView = paddingView
titleTF.leftViewMode = .always
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
dismiss(animated: true)
}
func currentDate() -> String {
let date = Date()
let formatter = DateFormatter()
formatter.dateFormat = "dd.MM.yyyy_HH:mm:ss"
let result = formatter.string(from: date)
return result
}
func saveImg(image: UIImage) {
let documentsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let iname = currentDate()
let fileName = "\(iname)"+".png"
let jpgData = UIImageJPEGRepresentation(detailsVCImage.image!, 1.0)
let fileurl = documentsDir.appendingPathComponent(fileName)
if !FileManager.default.fileExists(atPath: fileurl.path) {
do {
try jpgData?.write(to: fileurl)
print("Image Added Successfully")
print(fileurl)
imgname = fileName
let data = Defaults[.userDataResult]
print(data)
var userFinalArray = [[String:Any]]()
var userTempArray = [[String:Any]]()
if data.count != 0 {
userTempArray = data as! [[String:Any]]
var obj = [String:Any]()
obj["title"] = self.titleTF.text
obj["notes"] = self.notesTextView.text
obj["image"] = self.imgname
obj["date"] = Date().string(format: "dd.MM.yyyy")
obj["lati"] = currentLatitude
obj["longi"] = currentLongitude
userTempArray.append(obj)
}else {
userTempArray = data as! [[String:Any]]
var obj = [String:Any]()
obj["title"] = self.titleTF.text
obj["notes"] = self.notesTextView.text
obj["image"] = self.imgname
obj["date"] = Date().string(format: "dd.MM.yyyy")
obj["lati"] = currentLatitude
obj["longi"] = currentLongitude
userTempArray.append(obj)
}
userFinalArray = userTempArray
Defaults[.userDataResult] = userFinalArray
let dataArr = Defaults[.userDataResult]
print(dataArr)
} catch {
print("error saving file", error)
}
}
}
#IBAction func datePickerTapped(_ sender: Any) {
picker.datePickerMode = UIDatePickerMode.dateAndTime
picker.addTarget(self, action: #selector(dueDateChanged(sender:)), for: UIControlEvents.valueChanged)
// self.picker = UIDatePicker(frame:CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 85))
let pickerSize : CGSize = picker.sizeThatFits(CGSize.zero)
picker.frame = CGRect(x:0.0, y:442, width:pickerSize.width, height:85)
//width: 288
self.view.addSubview(picker)
}
#objc func dueDateChanged(sender:UIDatePicker){
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .short
dateFormatter.timeStyle = .short
selectedDate.setTitle(dateFormatter.string(from: sender.date), for: .normal)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
picker.removeFromSuperview()
}
#IBAction func saveDataTaopped(_ sender: Any) {
print("Store data in user Default")
self.navigationController?.popToRootViewController(animated: false)
saveImg(image: self.transferedImage)
}
func reverseGeocodeCoordinate(_ coordinate: CLLocationCoordinate2D) {
let geocoder = GMSGeocoder()
geocoder.reverseGeocodeCoordinate(coordinate) { response, error in
// self.geoAddressLabel.unlock()
guard let address = response?.firstResult(), let lines = address.lines else {
return
}
self.geoAddressLabel.text = lines.joined(separator: "\n")
}
}
#IBAction func getLocationAddress(_ sender: Any) {
// reverseGeocodeCoordinate(target)
}
}
extension DetailsViewController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func hideKeyboardWhenTapped () {
let tap:UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(DetailsViewController.dismissKeyboard))
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
func dismissKeyboard() {
view.endEditing(true)
}
}
extension DetailsViewController: GMSMapViewDelegate {
func mapView(_ mapView: GMSMapView, idleAt position: GMSCameraPosition) {
// reverseGeocodeCoordinate(position.target)
}
// func mapView(_ mapView: GMSMapView, willMove gesture: Bool) {
// geoAddressLabel.lock()
//
// if (gesture) {
// mapCenterPinImage.fadeIn(0.25)
// mapView.selectedMarker = nil
// }
// }
}
extension DetailsViewController: UITextViewDelegate {
func textViewDidBeginEditing(_ textView: UITextView) {
if textView.text == "Enter Notes here...." {
textView.text = ""
textView.textColor = .black
}
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if text == "\n" {
textView.resignFirstResponder()
}
return true
}
func textViewDidEndEditing(_ textView: UITextView) {
if textView.text == "" {
textView.text = "Enter Notes here...."
textView.textColor = .lightGray
}
}
}
extension DetailsViewController: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
guard status == .authorizedWhenInUse else {
return
}
locationManager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location: CLLocation = locations.last!
print("Location: \(location)")
currentLatitude = location.coordinate.latitude
currentLongitude = location.coordinate.longitude
print(currentLongitude)
print(currentLatitude)
}
// Handle location manager errors.
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
locationManager.stopUpdatingLocation()
print("Error: \(error)")
}
}
extension Date {
func string(format: String) -> String {
let formatter = DateFormatter()
formatter.dateFormat = "dd.MM.yyyy"
return formatter.string(from: self)
}
}

Swift 4- App crashes on button press that starts segue

I am programming an application and it is supposed to go to another view controller on a button press but instead it crashes when I run it. The editor shows this: and with editor breakpointing on it shows this: but there is no error in the console. Here is the code for the viewcontroller that does the segue:
//
// DoTodayViewController.swift
// Paley Foundation: Starfish Support
//
// Created by Sa'ar Lipshitz on 10/28/17.
//
import UIKit
class DoTodayViewController: UIViewController {
#IBOutlet weak var navItem: UINavigationItem!
#IBOutlet weak var getBtn: UIButton!
#IBOutlet weak var suggestBtn: UIButton!
var name = "Sa'ar"
override func viewDidLoad() {
super.viewDidLoad()
getBtn.layer.cornerRadius = 8
getBtn.clipsToBounds = true
suggestBtn.layer.cornerRadius = 8
suggestBtn.clipsToBounds = true
navItem.prompt = "What would you like to do today, "+name+"?"
}
#IBAction func suggest(_ sender: Any) {
let vc = storyboard?.instantiateViewController(withIdentifier: "SuggestViewController") as! SuggestViewController
navigationController?.pushViewController(vc, animated: true)
}
//This crashes my app:
#IBAction func get(_ sender: Any) {
let vc = storyboard?.instantiateViewController(withIdentifier: "AccessViewController") as! AccessViewController
navigationController?.pushViewController(vc, animated: true)
}
}
and here is my code for the viewcontroller that gets opened:
//
// AccessViewController.swift
// Paley Foundation: Starfish Support
//
// Created by Sa'ar Lipshitz on 10/29/17.
//
import UIKit
import Firebase
import Material
class AccessViewController: UIViewController {
var adviceRef: DatabaseReference!
var advice: [[String: Any]] = []
var i = 0
var card: Card!
var loadingLbl: UILabel!
var panGesture = UIPanGestureRecognizer()
var cardOrigPos: CGPoint!
override func viewDidLoad() {
super.viewDidLoad()
adviceRef = Database.database().reference().child("Advice")
var advDict: NSDictionary?
adviceRef.observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
advDict = value
print(advDict as Any)
for (_, adv) in advDict! {
self.advice.append(adv as! [String : Any])
}
print(self.advice)
self.showNextCard()
}) { (error) in
print(error.localizedDescription)
}
let swipeRec = UIPanGestureRecognizer(target: self, action: #selector(swipe(sender:)))
card.isUserInteractionEnabled = true
card.addGestureRecognizer(swipeRec)
}
#objc func swipe(sender: UIPanGestureRecognizer) {
let translation = sender.translation(in: view)
let velocity = sender.velocity(in: view)
let direction = velocity
print("Translation: \(translation)")
if sender.state == .began {
cardOrigPos = card.center
} else if sender.state == .changed {
card.center = CGPoint(x: cardOrigPos.x+translation.x, y: cardOrigPos.y+translation.y)
} else if sender.state == .ended {
if velocity.y == 0 && velocity.x == 0 {
UIView.animate(withDuration: 0.3, animations: {
self.card.center = self.view.center
})
} else {
UIView.animate(withDuration: 0.3, animations: {
self.card.center = CGPoint(x: self.cardOrigPos.x+direction.x*5, y: self.cardOrigPos.y+direction.y)
})
self.showNextCard()
}
}
}
func showNextCard() {
if advice.count >= 0 {
let adv = advice[i]
setCard(adv["username"] as? String, adv["title"] as! String, adv["desc"] as! String, image: adv["image"] as? UIImage)
i += 1
if i >= advice.count {
i = 0
}
}
}
func setCard(_ username: String?, _ title: String, _ desc: String, image: UIImage?) {
let toolbar = setToolbar(username ?? "", title)
card = Card()
card.toolbar = toolbar
card.toolbarEdgeInsetsPreset = .square3
card.toolbarEdgeInsets.bottom = 0
card.toolbarEdgeInsets.right = 8
card.contentView = setContentView(content: desc)
card.contentViewEdgeInsetsPreset = .wideRectangle3
card.layer.borderWidth = 1.0
card.layer.borderColor = UIColor.black.cgColor
card.layer.cornerRadius = 2
view.layout(card).horizontally(left: 20, right: 20).center()
}
func setToolbar(_ username: String, _ title: String) -> Toolbar {
let toolbar = Toolbar(rightViews: [setMoreBtn()])
toolbar.title = title
toolbar.detail = username
toolbar.detailLabel.textColor = Color.grey.base
return toolbar
}
func setMoreBtn() -> IconButton {
let moreBtn = IconButton(image: Icon.cm.moreVertical, tintColor: Color.grey.base)
return moreBtn
}
func setContentView(content: String) -> UILabel {
let contentView = UILabel()
contentView.numberOfLines = 0
contentView.text = content
contentView.font = RobotoFont.regular(with: 14)
return contentView
}
}
When I tried using print statements to debug, the one in the DoTodayViewController.get(_ sender: Any) method ran but not the one in AccessViewController.viewDidLoad()
Make sure you changed the class of the view controller object in the storyboard to AccessViewController and that the Storyboard ID is correctly spelled. You may be encountering a nil when trying to force unwrap storyboard?.instantiateViewController(withIdentifier: "AccessViewController") as! AccessViewController. Try using if let wherever an optional needs to be unwrapped to handle the scenario of it being nil.

Remove the UIView at Runtime and Automatically Correct the UI

I have a UIViewController. I have made a MyProfile section. Now what i want to do is that if a person has only one picture then the 4 images section (which is a uiview) disappear and my UI (AboutLabel and TextSection comes up) will set according to that
Please see this picture: https://www.dropbox.com/s/gwokb8ge4pu5cw3/MyProfile.png?dl=0
class MyProfileViewController: UIViewController , UIImagePickerControllerDelegate{
#IBOutlet weak var sidebarButton: UIBarButtonItem!
#IBOutlet weak var profilePic: UIImageView!
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var ageLabel: UILabel!
#IBOutlet weak var totalPicView: UIView!
#IBOutlet weak var aboutMeLabel: UITextView!
var imagesArray = [UIImageView]()
var tag: Int?
var check = false
var myUserInfo: UsersInformation!
var age: Int?
override func viewDidLoad() {
super.viewDidLoad()
if revealViewController() != nil
{
// revealViewController().rearViewRevealWidth = 62
sidebarButton.target = revealViewController()
sidebarButton.action = #selector(SWRevealViewController.revealToggle(_:))
//revealViewController().rightViewRevealWidth = 150
//rightReveal.target = revealViewController()
//rightReveal.action = "rightRevealToggle:"
view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
if NSUserDefaults.standardUserDefaults().valueForKey(KEY_UID) != nil
{
let uid = DataService.ds.currentUserID
DataService.ds.currentUserRef.observeEventType(.Value, withBlock: { (snapshot) in
if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot]
{
if let userDictionary = snapshot.value as? Dictionary<String , AnyObject>
{
print("ProfileData")
self.myUserInfo = UsersInformation(id:uid, userInfo: userDictionary)
}
}
/*SavingDataFUnction*/
self.setProfileData()
})
}
}
func setProfileData()
{
age = giveMeAge()
let width = view.frame.width
let height = view.frame.height
print("w:\(width) ; h \(height)")
/*Basic Information*/
self.nameLabel.text = myUserInfo.uName
self.ageLabel.text = "Age: " + String(age!)
self.aboutMeLabel.text = myUserInfo.about
if myUserInfo.imageUrl[0] == noImageUrl
{
profilePic.image = UIImage(named: "Profile")
/*Hide totalPicView and Adjust aboutLabel and TextView*/
//totalPicView.viewWithTag(101)?.hidden = true
//totalPicView.frame.size.height = 0
}
else if myUserInfo.imageUrl.count >= 1
{
/*FirstPic is Profile Pic*/
let profile = myUserInfo.imageUrl[0]
profilePic.kf_setImageWithURL(NSURL(string: profile))
for i in 0 ... 3
{
let url = self.myUserInfo.imageUrl[i]
let imgOne = UIImageView(frame: CGRectMake(89.5 * CGFloat(i), 0, 89.5, totalPicView.frame.height))
imgOne.kf_setImageWithURL(NSURL(string: url))
imgOne.tag = 11 + i
imagesArray.append(imgOne)
self.totalPicView.addSubview(imgOne)
}
for image: UIImageView in imagesArray
{
image.userInteractionEnabled = true
image.clipsToBounds = true
let tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.setImage))
image.addGestureRecognizer(tapGesture)
}
}
}
func setImage(gesture: UITapGestureRecognizer) {
print(gesture.view?.tag)
tag = gesture.view?.tag
performSegueWithIdentifier("showImages", sender: self)
//presentViewController(imagePicker, animated: true, completion: nil)
}
func setMyUI(imageView: UIImageView)
{
aboutMeLabel.layer.borderColor = UIColor.blackColor().CGColor
aboutMeLabel.layer.cornerRadius = 5
aboutMeLabel.layer.borderWidth = 1
}
func giveMeAge() -> Int
{
let dob = myUserInfo.dob
let todaysDate = NSDate() //dateFromString("2015-02-04 23:29:28", format: "yyyy-MM-dd HH:mm:ss")
let dateFormater = NSDateFormatter()
dateFormater.dateFormat = "MM/dd/yyyy"
let currentDate = dateFormater.dateFromString(dateFormater.stringFromDate(todaysDate))
let myDob = dateFormater.dateFromString(dob)
let calendar: NSCalendar = NSCalendar.currentCalendar()
let age = calendar.components(.Year, fromDate: myDob! , toDate: currentDate!, options: [])
return age.year
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if segue.identifier == "showImages"
{
let dest = segue.destinationViewController as! ProfileImages
dest.arrarayOfImages = imagesArray
dest.tag = tag
dest.uname = myUserInfo.uName
dest.myage = age
}
}
}
Ok if I understand correctly you want to remove the UIView section with the 4 UIImageViews if the user has just one/no picture/s. Why not try with an if statement in your viewDidLoad (Swift 3 syntax):
if(yourImageViewArray.count <= 1){
yourUIViewForImages.isHidden = true
}
Once your UIView yourUIViewForImages is hidden, your stack should adjust accordingly. Unless you have hardcoded CGRect values (x,y) for your About sections. It would really help to post your code as already mentioned in your comments section.

ViewController persist through segue

I don't know how to explain my problem that will show here is a video showing the problem(s) I am having: https://youtu.be/dfiwenMj6xc
As you can see the push segue back is sloppy. I want to keep the Alerts label in the top right with the correct data, and not have a flash. I also would like the image to go away and not have the jitter that is visible. Here is part of my code in my first view class:
class WeatherViewController: UIViewController, LocationServiceDelegate, UIViewControllerPreviewingDelegate{
var fromWarnignsViewController = false
var weatherAlerts: WeatherAlerts!
var locationFixAchieved : Bool = false
var locationStatus : NSString = "Not Started"
var userLocation : String!
var userLatitude : Double!
var userLongitude : Double!
var userTemperatureCelsius : Bool!
var hourlyWeather2: Hourly!
var weeklyyWeather2: Weekly!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated);
if (!fromWarnignsViewController){
let currentLocation = LocationService.sharedInstance.lastLocation
userLatitude = currentLocation?.coordinate.latitude
userLongitude = currentLocation?.coordinate.longitude
let defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()
userTemperatureCelsius = defaults.boolForKey("celsius")
self.warningsLabel.hidden = true
}
}
func getCurrentWeatherData() -> Void {
let baseURL = NSURL(string: "https://api.forecast.io/forecast/\(apiKey)/")
let forecastURL = NSURL(string: "\(userLocation)", relativeToURL:baseURL)
let sharedSession = NSURLSession.sharedSession()
let downloadTask: NSURLSessionDownloadTask = sharedSession.downloadTaskWithURL(forecastURL!, completionHandler: { (location: NSURL?, response: NSURLResponse?, error: NSError?) -> Void in
if (error == nil) {
let dataObject = NSData(contentsOfURL: location!)
let weatherDictionary = (try! NSJSONSerialization.JSONObjectWithData(dataObject!, options: [])) as! NSDictionary
let currentWeather = Current(weatherDictionary: weatherDictionary)
let weeklyWeather = Weekly(weatherDictionary: weatherDictionary)
self.hourlyWeather2 = Hourly(weatherDictionary: weatherDictionary)
self.weeklyyWeather2 = weeklyWeather
let hourlyWeather = self.hourlyWeather2
dispatch_async(dispatch_get_main_queue(), {
self.weatherAlerts = WeatherAlerts(weatherDictionary: weatherDictionary)
if(self.weatherAlerts.userAlert.count > 0){
self.warningsLabel.hidden = false;
let buttonTitle = String(self.weatherAlerts.userAlert.count) + " Alerts"
self.warningsLabel.setTitle(buttonTitle, forState: UIControlState.Normal)
self.warningsLabel.enabled = true
} else {
self.warningsLabel.hidden = true;
let buttonTitle = "0 Alerts"
self.warningsLabel.setTitle(buttonTitle, forState: UIControlState.Normal)
self.warningsLabel.enabled = false
}
});
}
})
downloadTask.resume()
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "warnings") {
let svc = segue.destinationViewController as! WarningsViewController;
svc.weatherAlerts = self.weatherAlerts
svc.userLocation = self.userLocation
svc.userLatitude = self.userLatitude
svc.userLongitude = self.userLongitude
svc.hourlyWeather2 = self.hourlyWeather2
svc.weeklyyWeather2 = self.weeklyyWeather2
svc.weatherViewController = self
}
}
func tracingLocation(currentLocation: CLLocation) {
// IF APPLICATION IS ACTIVE
if UIApplication.sharedApplication().applicationState == .Active {
self.userLatitude = currentLocation.coordinate.latitude;
self.userLongitude = currentLocation.coordinate.longitude;
activeLocationUpdate(currentLocation)
getCurrentWeatherData()
}
}
}
And here is the code in the alert view:
class WarningsViewController: UIViewController {
var weatherViewController: WeatherViewController!
var weatherAlerts: WeatherAlerts!
var userLocation : String!
var userLatitude : Double!
var userLongitude : Double!
var hourlyWeather2: Hourly!
var weeklyyWeather2: Weekly!
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
print(weatherAlerts.userAlert)
if (segue.identifier == "embed") {
let svc = segue.destinationViewController as! WarningTableViewController;
svc.weatherAlerts = self.weatherAlerts
} else if (segue.identifier == "back") {
let svc = segue.destinationViewController as! WeatherViewController;
svc.weatherAlerts = self.weatherAlerts
svc.userLocation = self.userLocation
svc.userLatitude = self.userLatitude
svc.userLongitude = self.userLongitude
svc.hourlyWeather2 = self.hourlyWeather2
svc.weeklyyWeather2 = self.weeklyyWeather2
svc.fromWarnignsViewController = true
}
}
}
It's a lot of code but I don't know how to condense. Any help would be greatlhy appreciated!

Resources