1

i am a beginner in swift, i was trying to use an UIAlertController but i have got an error and the UiAlertController do not show up and i can see an error in the console that says

2021-06-20 18:16:28.494162+0200 Bicycall[50670:543648] [Presentation] Attempt to present <UIAlertController: 0x7fbaca034e00> on <Bicycall.login: 0x7fbabb01d800> (from <Bicycall.login: 0x7fbabb01d800>) whose view is not in the window hierarchy.
2021-06-20 18:16:28.494339+0200 Bicycall[50670:543648] [Presentation] Attempt to present <UIAlertController: 0x7fbac9862800> on <Bicycall.login: 0x7fbabb01d800> (from <Bicycall.login: 0x7fbabb01d800>) whose view is not in the window hierarchy.

Here what i have tried:

import UIKit
import CoreData
import AVKit
import AVFoundation
import TKSubmitTransition

class login: UIViewController {

    
    @IBOutlet weak var passwordView: UIView!
    @IBOutlet weak var emailView: UIView!
    var id: Int?
    var name: String?
    var lastname: String?
    var email:String?
    var password:String?
    var phone:String?
    
    var u = ConnectedUser()
    var BR = BaseUrl.baseUrl
    
    var player: AVPlayer?
        let videoURL: NSURL = Bundle.main.url(forResource: "Bikers", withExtension: "mp4")! as NSURL
    
    


    func getTopMostViewController() -> UIViewController? {
        var topMostViewController = UIApplication.shared.keyWindow?.rootViewController

        while let presentedViewController = topMostViewController?.presentedViewController {
            topMostViewController = presentedViewController
        }

        return topMostViewController
    }

    
    
    func presentTestAlert(_ title: String, _ message: String){
        let alert = UIAlertController(title: title , message: message, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "Default action"), style: .default, handler: { _ in
        NSLog("The \"OK\" alert occured.")
        }))
        DispatchQueue.main.async {
            self.getTopMostViewController()?.present(alert, animated: true, completion: nil)
        }

    }
 
    override func viewDidLoad() {
        super.viewDidLoad()

        self.DeleteAllData()
        
        
        player = AVPlayer(url: videoURL as URL)
                player?.actionAtItemEnd = .none
                player?.isMuted = true
                
                let playerLayer = AVPlayerLayer(player: player)
                playerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
                playerLayer.zPosition = -1
                playerLayer.frame = view.frame
                view.layer.addSublayer(playerLayer)
                player?.play()
                NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.player?.currentItem, queue: .main) { [weak self] _ in
                                    self?.player?.seek(to: CMTime.zero)
                                    self?.player?.play()
        
        
        // Do any additional setup after loading the view.
    }
        
        
                emailView.layer.cornerRadius = 30.0
                emailView.layer.borderWidth = 0.5
        emailView.layer.borderColor = UIColor.white.cgColor
                
                passwordView.layer.cornerRadius = 30.0
                passwordView.layer.borderWidth = 0.5
                passwordView.layer.borderColor = UIColor.white.cgColor
    }
    
    
    
    //widgets
    
    @IBOutlet weak var txtEmail: UITextField!
    
    
    @IBOutlet weak var txtPassword: UITextField!
    
    
    
    //Actions
    @IBAction func btnLogin(_ sender: Any){

         //get
       /*
        guard let url = URL(string: "http://localhost:3000/bikes") else {
        return
        }
        let session = URLSession.shared
        session.dataTask(with: url)  { ( data , response ,error) in
            if let response = response {
                print(response)
            }
            
            if let data = data {
                print(data)
                do
                {
                    let json = try JSONSerialization.jsonObject(with: data, options: [])
                    print(json)
                }catch{
                    print(error)
                }
            }
            
        }.resume()
        */
        
        //post
    
        guard let url = URL(string: BR+"/login") else {
        return
        }
        
        let bodyparameters = ["email": txtEmail.text, "password": txtPassword.text]
       
        if (txtEmail.text!.isEmpty || txtPassword.text!.isEmpty ){
            
            self.presentTestAlert("Wrong credentials","Email and Password must not be empty")
            
        }else{

            
            var request = URLRequest(url: url)
            request.httpMethod = "POST"
            request.addValue("application/json", forHTTPHeaderField: "Content-Type")
            guard let httpBody = try? JSONSerialization.data(withJSONObject: bodyparameters, options: []) else{
                return
                }
            request.httpBody = httpBody
            let session = URLSession.shared
            session.dataTask(with: request) { (data,response,error) in
                let status = (response as! HTTPURLResponse).statusCode
                //print(response)
                print(status)
                if let response = response {
                    let status = (response as! HTTPURLResponse).statusCode
                    //print(response)
                    print(status)
                }
                
                if((status) == 200){
                    self.presentTestAlert("Connection Success", " internet connection")
                    print(" Connection Successssssssssssssss")
                    
                    if let data = data {
                        do {
                            //let json = try JSONSerialization.jsonObject(with: data, options: [])
                           // print(json);
                            print(data)
                            let user = try JSONDecoder().decode(User.self, from: data)
                           
                            DispatchQueue.main.async {
                                
                                self.id = user.user_id
                                self.name = user.name
                                self.lastname = user.lastname
                                self.email = user.email
                                self.password = user.password
                                self.phone = user.phone
                                
                                print(self.id!)
                                print(self.email!)
                                
                                
                                if(user.user_id != 0){
                                   
                                    self.saveUser()
                                    self.DisplayConnectedUser()
                                   self.performSegue(withIdentifier: "HomeSegue", sender: "nil")
                                    
                                }else{
                                    self.presentTestAlert("Login Failed","Wrong credentials")
                                  
                                }
                            
                            }
                            
                        }catch{
                            print(error)
                        }
                        
                    }
                    
                }else {
                    self.presentTestAlert("No Connection", "No internet connection")
                    print(" Connection Nooooooooooooooooooooooooo")
                }
                
       
                
            }.resume()

            
            
        }
        
        
    }
    
    
    func DeleteAllData(){

        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        let managedContext = appDelegate.persistentContainer.viewContext
        let DelAllReqVar = NSBatchDeleteRequest(fetchRequest: NSFetchRequest<NSFetchRequestResult>(entityName: "Users"))
        do {
            try managedContext.execute(DelAllReqVar)
        }
        catch {
            print(error)
        }
    }

    

    func saveUser() {
        
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        //represente l'ORM
        let persistentContainer = appDelegate.persistentContainer
        let managedContext = persistentContainer.viewContext
        
        let entityDescription = NSEntityDescription.entity(forEntityName: "Users" ,  in: managedContext)
        let object = NSManagedObject(entity: entityDescription! , insertInto: managedContext )
        object.setValue(id!  ,  forKey: "user_id"  )
        object.setValue(email!  ,  forKey: "email"  )
        object.setValue(password!  ,  forKey: "password"  )
        object.setValue(name!  ,  forKey: "name"  )
        object.setValue(lastname!  ,  forKey: "lastname"  )
        object.setValue(phone!  ,  forKey: "phone"  )
        
                  do {
                  
                 try managedContext.save()
                   print("INSERT SUCCESSFULLY")
                print(id!)
                   }
                   catch  {
                   print("INSERT ERROR")
                   }
        
    }
    

    
    
    @IBAction func btnSignup(_ sender: Any) {
        performSegue(withIdentifier: "signupSegue", sender: "nil")
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
      
    }

    
    
    func DisplayConnectedUser() {
            
             let appDelegate = UIApplication.shared.delegate as! AppDelegate
                //represente l'ORM
                let persistentContainer = appDelegate.persistentContainer
                
                let managedContext = persistentContainer.viewContext     //retourne NSManagedObject toujours
                
                //la requete retourne un NSManagedObject
                let request = NSFetchRequest<NSManagedObject>(entityName :   "Users")
                
                //execution de la requete
                do {
                
                    let result = try  managedContext.fetch(request)
                for item in result {
                    print(item.value(forKey: "user_id") as! Int )
                    print(item.value(forKey: "email")  as! String)
                    self.u.user_id  = (item.value(forKey: "user_id")  as! Int)
                    self.u.email = (item.value(forKey: "email")  as! String)
                    self.u.password = (item.value(forKey: "password")  as! String)
                    self.u.name = (item.value(forKey: "name")  as! String)
                    self.u.lastname = (item.value(forKey: "lastname")  as! String)
                    self.u.phone = (item.value(forKey: "phone")  as! String)
                   
                    print(self.u.user_id!)
                    print(self.u.email!)
                    print(self.u.password!)
                    print(self.u.name!)
                    print(self.u.lastname!)
                    print(self.u.phone!)
                  
                }
                
                   }
                   catch {
                   print("NO DATA FOUND , Error")
                   }


        }
    
    
    

}

What is annoying me is that none of my alerts worked! i read some other answer in stackoverflow but the solutions did not work for me

What i am trying is to make my alerts working good

Any help will be so appreciated

LearnDeep
  • 27
  • 6

1 Answers1

0

It seems you want to present the alert over the video player (playerLayer) but you are calling your alert over the layer behind the playerLayer, it will give you the error that you're getting.

With reference to Swift 4 Attempt to present ViewController whose view is not in the window hierarchy

Add this function in your code

func getTopMostViewController() -> UIViewController? {
    var topMostViewController = UIApplication.shared.keyWindow?.rootViewController

    while let presentedViewController = topMostViewController?.presentedViewController {
        topMostViewController = presentedViewController
    }

    return topMostViewController
}

And replace (Line 33)

self.present(alert, animated: true, completion: nil)

with

DispatchQueue.main.async {
    getTopMostViewController()?.present(alert, animated: true, completion: nil)
}
Asad
  • 279
  • 1
  • 7
  • hi , thank you for the answer but it did not work properly because after i executed the condition of checking if the email or password stopped working while it was working before i add your code , it is like when i click on the button the app ignores the if conditions after i added your code, i updated my post – LearnDeep Jun 20 '21 at 17:32
  • yes but the segue is performed in all the cases , it was not happening before your code – LearnDeep Jun 20 '21 at 18:43
  • Can you check if email and password are actually empty in your else block? – Asad Jun 20 '21 at 18:56
  • no , after your code , the else block do not work properly – LearnDeep Jun 20 '21 at 19:16
  • I don’t know why the `if; else` block is not working. The issue with the alert is I guess solved, you need to see what is going wrong in the `if; else` block – Asad Jun 20 '21 at 21:36