Reputation: 29
I'm trying to learn how to use Rest API. I want to use Github API to login from iPhone first.
Here is my model (it's not completed yet):
mutating func gettingAceess(completionBlock: @escaping (_ data : Data?, _ response : URLResponse?, _ error : Error?) -> Void ) throws {
guard username != "", password != "" else {
throw loginError.emptyUsernameOrPassword
}
let loginString = "\(self.username):\(self.password)"
let resourceUrl = "https://\(loginString)@api.github.com"
guard let loggingUrl = URL(string: resourceUrl) else {fatalError()}
let logging = URLSession.shared.dataTask(with: loggingUrl) { (data, response, error) in
if error != nil {
print("\(String(describing: error))")
}
}
logging.resume()
}
In the controller, I want when user taps the login button, getting access function should be called.
@IBAction func pressLoginBtn(_ sender: UIButton) {
if let username = usernameInput.text, let password = passwordInput.text {
var logginInformation = LogginReguest(username: username, password: password)
do {
try logginInformation.gettingAceess(completionBlock: ...)
} catch {
}
In the code front of the try
, I don't know what I should write. Can anyone help me? Or I am doing the whole thing wrong?
Upvotes: 1
Views: 213
Reputation: 2100
do {
// if completion block is last argument; you can use trailing syntax
try logginInformation.gettingAceess() { (data, response, error) in
// as your completion block have this signature
// completionBlock: @escaping (_ data : Data?, _ response : URLResponse?, _ error : Error?) -> Void)
}
} catch {
You will need to update gettingAceess
method also.
let logging = URLSession.shared.dataTask(with: loggingUrl) { (data, response, error) in
if error != nil {
print("\(String(describing: error))")
}
// This line passes this completion block to caller who can read it
completion(data, response, error)
}
The above detail was how you will get completion block working in your example. The suggestion would be not to pass the URLSession
completion block directly; rather process it.
enum NKError: Error {
case networkError
}
func gettingAceess(completionBlock: @escaping (Result<[String: Any], NKError>) -> Void ) {
let logging = URLSession.shared.dataTask(with: loggingUrl) { (data, response, error) in
if error != nil {
print("\(String(describing: error))")
completion(.failure(NKError.networkError))
}
// Now I can check for status or data
if let data = data {
// parse the result and then return
if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] {
completion(.success(json))
}
}
}
}
In this case, I am trying to pass the error
or json
to caller.
Upvotes: 0
Reputation: 285082
Your approach is wrong. First of all check for empty text fields already before calling the asynchronous task.
Secondly it's bad practice to make a function throws
which contains an asynchronous task, in the completion block return the received data or the error.
This is an example with the Result
struct returning the received Data
as string or the error.
mutating func gettingAccess(completionBlock: @escaping (Result<String,Error>) -> Void)
{
let loginString = "\(self.username):\(self.password)"
let resourceUrl = "https://\(loginString)@api.github.com"
guard let loggingUrl = URL(string: resourceUrl) else {fatalError()}
let logging = URLSession.shared.dataTask(with: loggingUrl) { (data, _, error) in
if let error = error {
completion(.failure(error))
} else {
let string = String(data: data!, encoding: .utf8)!
completion(.success(string))
}
}
logging.resume()
}
@IBAction func pressLoginBtn(_ sender: UIButton) {
guard usernameInput.hasText, passwordInput.hasText else {
// show an alert
return
}
let logginInformation = LogginReguest(username: usernameInput.text!, password: passwordInput.text!)
logginInformation.gettingAccess { result in
switch result {
case .success(let string): print(string)
case .failure(let error): print(error)
}
}
}
Side note:
Please look for contemporary tutorials. The syntax (_ data : Data?, _ response : URLResponse?, _ error : Error?)
with parameter labels and underscores is Swift 2 legacy syntax.
Upvotes: 1