Auth button is not visible in Fabric Digits Integration - swift

Hi I'm new to swift and currently I'm working on a project which was done before in swift 2.3 for both iPad and iPhone. My requirement is to use fabric digits framework as to sign up using the mobile number.I did everything as it is in the documentation but the pink color 'login with phone number' button is not appearing in my screen (UIViewController) for some reason. The code is bellow.
import Alamofire
import SwiftyJSON
import DigitsKit
class ViewController: UIViewController, UITextFieldDelegate {
var phoneNum : String?
let movement: CGFloat = 20.0
var phoneHeight: CGFloat = 0.0
var appURLs = AppURLs.sharedInstance
var loadingView: UIView!
var Id: Int!
#IBOutlet weak var username: UITextField!
#IBOutlet weak var activity: UIActivityIndicatorView!
#IBOutlet weak var password: UITextField!
#IBAction func signUpButton(sender: AnyObject) {
let storyboard = switchStoryboards()
let vc = storyboard.instantiateViewControllerWithIdentifier("SignUpViewController")
self.presentViewController(vc, animated: false, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
configureLoadingView()
phoneHeight = self.view.frame.height
UIApplication.sharedApplication().statusBarHidden = true
self.username.delegate = self
self.password.delegate = self
self.slideMenuController()?.removeLeftGestures()
let usernameImageView = UIImageView()
if isIphone() {
usernameImageView.frame = CGRect(x: 0, y: 0, width: 36, height: 20)
} else {
usernameImageView.frame = CGRect(x: 0, y: 0, width: 54, height: 30)
}
usernameImageView.image = UIImage(named: "Username")
view.addSubview(usernameImageView)
username.leftView = usernameImageView
username.leftViewMode = UITextFieldViewMode.Always
let passwordImageView = UIImageView()
if isIphone() {
passwordImageView.frame = CGRect(x: 0, y: 0, width: 36, height: 20)
} else {
passwordImageView.frame = CGRect(x: 0, y: 0, width: 54, height: 30)
}
passwordImageView.image = UIImage(named: "Password")
view.addSubview(passwordImageView)
password.leftView = passwordImageView
password.leftViewMode = UITextFieldViewMode.Always
print("Login view did load loaded")
let authButton = DGTAuthenticateButton(authenticationCompletion: { (session, error) in
if (session != nil) {
// TODO: associate the session userID with your user model
let message = "Phone number: \(session!.phoneNumber)"
let alertController = UIAlertController(title: "You are logged in!", message: message, preferredStyle: .Alert)
alertController.addAction(UIAlertAction(title: "Cancel", style: .Cancel, handler: .None))
self.presentViewController(alertController, animated: true, completion: .None)
} else {
NSLog("Authentication error: %#", error!.localizedDescription)
}
})
authButton?.center = self.view.center
self.view.addSubview(authButton!)
}
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.Portrait
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(true)
}
func configureLoadingView() {
loadingView = UIView(frame: CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height))
}
func loginAlerts(messages: String) {
self.activity.stopAnimating()
SwiftSpinner.show("Sign in Failed!", animated: false).addTapHandler({
SwiftSpinner.hide()
}, subtitle: messages)
}
func switchStoryboards() -> UIStoryboard {
switch UIDevice.currentDevice().userInterfaceIdiom {
case .Phone:
// It's an iPhone
return UIStoryboard(name: "Main", bundle: nil)
case .Pad:
return UIStoryboard(name: "StoryboardiPad", bundle: nil)
// It's an iPad
case .Unspecified:
return UIStoryboard(name: "Main", bundle: nil)
// Uh, oh! What could it be?
default:
return UIStoryboard(name: "Main", bundle: nil)
}
}
func isIphone() -> Bool {
switch UIDevice.currentDevice().userInterfaceIdiom {
case .Phone:
// It's an iPhone
return true
case .Pad:
return false
// It's an iPad
case .Unspecified:
return true
// Uh, oh! What could it be?
default:
return true
}
}
}

Okay in such instance all you have to do is to create a custom button in the relevant UI then all will works fine

Related

UIAlertController Already presenting (null)

I have an app where at first a map is shown with all companies close to my position. Main screen has a search button where I can click and filter results according to my specific needs
The connection between Mapa View Controller and Filtrar View Controller was built based on a custom protocol (according to https://medium.com/#jamesrochabrun/implementing-delegates-in-swift-step-by-step-d3211cbac3ef).
All the communication works fine and I'm able to filter and present companies that meet the criteria. My issue is when the filter returns nothing (there are no companies that meet the criteria). When that happen I wanted to present a UIAltert as an advice to the end user.
Alert is triggered but I get an error message "Attempt to present on which is already presenting (null)".
I tried one of the suggestions from What is the best way to check if a UIAlertController is already presenting?
if self.presentedViewController == nil {
// do your presentation of the UIAlertController
// ...
} else {
// either the Alert is already presented, or any other view controller
// is active (e.g. a PopOver)
// ...
let thePresentedVC : UIViewController? = self.presentedViewController as UIViewController?
if thePresentedVC != nil {
if let thePresentedVCAsAlertController : UIAlertController = thePresentedVC as? UIAlertController {
// nothing to do , AlertController already active
// ...
print("Alert not necessary, already on the screen !")
} else {
// there is another ViewController presented
// but it is not an UIAlertController, so do
// your UIAlertController-Presentation with
// this (presented) ViewController
// ...
thePresentedVC!.presentViewController(...)
print("Alert comes up via another presented VC, e.g. a PopOver")
}
}
}
I see "Alert comes up via another presented VC, e.g. a PopOver" printed but I don't know how to use thePresentedVC!.presentViewController(...).
I'm using XCode 11.2.1 and IOS 11.
My detailed code is
Alert Class
import UIKit
class Alerta {
var titulo : String
var mensagem : String
init(titulo: String, mensagem: String) {
self.titulo = titulo
self.mensagem = mensagem
}
func getAlerta() -> UIAlertController {
let alerta = UIAlertController(title: titulo, message: mensagem, preferredStyle: .alert)
let acaoCancelar = UIAlertAction(title: "Ok", style: .cancel, handler: nil)
alerta.addAction(acaoCancelar)
return alerta
}
}
Mapa Class
import UIKit
import MapKit
import ProgressHUD
class MapaViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate, FiltroVCDelegate {
#IBOutlet weak var mapa: MKMapView!
var gerenciadorLocalizacao = CLLocationManager()
var anotacaoArray = [MinhaAnotacao]()
// var annotationSearch: [MinhaAnotacao] = [] // Filtered annotation
var anotacao = MinhaAnotacao()
var searchArr: [String] = []
var searching = false
var todasAnotacoes: [(objLat: CLLocationDegrees, objLong: CLLocationDegrees, objName: String, objDesc: String, objId: String, objTel1: String, objTel2: String, objEsp1: String, objEsp2: String, objEst: String, objCid: String)] = []
var clinicasR: [(objLat: CLLocationDegrees, objLong: CLLocationDegrees, objName: String, objDesc: String, objId: String, objTel1: String, objTel2: String, objEsp1: String, objEsp2: String, objEst: String, objCid: String)] = []
#IBOutlet weak var adicionarOutlet: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
mapa.register(MyAnnotationView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)
// Retrieving Logger user data and hidding "add" button if applicable
ProgressHUD.show("Carregando...")
var searching = false
// Map - User location
self.mapa.delegate = self
self.gerenciadorLocalizacao.delegate = self
self.gerenciadorLocalizacao.desiredAccuracy = kCLLocationAccuracyBest
self.gerenciadorLocalizacao.requestWhenInUseAuthorization()
self.gerenciadorLocalizacao.startUpdatingLocation()
ProgressHUD.dismiss()
}
// add annotations to the map
func addAnnotationsToMap() {
anotacaoArray = []
self.mapa.removeAnnotations(mapa.annotations)
if searching {
for oneObject in self.clinicasR {
let umaAnotacao = MinhaAnotacao()
let oneObjLoc: CLLocationCoordinate2D = CLLocationCoordinate2DMake(oneObject.objLat, oneObject.objLong)
umaAnotacao.coordinate = oneObjLoc
umaAnotacao.title = oneObject.objName
umaAnotacao.subtitle = oneObject.objDesc
umaAnotacao.identicadorMapa = oneObject.objId
umaAnotacao.telefone = oneObject.objTel1
umaAnotacao.telefone2 = oneObject.objTel2
umaAnotacao.especialidade1 = oneObject.objEsp1
umaAnotacao.especialidade2 = oneObject.objEsp2
umaAnotacao.estado = oneObject.objEst
umaAnotacao.cidade = oneObject.objCid
umaAnotacao.endereco = oneObject.objDesc
umaAnotacao.latitude = String(oneObject.objLat)
umaAnotacao.longitude = String(oneObject.objLong)
self.anotacaoArray.append(umaAnotacao)
}
} else {
for oneObject in self.todasAnotacoes {
let umaAnotacao = MinhaAnotacao()
let oneObjLoc: CLLocationCoordinate2D = CLLocationCoordinate2DMake(oneObject.objLat, oneObject.objLong)
umaAnotacao.coordinate = oneObjLoc
umaAnotacao.title = oneObject.objName
umaAnotacao.subtitle = oneObject.objDesc
umaAnotacao.identicadorMapa = oneObject.objId
umaAnotacao.telefone = oneObject.objTel1
umaAnotacao.telefone2 = oneObject.objTel2
umaAnotacao.especialidade1 = oneObject.objEsp1
umaAnotacao.especialidade2 = oneObject.objEsp2
umaAnotacao.estado = oneObject.objEst
umaAnotacao.cidade = oneObject.objCid
umaAnotacao.endereco = oneObject.objDesc
umaAnotacao.latitude = String(oneObject.objLat)
umaAnotacao.longitude = String(oneObject.objLong)
self.anotacaoArray.append(umaAnotacao)
}
}
self.mapa.addAnnotations(self.anotacaoArray)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "clinicaDetailsSegue" {
let clinicasDetailsViewController = segue.destination as! ClinicasDetailsViewController
clinicasDetailsViewController.identificador = self.anotacao.identicadorMapa
} else if segue.identifier == "searchSegue" {
if let nav = segue.destination as? UINavigationController, let filterVC = nav.topViewController as? FiltrarViewController {
filterVC.delegate = self
}
}
}
func search(searchAnnotation: [MinhaAnotacao], searchArr: [String]) -> [MinhaAnotacao] {
var searchArr = searchArr
// base case - no more searches - return clinics found
if searchArr.count == 0 {
return searchAnnotation
}
// itterative case - search clinic with next search term and pass results to next search
let foundAnnotation = searchAnnotation.filter { item in
(item.title!.lowercased() as AnyObject).contains(searchArr[0]) ||
item.especialidade1.lowercased().contains(searchArr[0]) ||
item.especialidade2.lowercased().contains(searchArr[0]) ||
item.cidade.lowercased().contains(searchArr[0]) ||
item.estado.lowercased().contains(searchArr[0]) ||
item.latitude.contains(searchArr[0]) || item.longitude.contains(searchArr[0]) || item.endereco.contains(searchArr[0])
}
// remove completed search and call next search
searchArr.remove(at: 0)
return search(searchAnnotation: foundAnnotation, searchArr: searchArr)
}
// From Custom Protocol
func dadosEscolhidos(nomeClinicaFiltro: String, estadoClinicaFiltro: String, cidadeClinicaFiltro: String, especialidade1ClinicaFiltro: String, especialidade2ClinicaFiltro: String) {
searchArr = []
clinicasR = []
searchArr = ["\(nomeClinicaFiltro.lowercased())","\(estadoClinicaFiltro.lowercased())", "\(cidadeClinicaFiltro.lowercased())", "\(especialidade1ClinicaFiltro.lowercased())", "\(especialidade2ClinicaFiltro.lowercased())"]
searchArr = searchArr.filter({ $0 != ""})
let annotationSearch = search(searchAnnotation: anotacaoArray, searchArr: searchArr) // Filtered Clinicas
if annotationSearch.count > 0 {
for i in 0...annotationSearch.count - 1 {
self.clinicasR.append((objLat: Double(annotationSearch[i].latitude)!, objLong: Double(annotationSearch[i].longitude)!, objName: annotationSearch[i].title!, objDesc: annotationSearch[i].endereco, objId: annotationSearch[i].identicadorMapa, objTel1: annotationSearch[i].telefone, objTel2: annotationSearch[i].telefone2, objEsp1: annotationSearch[i].especialidade1, objEsp2: annotationSearch[i].especialidade2, objEst: annotationSearch[i].estado, objCid: annotationSearch[i].cidade))
}
searching = true
addAnnotationsToMap()
} else {
if self.presentedViewController == nil {
let alerta = Alerta(titulo: "Erro", mensagem: "Nenhuma clínica atende ao filtro definido")
self.present(alerta.getAlerta(), animated: true, completion: nil)
print( "e Aqui, chegou? \(annotationSearch.count)")
} else {
// either the Alert is already presented, or any other view controller
// is active (e.g. a PopOver)
// ...
let thePresentedVC : UIViewController? = self.presentedViewController as UIViewController?
if thePresentedVC != nil {
if let thePresentedVCAsAlertController : UIAlertController = thePresentedVC as? UIAlertController {
// nothing to do , AlertController already active
// ...
print("Alert not necessary, already on the screen !")
} else {
// there is another ViewController presented
// but it is not an UIAlertController, so do
// your UIAlertController-Presentation with
// this (presented) ViewController
// ...
//let alerta = Alerta(titulo: "Erro", mensagem: "Nenhuma clínica atende ao filtro definido")
//thePresentedVC!.presentedViewController(alerta)
print("Alert comes up via another presented VC, e.g. a PopOver")
}
}
}
}
}
}
Filtrar View Controller
import UIKit
import ProgressHUD
protocol FiltroVCDelegate: class {
func dadosEscolhidos(nomeClinicaFiltro: String, estadoClinicaFiltro: String, cidadeClinicaFiltro: String, especialidade1ClinicaFiltro: String, especialidade2ClinicaFiltro: String)
}
class FiltrarViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
weak var delegate: FiltroVCDelegate?
var nomeSelecionado = ""
var estadosJSON = [Estado]()
var cidades = [Cidade]()
var estado : Estado? // Selected State identifier
var cidade : Cidade? // Selected City identifier
var estadoSelecionado = "" // Selected State
var cidadeSelecionada = "" // Selected City
var especialidadesJSON = [Especialidade]()
var especialidades2 = [Especialidade2]()
var especialidade1 : Especialidade? // Selected Specialty1 identifier
var especialidade2 : Especialidade2? // Selected Specialty2 identifier
var especialidade1Selecionada = ""
var especialidade2Selecionada = ""
let fontName = "HelveticaNeue"
var searchArr = [String]()
#IBOutlet weak var nomeClinica: UITextField!
#IBOutlet weak var especialidadeLabel: UILabel!
#IBOutlet weak var estadoClinicaPicker: UIPickerView!
#IBOutlet weak var especialidade1Picker: UIPickerView!
#IBOutlet weak var especialidade2Picker: UIPickerView!
override func viewDidLoad() {
ProgressHUD.show("Carregando...")
readJsonEstados()
readJsonEspecialidades()
super.viewDidLoad()
nomeClinica.text = ""
especialidadeLabel.transform = CGAffineTransform(rotationAngle: -CGFloat.pi / 2)
ProgressHUD.dismiss()
}
#IBAction func aplicarFiltro(_ sender: Any) {
if nomeClinica.text == nil {
nomeClinica.text = ""
}
delegate?.dadosEscolhidos(nomeClinicaFiltro: nomeClinica.text!, estadoClinicaFiltro: estadoSelecionado, cidadeClinicaFiltro: cidadeSelecionada, especialidade1ClinicaFiltro: especialidade1Selecionada, especialidade2ClinicaFiltro: especialidade2Selecionada)
navigationController?.dismiss(animated: true)
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
especialidade1Picker.reloadComponent(0)
especialidade2Picker.reloadComponent(0)
estadoClinicaPicker.reloadAllComponents()
if pickerView == estadoClinicaPicker {
if component == 0 {
self.estado = self.estadosJSON[row]
self.cidades = self.estadosJSON[row].cidades
estadoClinicaPicker.reloadComponent(1)
estadoClinicaPicker.selectRow(0, inComponent: 1, animated: true)
} else {
self.cidade = self.cidades[row]
estadoClinicaPicker.reloadAllComponents()
}
} else if pickerView == especialidade1Picker {
self.especialidade1 = self.especialidadesJSON[row]
self.especialidades2 = self.especialidadesJSON[row].especialidade2
especialidade1Picker.reloadComponent(0)
especialidade2Picker.reloadComponent(0)
especialidade2Picker.selectRow(0, inComponent: 0, animated: true)
} else if pickerView == especialidade2Picker {
self.especialidade2 = self.especialidades2[row]
especialidade1Picker.reloadComponent(0)
especialidade2Picker.reloadComponent(0)
}
let estadoIndiceSelecionado = estadoClinicaPicker.selectedRow(inComponent: 0)
let cidadeIndiceSelecionada = estadoClinicaPicker.selectedRow(inComponent: 1)
let especialidade1IndiceSelecionado = especialidade1Picker.selectedRow(inComponent: 0)
let especialidade2IndiceSelecionado = especialidade2Picker.selectedRow(inComponent: 0)
if estadoIndiceSelecionado >= 0 {
if cidadeIndiceSelecionada >= 0 {
estadoSelecionado = estadosJSON[estadoIndiceSelecionado].nome
cidadeSelecionada = cidades[cidadeIndiceSelecionada].nome
}
}
if especialidade1IndiceSelecionado >= 0 {
if especialidade2IndiceSelecionado >= 0 {
especialidade1Selecionada = especialidadesJSON[especialidade1IndiceSelecionado].nome
especialidade2Selecionada = especialidadesJSON[especialidade1IndiceSelecionado].especialidade2[especialidade2IndiceSelecionado].nome
}
}
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
if pickerView == estadoClinicaPicker {
return 2
} else if pickerView == especialidade1Picker {
return 1
} else if pickerView == especialidade2Picker {
return 1
}
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView == estadoClinicaPicker {
if component == 0 {
return estadosJSON.count
} else {
return cidades.count
}
} else if pickerView == especialidade1Picker {
return self.especialidadesJSON.count
} else if pickerView == especialidade2Picker {
return especialidades2.count
}
return 1
}
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
var rowTitle = ""
let pickerLabel = UILabel()
pickerLabel.textColor = UIColor.black
if pickerView == estadoClinicaPicker {
if component == 0 {
rowTitle = estadosJSON[row].nome
} else {
rowTitle = cidades[row].nome
}
} else if pickerView == especialidade1Picker {
rowTitle = especialidadesJSON[row].nome
} else if pickerView == especialidade2Picker {
rowTitle = especialidades2[row].nome
}
pickerLabel.text = rowTitle
pickerLabel.font = UIFont(name: fontName, size: 16.0)
pickerLabel.textAlignment = .center
return pickerLabel
}
func pickerView(_ pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat {
if pickerView == estadoClinicaPicker {
if component == 0 {
return 50
} else {
return 300
}
}
return 300
}
#IBAction func cancel(_ sender: Any) {
navigationController?.dismiss(animated: true)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
view.endEditing(true)
}
func readJsonEstados() {
let url = Bundle.main.url(forResource: "EstadosECidades", withExtension: "json")!
do {
let data = try Data(contentsOf: url)
let jsonResult = try JSONDecoder().decode(RootState.self, from: data)
//handles the array of countries on your json file.
self.estadosJSON = jsonResult.estado
self.cidades = self.estadosJSON.first!.cidades
} catch {
let alerta = Alerta(titulo: "Erro ao Carregar", mensagem: "Erro ao carregar Estados e Cidades. Por favor reinicie o app")
self.present(alerta.getAlerta(), animated: true, completion: nil)
}
}
func readJsonEspecialidades() {
let url = Bundle.main.url(forResource: "Especialidades", withExtension: "json")!
do {
let data = try Data(contentsOf: url)
let jsonResult = try JSONDecoder().decode(RootEsp.self, from: data)
//handles the array of specialties on your json file.
self.especialidadesJSON = jsonResult.especialidade
self.especialidades2 = self.especialidadesJSON.first!.especialidade2
} catch {
let alerta = Alerta(titulo: "Erro ao Carregar", mensagem: "Erro ao carregar Especialidades. Por favor reinicie o app")
self.present(alerta.getAlerta(), animated: true, completion: nil)
}
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}
Thanks
EDIT
Link to the project https://github.com/afernandes0001/UIAlertController.
You just need to click Log in (no validation is done), go to main screen, Map, Click Search and Apply - There is no need to add any data as I have made data static.
import UIKit
class ViewController: UIViewController {
let button = UIButton(type: .system)
override func viewDidLoad() {
super.viewDidLoad()
button.backgroundColor = .black
button.setTitle("Alert", for: .normal)
button.setTitleColor(.white, for: .normal)
button.addTarget(self, action: #selector(handleAlert), for: .touchUpInside)
button.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(button)
button.heightAnchor.constraint(equalToConstant: 50).isActive = true
button.widthAnchor.constraint(equalToConstant: 100).isActive = true
button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
// Do any additional setup after loading the view.
}
#objc fileprivate func handleAlert() {
OperationQueue.main.addOperation {
showAlert(titulo: "YourTilte", mensagem: "YourMessage", vc: self)
print("On main thread: \(Thread.current.isMainThread)")
}
}
extension UIViewController {
func showAlert(titulo: String, mensagem: String, vc: UIViewController) {
let alerta = UIAlertController(title: titulo, message: mensagem, preferredStyle: .alert)
let acaoCancelar = UIAlertAction(title: "Ok", style: .cancel, handler: nil)
alerta.addAction(acaoCancelar)
vc.present(alerta, animated: true)
}
}
it work :)
Try passing in the VC to your Alert class and presenting from there.
class Alert {
class func show(titulo: String, mensagem: String, vc: UIViewController) {
let alerta = UIAlertController(title: titulo, message: mensagem, preferredStyle: .alert)
let acaoCancelar = UIAlertAction(title: "Ok", style: .cancel, handler: nil)
alerta.addAction(acaoCancelar)
//if more than one VC is presenting, or the same one is presenting twice, this might at least tell you which one (assuming it has a title) or when (if the same one is presenting twice)
print("\(vc.title) is presenting alert")
vc.present(alerta, animated: true)
}
}
class ViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
Alert.show(titulo: "title", mensagem: "this is an alert", vc: self)
}
}
Call with Alert.show(titulo: "", mensagem: "", vc: self)
If Alert.show(arguments) doesn't work, you may have left the class keyword off of the function. If so, you'll need to create an instance first let alert = Alert() and use alert.show(arguments)
Or you could modify the func to use class properties and create an instance of the class then call instance.show(vc: self) since you already have properties for titulo and mensagem
Make it an extension of UIViewControiller like this:
extension UIViewController {
func showAlert(titulo: String, mensagem: String, vc: UIViewController) {
let alerta = UIAlertController(title: titulo, message: mensagem, preferredStyle: .alert)
let acaoCancelar = UIAlertAction(title: "Ok", style: .cancel, handler: nil)
alerta.addAction(acaoCancelar)
//if more than one VC is presenting, or the same one is presenting twice, this might at least tell you which one (assuming it has a title) or when (if the same one is presenting twice)
print("\(vc.title) is presenting alert")
vc.present(alerta, animated: true)
}}
after simply call wherever you want:
showAlert(titulo: "YourTitle", mensagem: "YourMessage", vc: self)

Value not display into multiple picker view

I'm making an app with a viewcontroller that displays two arrays in two different pickerview, an array has the values ​​saved within the application the others are retrieved with rest calls from a rest server. I tried to print the values ​​of the rest server and they are displayed but they are not displayed inside the uipickerview how can I solve this? what is due
class ModificaArticoloMagazzino: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate,UIPickerViewDelegate, UIPickerViewDataSource
{
private var TipologiaUIPicker: UIPickerView = UIPickerView()
private var MagazzinoModUIPicker: UIPickerView = UIPickerView()
private let valori = ["Carico","Scarico","Rimozione","Spostamento"]
private var SetValue:String="Carico"
private var filteredDataMagazzini: [MagazzinoStruct] = []
init() {
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
hideKeyboardWhenTappedAround()
self.view.backgroundColor = UIColor.white
//Caricamento Magazzini
//Caricamento Magazzini
DispatchQueue.main.async {
let mtemp = Magazzino(User: self.u)
mtemp.CaricaMagazzini(completion: { result in
self.filteredDataMagazzini=result
print("\n \n Magazzini caricati: \(result.count)")
//Configurazione Picker View Tipologia Preventivo
self.labelMagazzinoMod = UILabel(frame: CGRect(x: 20, y: 400, width: 120, height: 21))
self.labelMagazzinoMod.font = UIFont(name: "HelveticaNeue-Bold", size: 16.0)
self.labelMagazzinoMod.text = "Magazzino: "
self.view.addSubview(self.labelMagazzinoMod)
self.MagazzinoModUIPicker = UIPickerView(frame: CGRect(x: 150, y: 400, width: 200, height: 50))
self.MagazzinoModUIPicker.delegate = self
self.MagazzinoModUIPicker.dataSource = self
self.MagazzinoModUIPicker.backgroundColor = UIColor.white
self.view.addSubview(self.MagazzinoModUIPicker)
});
}
//Configurazione Picker View Tipologia Preventivo
labelTipologia = UILabel(frame: CGRect(x: 20, y: 270, width: 120, height: 21))
labelTipologia.font = UIFont(name: "HelveticaNeue-Bold", size: 16.0)
labelTipologia.text = "Tipologia: "
self.view.addSubview(labelTipologia)
self.TipologiaUIPicker = UIPickerView(frame: CGRect(x: (self.view.frame.width / 2) - 70, y: 270, width: 200, height: 50))
self.TipologiaUIPicker.delegate = self as UIPickerViewDelegate
self.TipologiaUIPicker.dataSource = self as UIPickerViewDataSource
self.TipologiaUIPicker.backgroundColor = UIColor.white
self.view.addSubview(TipologiaUIPicker)
//Quantita--> labelQuantitaMod e txtQuantita
labelQuantitaMod = UILabel(frame: CGRect(x: 20, y: 220, width: 60, height: 21))
labelQuantitaMod.font = UIFont(name: "HelveticaNeue-Bold", size: 16.0)
labelQuantitaMod.text = "Quantita: "
self.view.addSubview(labelQuantitaMod)
txtQuantita = UITextField(frame: CGRect(x: 120, y: 220, width: 200, height: 21));
txtQuantita.backgroundColor = UIColor.lightGray
txtQuantita.text = "1"
self.view.addSubview(txtQuantita)
}
//Funzione per aggiornare articolo in magazzino
#objc func AggiornaArticoloMagazzino(sender: UIButton!) {
let mtemp = Magazzino(SetArticolo: art, User: u)
if(SetValue=="Carico" || SetValue=="Scarico" || SetValue=="Rimozione"){
mtemp.Aggiorna(Quantita: Int(txtQuantita.text!)!, QuantitaPrecedente: art.Quantita!, IdMagazzino2: 0,Modalita:SetValue, completion: { result in
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1, execute: {
if(result==false){
let alertController = UIAlertController(title: "Errore", message: "\(self.SetValue) non riuscito ", preferredStyle: .alert)
let OKAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alertController.addAction(OKAction)
self.present(alertController, animated: true, completion: nil)
}
else{
if(self.SetValue=="Rimozione"){
self.previosScreen()
}
else if(self.SetValue=="Scarico"){
self.art.Quantita=self.art.Quantita!-Int(self.txtQuantita.text!)!
}
else if(self.SetValue=="Carico"){
self.art.Quantita=self.art.Quantita!+Int(self.txtQuantita.text!)!
}
self.labelQuantita.text = "Quantita attuale: \(String(describing: self.art.Quantita!))"
}
});
});
}
else{
mtemp.Aggiorna(Quantita: Int(txtQuantita.text!)!, QuantitaPrecedente: art.Quantita!, IdMagazzino2: 0,Modalita:SetValue, completion: { result in
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1, execute: {
if(result==false){
let alertController = UIAlertController(title: "Errore", message: "\(self.SetValue) non riuscito ", preferredStyle: .alert)
let OKAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alertController.addAction(OKAction)
self.present(alertController, animated: true, completion: nil)
}
});
});
}
}
//Questa funzione verifica quale selezione viene effettuata
func CheckSelezione(row: Int){
if(valori[row]=="Carico"){
txtQuantita.isEnabled = true
txtQuantita.isUserInteractionEnabled = true
}
else if(valori[row]=="Scarico"){
txtQuantita.isEnabled = true
txtQuantita.isUserInteractionEnabled = true
}
else if(valori[row]=="Rimozione"){
txtQuantita.isEnabled = false
txtQuantita.isUserInteractionEnabled = false
}
else{
txtQuantita.isEnabled = true
txtQuantita.isUserInteractionEnabled = true
}
SetValue=valori[row]
}
//Funzione per tornare alla schermata principale
func previosScreen(){
let returnView = TabBarViewController()
self.present(returnView, animated: true, completion: nil)
}
#objc func Return(sender: UIButton!) {
previosScreen()
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView == TipologiaUIPicker {
return valori.count
}
else{
return filteredDataMagazzini.count
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView == TipologiaUIPicker {
CheckSelezione(row: row)
return valori[row]
}
else{
print("\n Nome Magazzino\(filteredDataMagazzini[row].Nome!)")
return filteredDataMagazzini[row].Nome
}
}
}
First of all you need to check result in your API call like how you are getting the data from server. next step is you need to cast your data object into MagazzinoStruct object then you need to append that object into your filteredDataMagazzini array.
Now once you do that you need to reload your MagazzinoModUIPicker pickerview once you complete the first task.
And you need to reload MagazzinoModUIPicker in main queue because you are making an asynchronous call with API.

space between textView and keyboard

I am facing an issue, whenever I going to type in ALTextInputBar() there is a space between keyboard and ALTextInputBar() of 44 points. I don't know from where it is coming. Please have a look on code and image.
#IBOutlet weak var viewChatBox: UIView!
#IBOutlet weak var viewChatBoxBottomConstraint: NSLayoutConstraint!
let textInputBar = ALTextInputBar()
let keyboardObserver = ALKeyboardObservingView()
override func viewDidLoad() {
super.viewDidLoad()
IQKeyboardManager.shared.enable = false
IQKeyboardManager.shared.enableAutoToolbar = false
configureView()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChangeFrame), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if #available(iOS 11, *) {
// safe area constraints already set
}
else {
if (!(self.topLayoutConstraint != nil)) {
topLayoutConstraint = viewTopBar.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor)
self.topLayoutConstraint?.isActive = true
}
if (!(self.bottomLayoutConstraint != nil)) {
// bottomLayoutConstraint = viewChatBox.bottomAnchor.constraint(equalTo: bottomLayoutGuide.topAnchor)
self.bottomLayoutConstraint?.isActive = true
}
}
}
func configureInputBar () {
btnChat = UIButton(frame: CGRect(x: 0, y: 0, width: 36, height: 36))
keyboardObserver.isUserInteractionEnabled = false
textInputBar.showTextViewBorder = true
textInputBar.leftView = nil
textInputBar.rightView = btnChat
textInputBar.alwaysShowRightButton = true
textInputBar.delegate = self
textInputBar.textView.autocorrectionType = .yes
textInputBar.backgroundColor = UIColor(white: 0.95, alpha: 1)
textInputBar.keyboardObserver = keyboardObserver
viewChatBox.addSubview(textInputBar)
applyConstraintToChatBox()
self.view.layoutIfNeeded()
}
func applyConstraintToChatBox() {
textInputBar.translatesAutoresizingMaskIntoConstraints = false
viewChatBox.translatesAutoresizingMaskIntoConstraints = false
let views = ["textView": textInputBar]
let hConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[textView]-0-|", options: [], metrics: nil, views: views)
let vConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[textView]-0-|", options: [], metrics: nil, views: views)
viewChatBox.addConstraints(hConstraints)
viewChatBox.addConstraints(vConstraints)
}
override var inputAccessoryView: UIView? {
get {
return keyboardObserver
}
}
override var canBecomeFirstResponder: Bool {
return true
}
//MARK: - TEXTVIEW DELEGATE
func textView(textView: ALTextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
if (textInputBar.text.count == 0) {
return true
}
let newLength = textInputBar.text.count + text.count - range.length
return (newLength <= 144);
}
func inputBarDidChangeHeight(height: CGFloat) {
UIView.animate(withDuration: 0.3, delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.7, options: [.curveLinear], animations: { () -> Void in
self.view.layoutIfNeeded()
}, completion: nil)
}
// MARK: - KEYBOARDS
#objc func keyboardWillChangeFrame(notification: Notification) {
let endFrame = ((notification as NSNotification).userInfo![UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
viewChatBoxBottomConstraint.constant = view.bounds.height - endFrame.origin.y
print("CHAT BOX FRAME: \(viewChatBox.frame)")
print("TEXT FRAME FRAME: \(textInputBar.frame)")
self.view.layoutIfNeeded()
}
Late answer but may help someone. I had the same issue and found this below code in the documentation.
Only helpful for IQKeyboardManager users.
IQKeyboardManager
self.textField.keyboardDistanceFromTextField = 8; //This will modify default distance between textField and keyboard. For exact value, please manually check how far your textField from the bottom of the page. Mine was 8pt.

UIAlertController : it does not close in a controlleView that a UICollectionView

I created a class « Chargement »which allows to display an alert with a loading and to close it.
import Foundation
class Chargement {
var alert : UIAlertController;
var message : String = NSLocalizedString("PleaseWait", comment:"") ;
let loadingIndicator : UIActivityIndicatorView;
init(message : String?) {
if(message != nil){
self.message = message!;
}
self.alert = UIAlertController(title: nil, message: self.message, preferredStyle: UIAlertControllerStyle.alert)
self.loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 4, width: 40, height: 60))
}
func showLoading(view : UIViewController){
loadingIndicator.hidesWhenStopped = true
loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
loadingIndicator.startAnimating();
alert.view.addSubview(loadingIndicator)
view.present(alert, animated: true, completion: nil)
}
func closeLoading(){
alert.dismiss(animated: true, completion: nil)
}
}
When I use my class "Chargement" in a controllerView without UICollectionView, it works for example :
class ViewController : UIViewController{
let loadingView : Chargement = Chargement(message: nil);
override func viewDidLoad() {
super.viewDidLoad();
loadingView.showLoading(view: self);
}
#IBAction func btn_Action(_ sender: UIButton) {
self.loadingView.closeLoading();//it works
}
}
But when I use it in a controllerView with UICollectionView the alert display works but it doesn’t close.
class TTwoViewController: UIViewController,UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout {
let loadingView : Chargement = Chargement(message: nil);
#IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad();
loadingView.showLoading(view: self);
loadingData();
}
func loadingData() {
dataManager().getData(num: 1, completion: {
(data, messages) in
self.loadingView.closeLoading(); //it don't work
DispatchQueue.main.async(execute: {
self.collectionView.reloadData();
//self.loadingView.closeLoading(); //it don't work
})
})
}
}
If you just want to show an activity indicator, you can simplify the whole process by using NVActivityIndicatorView:
override func viewDidLoad() {
super.viewDidLoad();
let activityData = ActivityData()
NVActivityIndicatorPresenter.sharedInstance.startAnimating(activityData)
NVActivityIndicatorPresenter.sharedInstance.setMessage("Please Wait")
loadingData();
}
func loadingData() {
dataManager().getData(num: 1, completion: { (data, messages) in
DispatchQueue.main.async {
self.collectionView.reloadData()
NVActivityIndicatorPresenter.sharedInstance.stopAnimating()
}
})
}

How to make Images clickable in a UIPageViewController?

I am creating a UIPageController which swipes 4 pages. In each page there is an image from the array I created. Now I want to make each image from the swipe view clickable to present a new specific page. Each image from the swipe view leads to a different 10 levels (buttons) page.
the project file is here:
http://s000.tinyupload.com/?file_id=90198426971136689376
This is my code in ViewController:
private var pageViewController: UIPageViewController?
private let contentImages = ["Pack_1.png",
"Pack_2.png",
"Pack_3.png",
"nature_pic_4.png"];
override func viewDidLoad() {
super.viewDidLoad()
createPageViewController()
setupPageControl()
}
private func createPageViewController() {
let pageController = self.storyboard!.instantiateViewControllerWithIdentifier("PageController") as! UIPageViewController
pageController.dataSource = self
if contentImages.count > 0 {
let firstController = getItemController(0)!
let startingViewControllers: NSArray = [firstController]
pageController.setViewControllers(startingViewControllers as? [UIViewController], direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)
}
pageViewController = pageController
addChildViewController(pageViewController!)
self.view.addSubview(pageViewController!.view)
pageViewController!.didMoveToParentViewController(self)
}
private func setupPageControl() {
let appearance = UIPageControl.appearance()
appearance.pageIndicatorTintColor = UIColor.grayColor()
appearance.currentPageIndicatorTintColor = UIColor.whiteColor()
appearance.backgroundColor = UIColor.darkGrayColor()
}
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
let itemController = viewController as! PageItemController
if itemController.itemIndex > 0 {
return getItemController(itemController.itemIndex-1)
}
return nil
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
let itemController = viewController as! PageItemController
if itemController.itemIndex+1 < contentImages.count {
return getItemController(itemController.itemIndex+1)
}
return nil
}
private func getItemController(itemIndex: Int) -> PageItemController? {
if itemIndex < contentImages.count {
let pageItemController = self.storyboard!.instantiateViewControllerWithIdentifier("ItemController") as! PageItemController
pageItemController.itemIndex = itemIndex
pageItemController.imageName = contentImages[itemIndex]
return pageItemController
}
return nil
}
}
and this code is in my pageItemController:
var itemIndex: Int = 0
var imageName: String = "" {
didSet {
if let imageView = contentImageView {
imageView.image = UIImage(named: imageName)
}
}
}
#IBOutlet var contentImageView: UIImageView?
override func viewDidLoad() {
super.viewDidLoad()
contentImageView!.image = UIImage(named: imageName)
self.view.backgroundColor = UIColor (red: 100, green: 100, blue: 100, alpha: 0)
}
}
As per this version of the quesion:
"I'm creating a UIPageControllerView that shows 4 images. is there any way to make this images clickable? each image should present a dedicate page. this is my code in viewController:"
SOLUTION:
Use UIGestureRecognizer.
1) Click on your Main.Storyboard.
2) Select UIGestureRecognizer.
3) Drag it on your Image of choice.
3.5) Use Cmd+Alt+Enter to open the Assistant Editor
4) Create an IBAction by Ctrl-dragging from your UITapGestureRecogniser to the Assistant Editor.
5) Put this code in your ViewController.
class ViewController {
let itemIndex: Int!
func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool)
{
if (!completed)
{
return
}
self.pageControl.currentPageIndex = pageViewController.viewControllers!.first!.view.tag //Page Index
self.itemIndex = self.pageControl.currentPageIndex
}
#IBAction func presentDedicatedPage(sender: UIImageView) {
//pseudo-code here, for example:
switch self.itemIndex {
case 0:
// present these 10 levels
break
case 1:
//present these other 10 levels
break
case 2:
//present these other 10 levels
break
case 3:
//present these other 10 levels
break
}
}
On your ItemPageController:
var itemIndex:Int?
var imageName:String?
Add UITapGesture To ImageView.
override func viewDidLoad() {
super.viewDidLoad()
let tapGestureRecognizer = UITapGestureRecognizer(target:self, action:Selector("imageTapped:"))
targetImageView.userInteractionEnabled = true
targetImageView.addGestureRecognizer(tapGestureRecognizer)
targetImageView.image = UIImage(named: imageName!)
}
On its triggered method:
func imageTapped(img: AnyObject)
{
print(imageName)
print(itemIndex)
//Using a switch statement
let targetImageIndex = itemIndex! as Int
switch (targetImageIndex) {
case 0:
print("case 0")
break;
case 1:
print("case 1")
break;
case 2:
print("case 2")
break;
default:
break;
}
}