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")
})
//}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With