0

what I need to do is call a function that is located in an extension of UIViewController from an static var with a didSet that is also located in the extension of UIViewController. Here would be some example code.

extension UIViewController {
    static var isWifiAvailable = false {
        didSet {
            if isWifiAvailable = true {
                 getValidLogin()
            }
        }
    }

    func getValidLogin() {
        // do something
    }

    func otherFuncCallsit() {
         isWifiAvailable = true
    }

}

I tried using

DispatchQueue.main.async {
    let keyWindow = UIApplication.shared.windows.filter {$0.isKeyWindow}.first

    if let topController = keyWindow?.rootViewController {
         topController.getValidLogin(username: email, password: password, sender: "backgroundCheck")
    }
}

But this caused the api I was calling from getValidLogin to not work. If I used this solution, when I would call the api, nothing after session.uploadTask would run (for example print("ok") wouldn't run). Here is my actual getValidLogin() (with the url of api changed)

func getValidLogin(username: String, password: String, sender: String = "") {
        
        let session = URLSession.shared
        let url = URL(string: "example.com")!
        
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        
        request.setValue("application/json", forHTTPHeaderField: "Accept")
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        
        let json = [
            "UserName": username,
            "Password": password
        ]
        let jsonData = try! JSONSerialization.data(withJSONObject: json, options: [])
        var done = false
        let group = DispatchGroup() // initialize
        
        print(request)
        let task = session.uploadTask(with: request, from: jsonData) { data, response, error in
            group.enter()
            if data == nil {
               
                self.showNoWifiAlert()
                
                loginResponseDetails.message = "Cannot Login Due to Unstable Internet Connection. Please Try again"
                group.leave()
                done = true
            } else {
                do {
                        guard let dictionary = try JSONSerialization.jsonObject(with: data!, options: []) as? [String: Any] else {
                            print("Could not cast JSON content as a Dictionary<String, Any>")
                            return
                        }
                        UIViewController.isWifiAvailable = true
                        loginResponseDetails.token = dictionary["Token"] as? String ?? "nil"
                        loginResponseDetails.message = dictionary["Message"] as! String
                        loginResponseDetails.status = dictionary["Status"] as! Bool
                        loginResponseDetails.isResetFirstPassword = dictionary["IsResetFirstPassword"] as! Bool
                        loginResponseDetails.isFinalRegistrationSubmitted = dictionary["IsFinalRegistrationSubmitted"] as! Bool
                        loginResponseDetails.finalStatus = dictionary["FinalStatus"] as? String ?? "nil"
                        loginResponseDetails.isAgreementsAccepted = dictionary["IsAgreementsAccepted"] as! Bool
                        loginResponseDetails.carrierCountry = dictionary["CarrierCountry"] as? String ?? "nil"
                        
                        print("token: " + loginResponseDetails.token)
                        print("message: " + loginResponseDetails.message)
                        print("status: " + String(loginResponseDetails.status))
                        print("isResetFirstPassword: " + String(loginResponseDetails.isResetFirstPassword))
                        print("isFinalRegistrationSubmitted: " + String(loginResponseDetails.isFinalRegistrationSubmitted))
                        print("finalStatus: " + loginResponseDetails.finalStatus)
                        print("isAgreementsAccepted: " + String(loginResponseDetails.isAgreementsAccepted))
                        print("carrierCountry: " + loginResponseDetails.carrierCountry)
                        group.leave()
                        done = true
                    } catch {
                        // Print error if something went wrong
                        print("Error: \(error)")
                    }
                }
            }
        group.notify(queue: .main) {
            task.resume()
        }
        repeat {
            RunLoop.current.run(until: Date(timeIntervalSinceNow: 0.1))
        } while !done
        
        print("ok")
        if sender == "backgroundCheck" {
            print(loginResponseDetails.status)
            print("ok")
            if loginResponseDetails.status == true {
                let vc = UIStoryboard(name: "ShamitMain", bundle: nil).instantiateViewController(identifier: "LoginVC")
                let navController = UINavigationController(rootViewController: vc)
                navController.isNavigationBarHidden = false
                navController.modalPresentationStyle = .fullScreen
                
                self.present(navController, animated: true, completion: nil)
            }
        
        }
    }

So is there either some other way to call getValidLogin() or is there any way to solve the problem I'm having when using the solution above?

  • 1
    make it non static. Btw if you need to check the network status https://stackoverflow.com/a/30743763/2303865 – Leo Dabus Sep 15 '20 at 16:01
  • @LeoDabus in an extension? – gcharita Sep 15 '20 at 16:05
  • you can call it from anywhere. Check the sample project attached to the post – Leo Dabus Sep 15 '20 at 16:05
  • @LeoDabus oh, now I show your edit. Good point. – gcharita Sep 15 '20 at 16:07
  • `if Network.reachability.status == .wifi` – Leo Dabus Sep 15 '20 at 16:07
  • You can't call a non-static function from a static getter/setter unless you have an instance to call the non-static function on. – clawesome Sep 15 '20 at 17:35
  • How would you suggest the best way to go about this problem is. I looked at the first comment, the network status thing is built for me in a very custom way specific to how I am handling my apis. It's just that everytime a user goes from no internet to internet I need to check the login status. I thought of using the setter for that reason. How else would I go about it. – Shamit Surana Sep 15 '20 at 19:38
  • Typically authentication returns some sort of token that you pass with your requests. You then handle the case where the token is rejected and re-authenticate when required. Trying to track network connectivity and build re-authentication logic into every view controller doesn't seem like the right approach to me. Even if you get it to work you still need to handle the case where the token is rejected for other reasons – Paulw11 Sep 15 '20 at 20:44

0 Answers0