我的问题是我有两个viewControllers连接模态segue,如普通A ---> B,A有像textFields,开关,按钮和mapView这样的控件,我得到userLocation。 B目前只有一个按钮和一个mapView,但当我点击退出按钮时,它确实成功解除了viewController B并显示A只有控件被冻结,不能再点击任何东西了,我不知道为什么。有什么帮助吗?
B代码
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)
}
}
编辑1:ViewController代码。
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 {
}
}
}
答案 0 :(得分:16)
您是否尝试将应用程序与调试器暂停以检查堆栈帧?有时,这可以帮助您发现死锁或无限循环。您将在代码编辑器和调试器之间的栏中找到暂停按钮(如果隐藏调试器,则在底部):
查看Xcode窗口左侧Debug Navigator中的堆栈帧。你能看到任何可疑的东西吗?这是一个堆栈框架,表明应用程序在主运行循环中空闲:
当应用等待用户输入时,这通常是完全正常的。如果您看到类似以下的内容,则可能会遇到死锁:
信号量阻止线程继续,直到某个其他线程再次打开信号量。如果两个或多个线程停止等待,则处理死锁。如果涉及主线程,应用程序将被冻结。
我能想到的第三种可能性是主线程上的无限循环:
当然这个很容易被发现:) 堆栈帧中较暗的条目来自您自己的代码。您可以单击这些条目以查找确切位置,并使用调试器检查变量。其他条目将显示汇编。
如果通过暂停调试器找不到任何可疑的东西,我会开始逐位删除这些代码部分,每次尝试重现问题。有两种可能的结果:
答案 1 :(得分:2)
尝试删除DispatchQueue.main.async
或A viewController未获得通知。它已被禁用,因为segue
//DispatchQueue.main.async {
self.dismiss(animated: true, completion: {
print("here dismissing")
})
//}
答案 2 :(得分:1)
确保检查是否有任何NSDelayedPerforming方法阻塞主线程(Foundation> NSRunloop)。即performSelector afterDelay ...
在我的情况下( Objective-C )我不得不在ViewController的viewDidDisappear实例方法中使用cancelPreviousPerformRequestsWithTarget。
[NSObject cancelPreviousPerformRequestsWithTarget:self];
我认为在使用NSTimer.scheduledTimerWithTimeInterval( Swift )时,同样适用,而不会在正确的生命周期方法中使计时器失效。