Use of unresolved identifier - ios

I am building a barcode scanner. the operations are simple
scan a barcode,
if the scanned barcode is in my firebase database perform func updateProductInfo() if the barcode is not in my firebase database perform func enterNewProduct().
The one problem that I am having now is how to define metadataObj so that it is accessible by all and any other function that I will define later. I have attempt to define it right below the ScanController class but I couldn't figure it out. My code is below
import UIKit
import AVFoundation
import Firebase
class ScanController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
var captureSession: AVCaptureSession?
var videoPreviewLayer: AVCaptureVideoPreviewLayer?
var qrCodeFrameView: UIView?
let itemDB = FIRDatabase.database().reference().child("Items")
let supportedCodeTypes = [AVMetadataObjectTypeUPCECode,
AVMetadataObjectTypeCode39Code,
AVMetadataObjectTypeCode39Mod43Code,
AVMetadataObjectTypeCode93Code,
AVMetadataObjectTypeCode128Code,
AVMetadataObjectTypeEAN8Code,
AVMetadataObjectTypeEAN13Code,
AVMetadataObjectTypeAztecCode,
AVMetadataObjectTypePDF417Code,
AVMetadataObjectTypeQRCode]
let messageLabel: UILabel = {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 40))
// label.center = CGPoint(x: 160, y: 285)
label.center = CGPoint(x: 160, y: 285)
label.textAlignment = .center
return label
}()
let productDescriptionTextField: UITextField = {
let tf = UITextField()
tf.placeholder = "Product Description"
tf.translatesAutoresizingMaskIntoConstraints = false
return tf
}()
let descriptionSeparatorView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(r: 220, g: 220, b: 220)
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let priceTextField: UITextField = {
let tf = UITextField()
tf.placeholder = "Price"
tf.translatesAutoresizingMaskIntoConstraints = false
return tf
}()
let priceSeparatorView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(r: 220, g: 220, b: 220)
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let productLocationTextField: UITextField = {
let tf = UITextField()
tf.placeholder = "Product Location"
tf.translatesAutoresizingMaskIntoConstraints = false
return tf
}()
let productImageView: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "XXXXXXX")
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.contentMode = .scaleAspectFill
return imageView
}()
let exitScanButton: UIButton = {
let button = UIButton(type: .system)
button.backgroundColor = UIColor(r: 80, g: 101, b: 161)
button.setTitle("Exit", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget( nil, action: #selector(exitScan), for:.touchUpInside)
return button
}()
let newProductEntry: UIView = {
let view = UIView()
view.backgroundColor = UIColor.white
view.translatesAutoresizingMaskIntoConstraints = false
view.layer.cornerRadius = 5
view.layer.masksToBounds = true
return view
}()
let productSummary: UIView = {
let view = UIView()
view.backgroundColor = UIColor.white
view.translatesAutoresizingMaskIntoConstraints = false
view.layer.cornerRadius = 5
view.layer.masksToBounds = true
return view
}()
let productDescriptionLabel: UILabel = {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 40))
// label.center = CGPoint(x: 160, y: 285)
label.center = CGPoint(x: 160, y: 285)
label.textAlignment = .center
return label
}()
let storeNameLabel: UILabel = {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 40))
// label.center = CGPoint(x: 160, y: 285)
label.center = CGPoint(x: 160, y: 285)
label.textAlignment = .center
return label
}()
let verifyProductInfoButton: UIButton = {
let button = UIButton(type: .system)
button.backgroundColor = UIColor(r: 80, g: 101, b: 161)
button.setTitle("Checked", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget( nil, action: #selector(verifyNewProduct), for:.touchUpInside)
return button
}()
let updateProductInfoButton: UIButton = {
let button = UIButton(type: .system)
button.backgroundColor = UIColor(r: 80, g: 101, b: 161)
button.setTitle("Update", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget( nil, action: #selector(updateProductInfo), for:.touchUpInside)
return button
}()
let enterNewProductButton: UIButton = {
let button = UIButton(type: .system)
button.backgroundColor = UIColor(r: 80, g: 101, b: 161)
button.setTitle("Enter", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget( nil, action: #selector(enterNewProduct), for:.touchUpInside)
return button
}()
func updateProductInfo() {
guard let price = priceTextField.text,
let location = productLocationTextField.text
else{
print("Please update price and product location")
return
}
}
func verifyNewProduct() {
// need to add a counter that counts how many people verified product information
self.dismiss(animated: true, completion: nil)
}
func enterNewProduct() {
let itemID = metadataObj.stringValue
guard let Description = productDescriptionTextField.text,
let price = priceTextField.text,
let location = productLocationTextField.text
else{
print("Fill basic product information")
return
}
let ref = FIRDatabase.database().reference(fromURL: "")
// creating an item child node
let values = ["Item Description": Description, "Image": price, "Location": location, "Price": price ]
let items = ref.child("Items").child(itemID!)
items.updateChildValues(values, withCompletionBlock: { (err, ref) in
if err != nil {
print(err)
return
}
})
self.dismiss(animated: true, completion: nil)
}
func exitScan() {
//Go back to ViewController
self.dismiss(animated: true, completion: nil)
}
func setupUpdateProductInfo() {
productSummary.addSubview(productDescriptionLabel)
productSummary.addSubview(storeNameLabel)
productSummary.addSubview(priceTextField)
productSummary.addSubview(productLocationTextField)
productSummary.addSubview(verifyProductInfoButton)
productSummary.addSubview(updateProductInfoButton)
productSummary.addSubview(productImageView)
// need x, y, width, height constraints for product image
productImageView.leftAnchor.constraint(equalTo: productSummary.leftAnchor, constant: 12).isActive = true
productImageView.topAnchor.constraint(equalTo: productSummary.topAnchor).isActive = true
productImageView.widthAnchor.constraint(equalTo: productSummary.widthAnchor, constant: 100).isActive = true
productImageView.heightAnchor.constraint(equalToConstant: 100).isActive = true
// need x, y, width, height constraints for store logo
storeNameLabel.leftAnchor.constraint(equalTo: productDescriptionLabel.leftAnchor, constant: 12).isActive = true
storeNameLabel.topAnchor.constraint(equalTo: productSummary.topAnchor).isActive = true
storeNameLabel.widthAnchor.constraint(equalTo: productSummary.widthAnchor).isActive = true
// need x, y, width, height constraints for description label
productDescriptionLabel.leftAnchor.constraint(equalTo: productImageView.leftAnchor, constant: 12).isActive = true
productDescriptionLabel.topAnchor.constraint(equalTo: productSummary.topAnchor).isActive = true
productDescriptionLabel.widthAnchor.constraint(equalTo: productSummary.widthAnchor).isActive = true
productDescriptionLabel.rightAnchor.constraint(equalTo: storeNameLabel.leftAnchor,constant: 12).isActive = true
// need x, y, width, height constraints for price textfield
priceTextField.leftAnchor.constraint(equalTo: productImageView.rightAnchor, constant: 12).isActive = true
priceTextField.topAnchor.constraint(equalTo: productDescriptionLabel.bottomAnchor).isActive = true
priceTextField.widthAnchor.constraint(equalToConstant: 50).isActive = true
// need x, y, width, height constraints for location textfield
productLocationTextField.leftAnchor.constraint(equalTo: priceTextField.rightAnchor, constant: 12).isActive = true
productLocationTextField.topAnchor.constraint(equalTo: productDescriptionLabel.bottomAnchor).isActive = true
productLocationTextField.widthAnchor.constraint(equalToConstant: 50).isActive = true
}
func setupNewProductEntry() {
newProductEntry.addSubview(productImageView)
newProductEntry.addSubview(productLocationTextField)
newProductEntry.addSubview(productDescriptionTextField)
newProductEntry.addSubview(priceTextField)
newProductEntry.addSubview(enterNewProductButton)
newProductEntry.addSubview(descriptionSeparatorView)
newProductEntry.addSubview(priceSeparatorView)
// need x, y, width, height constraints
newProductEntry.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
newProductEntry.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
newProductEntry.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -24).isActive = true
newProductEntry.heightAnchor.constraint(equalToConstant: 150).isActive = true
// need x, y, width, height constraints for name productDescriptionTextField
productDescriptionTextField.leftAnchor.constraint(equalTo: newProductEntry.leftAnchor, constant: 12).isActive = true
productDescriptionTextField.topAnchor.constraint(equalTo: newProductEntry.topAnchor).isActive = true
productDescriptionTextField.widthAnchor.constraint(equalTo: newProductEntry.widthAnchor).isActive = true
// need x, y, width, height constraints for description separator line
descriptionSeparatorView.leftAnchor.constraint(equalTo: newProductEntry.leftAnchor).isActive = true
descriptionSeparatorView.topAnchor.constraint(equalTo: productDescriptionTextField.bottomAnchor).isActive = true
descriptionSeparatorView.widthAnchor.constraint(equalTo: newProductEntry.widthAnchor).isActive = true
descriptionSeparatorView.heightAnchor.constraint(equalToConstant: 1).isActive = true
// need x, y, width, height constraints for name pricetextfield
priceTextField.leftAnchor.constraint(equalTo: newProductEntry.leftAnchor, constant: 12).isActive = true
priceTextField.topAnchor.constraint(equalTo: productDescriptionTextField.bottomAnchor).isActive = true
priceTextField.widthAnchor.constraint(equalTo: newProductEntry.widthAnchor).isActive = true
// need x, y, width, height constraints for price separator line
priceSeparatorView.leftAnchor.constraint(equalTo: newProductEntry.leftAnchor).isActive = true
priceSeparatorView.topAnchor.constraint(equalTo: priceTextField.bottomAnchor).isActive = true
priceSeparatorView.widthAnchor.constraint(equalTo: newProductEntry.widthAnchor).isActive = true
priceSeparatorView.heightAnchor.constraint(equalToConstant: 1).isActive = true
// need x, y, width, height constraints for name LocationTextField
productLocationTextField.leftAnchor.constraint(equalTo: newProductEntry.leftAnchor, constant: 12).isActive = true
productLocationTextField.topAnchor.constraint(equalTo: priceTextField.bottomAnchor).isActive = true
productLocationTextField.widthAnchor.constraint(equalTo: newProductEntry.widthAnchor).isActive = true
}
func setupenterNewProductButton(){
// need x, y, width, height constraints
enterNewProductButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
enterNewProductButton.topAnchor.constraint(equalTo: newProductEntry.bottomAnchor, constant: 12).isActive = true
enterNewProductButton.widthAnchor.constraint(equalTo: newProductEntry.widthAnchor).isActive = true
enterNewProductButton.heightAnchor.constraint(equalToConstant: (50)).isActive = true
}
func setupupdateProductInfoButton(){
// need x, y, width, height constraints
updateProductInfoButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
updateProductInfoButton.topAnchor.constraint(equalTo: productSummary.bottomAnchor, constant: 12).isActive = true
updateProductInfoButton.widthAnchor.constraint(equalTo: productSummary.widthAnchor).isActive = true
updateProductInfoButton.heightAnchor.constraint(equalToConstant: (50)).isActive = true
}
func setupverifyProductInfoButton(){
// need x, y, width, height constraints
verifyProductInfoButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
verifyProductInfoButton.topAnchor.constraint(equalTo: productSummary.bottomAnchor, constant: 12).isActive = true
verifyProductInfoButton.widthAnchor.constraint(equalTo: productSummary.widthAnchor).isActive = true
verifyProductInfoButton.heightAnchor.constraint(equalToConstant: (50)).isActive = true
verifyProductInfoButton.leftAnchor.constraint(equalTo: enterNewProductButton.rightAnchor).isActive = true
}
override func viewDidLoad() {
super.viewDidLoad()
//Get an instance of the AVCaptureDevice class a device object and provide the video as the media type parameter
let captureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
do {
// Get an instance of the AVCaptureDeviceInput class using the previous device object.
let input = try AVCaptureDeviceInput(device: captureDevice)
// Initialize the captureSession object.
captureSession = AVCaptureSession()
// Set the input device on the capture session.
captureSession?.addInput(input)
let captureMetadataOutput = AVCaptureMetadataOutput()
captureSession?.addOutput(captureMetadataOutput)
// Set delegate and use the default dispatch queue to execute the call back
captureMetadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
captureMetadataOutput.metadataObjectTypes = supportedCodeTypes
// Initialize the video preview layer and add it as a sublayer to the viewPreview view's layer.
videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
videoPreviewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
videoPreviewLayer?.frame = view.layer.bounds
view.layer.addSublayer(videoPreviewLayer!)
// Start video capture.
captureSession?.startRunning()
// Add the message label
self.view.addSubview(messageLabel)
self.view.addSubview(exitScanButton)
setupexitScanButton()
//initialize QR Code Frame to highlight the QR Code
qrCodeFrameView = UIView()
if let qrCodeFrameView = qrCodeFrameView {
qrCodeFrameView.layer.borderColor = UIColor.green.cgColor
qrCodeFrameView.layer.borderWidth = 2
view.addSubview(qrCodeFrameView)
}
} catch {
// If any error occurs, simply print it out and don't continue any more.
print(error)
return
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
// Check if the metadataObjects array is not nil and it contains at least one object.
if metadataObjects == nil || metadataObjects.count == 0 {
qrCodeFrameView?.frame = CGRect.zero
messageLabel.text = "No QR/barcode is detected"
return
}
//Get metadata object
let metadataObj = metadataObjects[0] as! AVMetadataMachineReadableCodeObject
let itemID = metadataObj.stringValue
if supportedCodeTypes.contains(metadataObj.type) {
//if the found metadata is equal to the QR code metadata then update the status label's text and set the the bounds
let barCodeObject = videoPreviewLayer?.transformedMetadataObject(for: metadataObj)
qrCodeFrameView?.frame = barCodeObject!.bounds
if metadataObj.stringValue != nil {
messageLabel.text = metadataObj.stringValue
//Searches firebase for existing barcode
let itemToSearchFor = metadataObj.stringValue
FIRDatabase.database().reference().child("Items").child(itemToSearchFor!).observeSingleEvent(of: .value, with:{(snap) in
print(snap)
}) } else {
setupNewProductEntry()
}
}
}
func setupexitScanButton() {
// need x, y, width, height constraints
exitScanButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
exitScanButton.topAnchor.constraint(equalTo: view.topAnchor, constant: 12).isActive = true
exitScanButton.widthAnchor.constraint(equalToConstant: 60).isActive = true
exitScanButton.heightAnchor.constraint(equalToConstant: (50)).isActive = true
}
}
My error is currently at let itemID = metadataObj.stringValue.

Define it at the top under qrcodeframeview to make it "global" in your class

Related

Swift - Subviews frame.maxY reading incorrectly

I have a basic sign up screen set up programmatically with the UI elements inside a view that is itself inside a scroll view.
The last UI element in the screen is a register button. I set up a keyboard notification observer with the Will Show and Will Hide notifications.
I am running this code on iPod touch 7th gen simulator.
My problem is when trying to read the maxY value of the sign up button and compare it to the keyboard minY it prints wrong numbers.
The keyboard is clearly blocking the register button which mean the button's maxY value will be greater the the keyboard minY value.
However the values printed shows that there is something wrong with the reading of the register button frame.
Here is my code:
import UIKit
class RegisterVC: UIViewController {
private let scrollView: UIScrollView = {
let scroll = UIScrollView()
scroll.clipsToBounds = true
scroll.isScrollEnabled = true
scroll.translatesAutoresizingMaskIntoConstraints = false
scroll.showsVerticalScrollIndicator = false
return scroll
}()
private let scrollInnerView: UIView = {
let innerView = UIView()
innerView.translatesAutoresizingMaskIntoConstraints = false
return innerView
}()
private let profilePic: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(systemName: "person.circle")
imageView.contentMode = .scaleAspectFit
imageView.tintColor = .gray
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
private let usernameField: UITextField = {
let field = UITextField()
field.autocapitalizationType = .none
field.autocorrectionType = .no
field.returnKeyType = .next
field.layer.cornerRadius = 12
field.layer.borderWidth = 1
field.layer.borderColor = UIColor.lightGray.cgColor
field.placeholder = "Username..."
field.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 5, height: 0))
field.leftViewMode = .always
field.backgroundColor = .white
field.keyboardType = .default
field.isHighlighted = false
field.textAlignment = .left
field.translatesAutoresizingMaskIntoConstraints = false
return field
}()
private let emailField: UITextField = {
let field = UITextField()
field.autocapitalizationType = .none
field.autocorrectionType = .no
field.returnKeyType = .next
field.layer.cornerRadius = 12
field.layer.borderWidth = 1
field.layer.borderColor = UIColor.lightGray.cgColor
field.placeholder = "Email Address..."
field.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 5, height: 0))
field.leftViewMode = .always
field.backgroundColor = .white
field.keyboardType = .default
field.textAlignment = .left
field.translatesAutoresizingMaskIntoConstraints = false
return field
}()
private let passwordField: UITextField = {
let field = UITextField()
field.autocapitalizationType = .none
field.autocorrectionType = .no
field.returnKeyType = .done
field.layer.cornerRadius = 12
field.layer.borderWidth = 1
field.layer.borderColor = UIColor.lightGray.cgColor
field.placeholder = "Password..."
field.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 5, height: 0))
field.leftViewMode = .always
field.backgroundColor = .white
field.isSecureTextEntry = true
field.textAlignment = .left
field.keyboardType = .default
field.translatesAutoresizingMaskIntoConstraints = false
return field
}()
private let registerButton: UIButton = {
let button = UIButton()
button.setTitle("Create Account", for: .normal)
button.backgroundColor = .systemGreen
button.setTitleColor(.white, for: .normal)
button.layer.cornerRadius = 12
button.layer.masksToBounds = true
button.titleLabel?.font = .systemFont(ofSize: 20, weight: .bold)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
title = "Create Account"
view.backgroundColor = .white
view.addSubview(scrollView)
scrollView.addSubview(scrollInnerView)
scrollInnerView.addSubview(profilePic)
scrollInnerView.addSubview(usernameField)
scrollInnerView.addSubview(emailField)
scrollInnerView.addSubview(passwordField)
scrollInnerView.addSubview(registerButton)
usernameField.delegate = self
emailField.delegate = self
passwordField.delegate = self
profilePic.isUserInteractionEnabled = true
registerButton.addTarget(self,
action: #selector(registerButtonTapped),
for: .touchUpInside)
setUpKeyboard()
setUpConstraints()
}
private func setUpConstraints() {
// Scroll View Constraints
scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
// Scroll Inner View Constraints
scrollInnerView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
scrollInnerView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
scrollInnerView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
scrollInnerView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
scrollInnerView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
scrollInnerView.heightAnchor.constraint(equalTo: scrollView.heightAnchor, constant: 1).isActive = true
// Profile Picture Constraints
profilePic.widthAnchor.constraint(equalTo: scrollInnerView.widthAnchor, multiplier: 1/3).isActive = true
profilePic.heightAnchor.constraint(equalTo: scrollInnerView.widthAnchor, multiplier: 1/3).isActive = true
profilePic.centerXAnchor.constraint(equalTo: scrollInnerView.centerXAnchor).isActive = true
profilePic.topAnchor.constraint(equalTo: scrollInnerView.topAnchor, constant: 10).isActive = true
// User Name Field Constraints
usernameField.widthAnchor.constraint(equalTo: scrollInnerView.widthAnchor, constant: -60).isActive = true
usernameField.heightAnchor.constraint(equalToConstant: 45).isActive = true
usernameField.topAnchor.constraint(equalTo: profilePic.bottomAnchor, constant: 10).isActive = true
usernameField.centerXAnchor.constraint(equalTo: profilePic.centerXAnchor).isActive = true
// Email Field Constraints
emailField.widthAnchor.constraint(equalTo: usernameField.widthAnchor).isActive = true
emailField.heightAnchor.constraint(equalTo: usernameField.heightAnchor).isActive = true
emailField.topAnchor.constraint(equalTo: usernameField.bottomAnchor, constant: 10).isActive = true
emailField.centerXAnchor.constraint(equalTo: usernameField.centerXAnchor).isActive = true
// Password Field Constraints
passwordField.widthAnchor.constraint(equalTo: emailField.widthAnchor).isActive = true
passwordField.heightAnchor.constraint(equalTo: emailField.heightAnchor).isActive = true
passwordField.topAnchor.constraint(equalTo: emailField.bottomAnchor, constant: 10).isActive = true
passwordField.centerXAnchor.constraint(equalTo: emailField.centerXAnchor).isActive = true
// Register Button Constraints
registerButton.widthAnchor.constraint(equalTo: passwordField.widthAnchor).isActive = true
registerButton.heightAnchor.constraint(equalTo: passwordField.heightAnchor).isActive = true
registerButton.topAnchor.constraint(equalTo: passwordField.bottomAnchor, constant: 20).isActive = true
registerButton.centerXAnchor.constraint(equalTo: passwordField.centerXAnchor).isActive = true
}
private func setUpKeyboard() {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShowNotification), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHideNotification), name: UIResponder.keyboardWillHideNotification, object: nil)
}
#objc private func keyboardWillShowNotification(_ notification: NSNotification) {
guard let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
else {
return
}
print(keyboardSize.minY)
print(registerButton.frame.maxY)
}
}
It's because the keyboard frame and the button frame are in two different coordinate systems. You cannot compare them directly. You need to convert the button frame to window coordinates before comparing them. Or else convert the keyboard frame to the button frame coordinates (the button's superview).
Actually what I typically do is convert the keyboard frame to the internal coordinates of the target view and compare that to the target view's bounds. For example:
// n is the notification
let d = n.userInfo!
var r = d[UIResponder.keyboardFrameEndUserInfoKey] as! CGRect
r = self.slidingView.convert(r, from:nil) // <- this is the key move!
let h = self.slidingView.bounds.intersection(r).height
That tells me whether the keyboard would cover the sliding view, and if so, by how much.

How can I get a button in my subview to enable the rightbarbuttonitem in my view controller

I have a UIView with a textfield and a button, this UIView is a subview of my view controller. How can I have the button in my subview enable the view controller's navigation rightbarbuttonitem when it is pressed?
class CreateActivityView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
lazy var addButton: UIButton = {
let button = UIButton(type: UIButton.ButtonType.system)
button.setImage(UIImage(named: "add_dark.png"), for: .normal)
button.frame = CGRect(x: 0, y: 0, width: 24.0, height: 24.0)
button.addTarget(self, action: #selector(addButtonTapped), for: .touchUpInside)
button.isEnabled = false
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
lazy var activityNameTextField: DataEntryTextField = {
let textField = DataEntryTextField()
textField.frame = CGRect(x: 0, y: 0, width: 250.0, height: 30.0)
textField.placeholder = "Add an activity"
textField.font = UIFont(name: "Avenir", size: 17)
textField.keyboardType = UIKeyboardType.default
textField.returnKeyType = UIReturnKeyType.done
textField.translatesAutoresizingMaskIntoConstraints = false
return textField
}()
lazy var activityNameLabel: UILabel = {
let label = UILabel()
label.frame = CGRect(x: 0, y: 0, width: 0, height: 30.0)
label.font = UIFont(name: "Avenir", size: 17)
label.translatesAutoresizingMaskIntoConstraints = false
label.isHidden = true
return label
}()
func setupView() {
backgroundColor = UIColor.lightGray
addSubview(addButton)
addButton.rightAnchor.constraint(equalTo: self.safeAreaLayoutGuide.rightAnchor, constant: -16.0).isActive = true
addButton.centerYAnchor.constraint(equalTo: self.safeAreaLayoutGuide.centerYAnchor).isActive = true
addButton.heightAnchor.constraint(equalToConstant: 24.0).isActive = true
addButton.widthAnchor.constraint(equalToConstant: 24.0).isActive = true
addSubview(activityNameTextField)
activityNameTextField.leftAnchor.constraint(equalTo: self.safeAreaLayoutGuide.leftAnchor, constant: 16.0).isActive = true
activityNameTextField.topAnchor.constraint(equalTo: self.safeAreaLayoutGuide.topAnchor, constant: 10.0).isActive = true
activityNameTextField.bottomAnchor.constraint(equalTo: self.safeAreaLayoutGuide.bottomAnchor, constant: -10.0).isActive = true
activityNameTextField.rightAnchor.constraint(equalTo: addButton.safeAreaLayoutGuide.leftAnchor, constant: -20.0).isActive = true
addSubview(activityNameLabel)
activityNameLabel.leftAnchor.constraint(equalTo: self.safeAreaLayoutGuide.leftAnchor, constant: 16.0).isActive = true
activityNameLabel.rightAnchor.constraint(equalTo: self.safeAreaLayoutGuide.rightAnchor, constant: -16.0).isActive = true
activityNameLabel.topAnchor.constraint(equalTo: self.safeAreaLayoutGuide.topAnchor, constant: 10.0).isActive = true
activityNameLabel.bottomAnchor.constraint(equalTo: self.safeAreaLayoutGuide.bottomAnchor, constant: -10.0).isActive = true
}
#objc func addButtonTapped() {
guard let validatedText = activityNameTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines), !validatedText.isEmpty else {
return
}
displayActivityNameLabel(with: validatedText)
}
func displayActivityNameLabel(with text: String) {
activityNameLabel.text = text
activityNameLabel.isHidden = false
activityNameTextField.isHidden = true
print(activityNameLabel.text)
}
}
class QuickLogViewController: UIViewController {
let screenSize = UIScreen.main.bounds.size
var createActivityView: CreateActivityView!
override func viewDidLoad() {
super.viewDidLoad()
title = "Quick Log"
setupView()
}
func setupView() {
initializeCreateActivityView()
self.view.addSubview(createActivityView)
createActivityView.leftAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leftAnchor).isActive = true
createActivityView.rightAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.rightAnchor).isActive = true
createActivityView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor).isActive = true
createActivityView.heightAnchor.constraint(equalToConstant: 50.0).isActive = true
}
func initializeCreateActivityView() {
createActivityView = CreateActivityView()
createActivityView.frame = CGRect(x: 0, y: 0, width: screenSize.width, height: 50.0)
createActivityView.translatesAutoresizingMaskIntoConstraints = false
createActivityView.activityNameTextField.delegate = self
}
func enableCancelButton() {
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelButtonPressed))
}
}
I added my CreateActivityView to my view controller. The button target is handled by my createActvitiyView. So how can I access the rightbarbuttonitem from the subview?
You can try to use delegate
class CreateActivityView: UIView {
weak var delegate:VCName?
and
createActivityView = CreateActivityView()
createActivityView.delegate = self
after that inside any action do
delegate?.methodInsideTheVC()
Or write button action inside the vc
createActivityView = CreateActivityView()
createActivityView.button.addTarget(self, action: #selector(addButtonTapped), for: .touchUpInside)
and place
#objc func addButtonTapped() {

swift can't click uibutton located inside multiple subviews

I am not getting when I press the arrowButton, not even the print("toggleWhiteMenu pressed") is printing in the console? I have searched the other questions like this one but the don't seem to help.
let card: UIView = {
let tsl = UIView()
tsl.backgroundColor = UIColor.black
tsl.alpha = 0.9
return tsl
}()
let yellowCard: UIView = {
let tsl = UIView()
tsl.backgroundColor = UIColor.yellow
//tsl.alpha = 1
tsl.isUserInteractionEnabled = false
return tsl
}()
lazy var arrowButton: UIButton = {
let button = UIButton(type: .system)
button.setImage(#imageLiteral(resourceName: "down arrow"), for: .normal)
button.tintColor = UIColor.black
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 14)
button.addTarget(self, action: #selector(self.toggleWhiteMenu), for: .touchUpInside)
return button
}()
func toggleWhiteMenu() {
print("toggleWhiteMenu pressed")
UIView.animate(withDuration: 1, animations: {
self.whiteMenu.transform = CGAffineTransform(scaleX: 11, y: 11)
}) { (true) in
print("really sick")
}
}
let whiteMenu: UIView = {
let tsl = UIView()
tsl.backgroundColor = UIColor.white
tsl.alpha = 1
tsl.isUserInteractionEnabled = false
return tsl
}()
let containerView: UIView = {
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .yellow
v.isUserInteractionEnabled = false
return v
}()
let scrollView: UIScrollView = {
let v = UIScrollView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .white
return v
}()
let backgroundImageView: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "eiffel tower")
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.isUserInteractionEnabled = false
imageView.layer.masksToBounds = true
imageView.contentMode = .scaleAspectFill
return imageView
}()
func setUpViews() {
self.view.addSubview(scrollView)
scrollView.addSubview(containerView)
containerView.addSubview(backgroundImageView)
backgroundImageView.addSubview(card)
backgroundImageView.addSubview(yellowCard)
yellowCard.addSubview(whiteMenu)
yellowCard.addSubview(arrowButton)
///i have left out constraints except for the arrowbutton's constraints as i don't deem them necessary for this question
arrowButton.anchor(top: nil, left: nil, bottom: nil, right: nil, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: view.frame.width/6, height: view.frame.width/6)
arrowButton.clipsToBounds = true
arrowButton.centerXAnchor.constraint(equalTo: whiteMenu.centerXAnchor).isActive = true
arrowButton.centerYAnchor.constraint(equalTo: whiteMenu.centerYAnchor).isActive = true
}
Please add #objc with selector method like below.
#objc func toggleWhiteMenu() {
print("toggleWhiteMenu pressed")
UIView.animate(withDuration: 1, animations: {
self.whiteMenu.transform = CGAffineTransform(scaleX: 11, y: 11)
}) { (true) in
print("really sick")
}
}
You are setting:
.isUserInteractionEnabled = false
on multiple views, and then adding a button as a subview. isUserInteractionEnabled set to false on a parent view will cascade down to all subviews, including buttons and other controls.

swift can't call function after clicking button

I have made a container view with a image view and a button inside for some reason when running the app in simulator i can't click button and call the function taking me to the next screen , i have encountered this kind of problem before and it was as simple as changing the button to a lazy var though that hasn't work on this occasion?
lazy var nameLabelButton = UIButton()
func setupNavBarWithUser() {
guard let displayName = user?.DisplayName else { return }
let titleView = UIView()
titleView.frame = CGRect(x: 0, y: 0, width: 100, height: 40)
titleView.backgroundColor = UIColor.red
let containerView = UIView()
containerView.translatesAutoresizingMaskIntoConstraints = false
titleView.addSubview(containerView)
let profileImageView = UIImageView()
profileImageView.translatesAutoresizingMaskIntoConstraints = false
profileImageView.contentMode = .scaleAspectFill
profileImageView.layer.cornerRadius = 20
profileImageView.clipsToBounds = true
if let profileImageUrl = user?.profileImageURL {
profileImageView.loadImageUsingCacheWithUrlString(urlString:profileImageUrl)
}
containerView.addSubview(profileImageView)
//ios 9 constraint anchors
//need x,y,width,height anchors
profileImageView.leftAnchor.constraint(equalTo: containerView.leftAnchor).isActive = true
profileImageView.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true
profileImageView.widthAnchor.constraint(equalToConstant: 40).isActive = true
profileImageView.heightAnchor.constraint(equalToConstant: 40).isActive = true
containerView.addSubview(nameLabelButton)
nameLabelButton.setTitle("\(displayName)", for: .normal)
nameLabelButton.setTitleColor(.black, for: .normal)
nameLabelButton.translatesAutoresizingMaskIntoConstraints = false
//need x,y,width,height anchors
nameLabelButton.leftAnchor.constraint(equalTo: profileImageView.rightAnchor, constant: 8).isActive = true
nameLabelButton.centerYAnchor.constraint(equalTo: profileImageView.centerYAnchor).isActive = true
nameLabelButton.rightAnchor.constraint(equalTo: containerView.rightAnchor).isActive = true
nameLabelButton.heightAnchor.constraint(equalTo: profileImageView.heightAnchor).isActive = true
containerView.centerXAnchor.constraint(equalTo: titleView.centerXAnchor).isActive = true
containerView.centerYAnchor.constraint(equalTo: titleView.centerYAnchor).isActive = true
nameLabelButton.addTarget(self, action: #selector(self.openUsersProfileController), for: .touchUpInside)
self.navigationItem.titleView = titleView
}
func openUsersProfileController(){
print("asdasdadsad")
let openUsersProfileController = UserProfileController(collectionViewLayout: UICollectionViewFlowLayout())
openUsersProfileController.user = self.user
navigationController?.pushViewController(openUsersProfileController, animated: true)
}
well, code looks fine you just need to add #objc
#objc func openUsersProfileController(){
print("asdasdadsad")
let openUsersProfileController = UserProfileController(collectionViewLayout: UICollectionViewFlowLayout())
openUsersProfileController.user = self.user
navigationController?.pushViewController(openUsersProfileController, animated: true)
}
Reason:
From Swift 4, we manually need to add #objc before function.

How can i use activity indicator when a user registers or login messageView using swift 3

How can i use activity Indicator in the following code when a user registers or logs in the message view.
The Code below is a loginViewController which handles the login and Registeration of the User.
so, How can i use Activity Indicator View or Progress view PROGRAMATICALLY whenever a user hits the Login or Register Button .
class LoginController: UIViewController {
var messagesController: MessagesController?
let inputsContainerView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(r: 209, g:238, b:252).withAlphaComponent(0.3)
view.translatesAutoresizingMaskIntoConstraints = false
view.layer.cornerRadius = 5
view.layer.masksToBounds = true
return view
}()
lazy var loginRegisterButton: UIButton = {
let button = UIButton(type: .system)
button.backgroundColor = UIColor(r: 255, g: 45, b: 85)
button.setTitle("Register", for: UIControlState())
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitleColor(UIColor.white, for: UIControlState())
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
button.layer.cornerRadius = 10
button.addTarget(self, action: #selector(handleLoginRegister), for: .touchUpInside)
return button
}()
func handleLoginRegister() {
if loginRegisterSegmentedControl.selectedSegmentIndex == 0 {
handleLogin()
} else {
handleRegister()
}
}
func handleLogin() {
guard let email = emailTextField.text, let password = passwordTextField.text else {
print("Form is not valid")
return
}
FIRAuth.auth()?.signIn(withEmail: email, password: password, completion: { (user, error) in
if error != nil {
print(error ?? "")
return
}
//successfully logged in our user
self.messagesController?.fetchUserAndSetupNavBarTitle()
self.dismiss(animated: true, completion: nil)
})
}
// TextField, EmailTextField, PasswordTextField, seperator view
let nameTextField: UITextField = {
let tf = UITextField()
tf.placeholder = "Name"
tf.translatesAutoresizingMaskIntoConstraints = false
return tf
}()
let nameSeparatorView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(r: 220, g: 220, b: 220)
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let emailTextField: UITextField = {
let tf = UITextField()
tf.placeholder = "Email"
tf.translatesAutoresizingMaskIntoConstraints = false
return tf
}()
let emailSeparatorView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(r: 220, g: 220, b: 220)
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let passwordTextField: UITextField = {
let tf = UITextField()
tf.placeholder = "Password"
tf.translatesAutoresizingMaskIntoConstraints = false
tf.isSecureTextEntry = true
return tf
}()
lazy var profileImageView: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "backslash_inc02main")
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.contentMode = .scaleAspectFill
imageView.layer.cornerRadius = 20
imageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleSelectProfileImageView)))
imageView.isUserInteractionEnabled = true
return imageView
}()
lazy var loginRegisterSegmentedControl: UISegmentedControl = {
let sc = UISegmentedControl(items: ["Login", "Register"])
sc.translatesAutoresizingMaskIntoConstraints = false
sc.tintColor = UIColor.white
sc.selectedSegmentIndex = 1
sc.addTarget(self, action: #selector(handleLoginRegisterChange), for: .valueChanged)
return sc
}()
func handleLoginRegisterChange() {
let title = loginRegisterSegmentedControl.titleForSegment(at: loginRegisterSegmentedControl.selectedSegmentIndex)
loginRegisterButton.setTitle(title, for: UIControlState())
// change height of inputContainerView, but how???
inputsContainerViewHeightAnchor?.constant = loginRegisterSegmentedControl.selectedSegmentIndex == 0 ? 100 : 150
// change height of nameTextField
nameTextFieldHeightAnchor?.isActive = false
nameTextFieldHeightAnchor = nameTextField.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: loginRegisterSegmentedControl.selectedSegmentIndex == 0 ? 0 : 1/3)
nameTextFieldHeightAnchor?.isActive = true
nameTextField.isHidden = loginRegisterSegmentedControl.selectedSegmentIndex == 0
emailTextFieldHeightAnchor?.isActive = false
emailTextFieldHeightAnchor = emailTextField.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: loginRegisterSegmentedControl.selectedSegmentIndex == 0 ? 1/2 : 1/3)
emailTextFieldHeightAnchor?.isActive = true
passwordTextFieldHeightAnchor?.isActive = false
passwordTextFieldHeightAnchor = passwordTextField.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: loginRegisterSegmentedControl.selectedSegmentIndex == 0 ? 1/2 : 1/3)
passwordTextFieldHeightAnchor?.isActive = true
}
override func viewDidLoad() {
super.viewDidLoad()
//view.backgroundColor = UIColor(r: 255, g: 149, b: 0)
self.view.addBackground()
view.addSubview(inputsContainerView)
view.addSubview(loginRegisterButton)
view.addSubview(profileImageView)
view.addSubview(loginRegisterSegmentedControl)
setupInputsContainerView()
setupLoginRegisterButton()
setupProfileImageView()
setupLoginRegisterSegmentedControl()
}
func setupLoginRegisterSegmentedControl() {
//need x, y, width, height constraints
loginRegisterSegmentedControl.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
loginRegisterSegmentedControl.bottomAnchor.constraint(equalTo: inputsContainerView.topAnchor, constant: -12).isActive = true
loginRegisterSegmentedControl.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor, multiplier: 1).isActive = true
loginRegisterSegmentedControl.heightAnchor.constraint(equalToConstant: 36).isActive = true
}
func setupProfileImageView() {
//need x, y, width, height constraints
profileImageView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
profileImageView.bottomAnchor.constraint(equalTo: loginRegisterSegmentedControl.topAnchor, constant: -12).isActive = true
profileImageView.widthAnchor.constraint(equalToConstant: 150).isActive = true
profileImageView.heightAnchor.constraint(equalToConstant: 150).isActive = true
}
var inputsContainerViewHeightAnchor: NSLayoutConstraint?
var nameTextFieldHeightAnchor: NSLayoutConstraint?
var emailTextFieldHeightAnchor: NSLayoutConstraint?
var passwordTextFieldHeightAnchor: NSLayoutConstraint?
func setupInputsContainerView() {
//need x, y, width, height constraints
inputsContainerView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
inputsContainerView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
inputsContainerView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -24).isActive = true
inputsContainerViewHeightAnchor = inputsContainerView.heightAnchor.constraint(equalToConstant: 150)
inputsContainerViewHeightAnchor?.isActive = true
inputsContainerView.addSubview(nameTextField)
inputsContainerView.addSubview(nameSeparatorView)
inputsContainerView.addSubview(emailTextField)
inputsContainerView.addSubview(emailSeparatorView)
inputsContainerView.addSubview(passwordTextField)
//need x, y, width, height constraints
nameTextField.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor, constant: 12).isActive = true
nameTextField.topAnchor.constraint(equalTo: inputsContainerView.topAnchor).isActive = true
nameTextField.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true
nameTextFieldHeightAnchor = nameTextField.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: 1/3)
nameTextFieldHeightAnchor?.isActive = true
//need x, y, width, height constraints
nameSeparatorView.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor).isActive = true
nameSeparatorView.topAnchor.constraint(equalTo: nameTextField.bottomAnchor).isActive = true
nameSeparatorView.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true
nameSeparatorView.heightAnchor.constraint(equalToConstant: 1).isActive = true
//need x, y, width, height constraints
emailTextField.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor, constant: 12).isActive = true
emailTextField.topAnchor.constraint(equalTo: nameTextField.bottomAnchor).isActive = true
emailTextField.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true
emailTextFieldHeightAnchor = emailTextField.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: 1/3)
emailTextFieldHeightAnchor?.isActive = true
//need x, y, width, height constraints
emailSeparatorView.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor).isActive = true
emailSeparatorView.topAnchor.constraint(equalTo: emailTextField.bottomAnchor).isActive = true
emailSeparatorView.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true
emailSeparatorView.heightAnchor.constraint(equalToConstant: 1).isActive = true
//need x, y, width, height constraints
passwordTextField.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor, constant: 12).isActive = true
passwordTextField.topAnchor.constraint(equalTo: emailTextField.bottomAnchor).isActive = true
passwordTextField.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true
passwordTextFieldHeightAnchor = passwordTextField.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: 1/3)
passwordTextFieldHeightAnchor?.isActive = true
}
func setupLoginRegisterButton() {
//need x, y, width, height constraints
loginRegisterButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
loginRegisterButton.topAnchor.constraint(equalTo: inputsContainerView.bottomAnchor, constant: 12).isActive = true
loginRegisterButton.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true
loginRegisterButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
}
override var preferredStatusBarStyle : UIStatusBarStyle {
return .lightContent
}
}
extension UIColor {
convenience init(r: CGFloat, g: CGFloat, b: CGFloat) {
self.init(red: r/255, green: g/255, blue: b/255, alpha: 1)
}
}
To show activity indicator, first declare it at class level and then initialize it.
var activityIndicator:UIActivityIndicatorView!
Then in your viewdidLoad() method, initialize activityIndicator.
activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
activityIndicator.center = view.center
activityIndicator.isHidden = true
self.view.addSubview(activityIndicator)
You can write two methods to start and stop activity indicator in your view controller as:
func displayActivityIndicatorView() -> () {
UIApplication.shared.beginIgnoringInteractionEvents()
self.view.bringSubview(toFront: self.activityIndicator)
self.activityIndicator.isHidden = false
self.activityIndicator.startAnimating()
}
func hideActivityIndicatorView() -> () {
if !self.activityIndicator.isHidden{
DispatchQueue.main.async {
UIApplication.shared.endIgnoringInteractionEvents()
self.activityIndicator.stopAnimating()
self.activityIndicator.isHidden = true
}
}
}
Now start activity indicator just after validating the login data and before hitting the login API as:
func handleLogin() {
guard let email = emailTextField.text, let password = passwordTextField.text else {
print("Form is not valid")
return
}
//start activity indicator
self. displayActivityIndicatorView()
FIRAuth.auth()?.signIn(withEmail: email, password: password, completion: { (user, error) in
if error != nil {
print(error ?? "")
//stop activity indicator
self. hideActivityIndicatorView()
return
}
//successfully logged in our user
//stop activity indicator
self. hideActivityIndicatorView()
self.messagesController?.fetchUserAndSetupNavBarTitle()
self.dismiss(animated: true, completion: nil)
})
}
Step 1:
Create activity indicator somewhere in your code. Specially in viewDidLoad
if you want to create it programmatically or if you want to show activity indicator with an alert design in programmatically.
Step 2: To show activity indicator
There is a button like login or register . There you will start the to show the activity indicator and start it to animate.
Step 3: To hide activity indicator
You will hide activity indicator in FIRAuth.auth()?.signIn..... completion handler for login. just like
[indicator stopAnimating];
[indicator isHidden:YES];
There are two cases in that login method. one is error and the other is successful. Its better to show an error alert to the user or something else.
Hope you will find this solution helpful. :)
You can use below code.
let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .alert)
alert.view.tintColor = UIColor.black
let loadingIndicator: UIActivityIndicatorView = UIActivityIndicatorView(frame: CGRect(x:10, y:5, width:50, height:50)) as UIActivityIndicatorView
loadingIndicator.hidesWhenStopped = true
loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
loadingIndicator.color = UIColor(red: 255.0/255, green: 65.0/255, blue: 42.0/255,alpha : 1.0)
loadingIndicator.startAnimating();
alert.view.addSubview(loadingIndicator)
present(alert, animated: true, completion: nil)
///dismisss///
dismiss(animated: false, completion: nil)

Resources