Omep2005 Omep2005 - 11 days ago 5
Swift Question

Access DispatchGroup from another class

Is it possible to access a DispatchGroup from another class?
Say I have the following function in the class

Loginfunctions.swift
(with a
var loginQueue = DispatchGroup.init()
defined out of the
func
):

func logUserIn(emaila: String!, passworda: String!, urlPath: String!, completionHandler:@escaping (NSDictionary) -> Void) {
DispatchQueue.global(qos: .userInitiated).async {

let requestURL = NSURL(string: urlPath)!
let request = NSMutableURLRequest(url: requestURL as URL)
request.httpMethod = "POST"
let emailtext = emaila
let passwordtext = passworda

let postParameters = "email="+emailtext!+"&password="+passwordtext!;
request.httpBody = postParameters.data(using: .utf8)

DispatchGroup.enter(loginQueue)()

//creating a task to send the post request
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in

if error != nil{
print("error is \(error)")
return;
}

do {
//converting resonse to NSDictionary
let myJSON = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! NSDictionary
DispatchGroup.wait(self.loginQueue)()
DispatchQueue.main.async {
completionHandler(myJSON)
}
} catch {
print(error)
}
}

//executing the task
task.resume()
DispatchGroup.leave(self.loginQueue)()
}
}


Calling the following from another Class (
LoginViewController.swift
) results in different values for
TEMP_VAR_FOR_LOGIN
(Instance in
LoginViewController.swift
):

@IBAction func userLogin(_ sender: UIButton) {
self.loginFunctions.logUserIn(emaila: self.email.text, passworda: self.password.text, urlPath: "URL_PATH_WAS_ENTERED_HERE") {
(completionHandler) in
self.TEMP_VAR_FOR_LOGIN = completionHandler
print("*****************")
print(self.TEMP_VAR_FOR_LOGIN)
}

print("################")
print(TEMP_VAR_FOR_LOGIN)
}


The console output is

Some other stuff...
#################
{
}
More other stuff...
*****************
{
The Data I need : Out of the Closure
}


Any help where the problem is?

P.S. Rookie here ;)

Answer

URLSessionTask method itself is an async task. So, there is no need to use DispatchGroup here. The logUserIn function can be modified as below:

func logUserIn(emaila: String!, passworda: String!, urlPath: String!, completionHandler:@escaping (NSDictionary) -> Void)  {

    let emailtext = emaila
    let passwordtext = passworda

    let postParameters = "email="+emailtext!+"&password="+passwordtext!;

    let requestURL = URL(string: urlPath)!
    var request = URLRequest(url: requestURL)
    request.httpMethod = "POST"
    request.httpBody = postParameters.data(using: .utf8)

    //creating a task to send the post request
    let session = URLSession(configuration: URLSessionConfiguration.default)
    let task: URLSessionDataTask = session.dataTask(with: request, completionHandler: { data, response, error in

        if error != nil {
            print(error)
        }else {
            do {
                //converting resonse to NSDictionary
                let myJSON =  try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! NSDictionary
                DispatchQueue.main.async {
                    completionHandler(myJSON)
                }
            } catch {
                print(error)
            }
        }
    })

    task.resume()
}

Secondly, the way you're using closure here is wrong. It is used as given below:

var dictionaryObj:NSMutableDictionary = NSMutableDictionary() //global - defined outside functions

self.logUserIn(emaila: "lal", passworda: "lal", urlPath: "lal", completionHandler: { dictionaryObj in
    self.dictionaryObj = dictionaryObj as! NSMutableDictionary
    print(dictionaryObj)
    print(self.dictionaryObj)
})