I have a simple AWS Lambda function which returns the id of the user when he logins.
if (event.email && password)
{
connection.query("SELECT * FROM doctor_data WHERE doc_email = ?", [event.email], function(error, results, fields)
{
connection.release();
if(results.length > 0)
{
bcrypt.compare(password, results[0].password, function(err, ress)
{
if(!ress)
{
callback (null, "Incorrect Password");
}
else
{
callback (null, results[0].doc_id);
}
});
}
else
{
callback (null, "Incorrect Email");
}
});
}
else
{
callback(null, "Please enter Email and Password!");
}
Now in Android (Java) we used the below mentioned logic for accessing the id. We directly store it in the String variable and it works fine.
#Override
public void onResponse(Call call, Response response) throws IOException {
String responseMsg = response.body().string();
Log.e(TAG, msg: responseMsg+ " responseMsg");
The iOS swift code is mentioned below.
func callingLoginAPI(login: LoginModel,completionHandler: #escaping (Bool, String) -> ()){
let headers: HTTPHeaders = [
.contentType("application/json")
]
AF.request(doctor_login, method: .post, parameters: login, encoder:
JSONParameterEncoder.default, headers: headers).response{
response in debugPrint(response)
switch response.result{
case.success(let data):
let urlString = doctor_login
guard let url = URL(string: urlString) else {return}
URLSession.shared.dataTask(with: url){ (data, response, err) in
guard let data = data else {return}
let dataAsString = String(data: data,encoding: .utf8)
print("this is", dataAsString)
do{
let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers)
print(json)
print("json")
}
catch{
print(error.localizedDescription)
completionHandler(false, "Login not Done")
print("not done")
}
}.resume()
if response.response?.statusCode == 200
{
completionHandler(true, "Login Done")
print("done")
}
else{
completionHandler(false, "Please try again")
print("not done")
}
case.failure(let err):
print("that")
print(err.localizedDescription)
completionHandler(false, "Try Again")
}
}
It's giving me the following response. It's giving me the id of the user which is 2 in this case but I don't know how to get/extract or save it.
Can anyone guide me how to get/extract or save the response of the body which is 2 in this case?
In Android we used the okhttp library for accessing the API whereas in iOS swift we used NSURLConnection library for acccessing the API.
Related
I would like to get data from server, but credential (username, password. Not Basi Authentification) is necessary to get it. Therefore, I try to use URLSession with URLCredential as following:
https://developer.apple.com/documentation/foundation/url_loading_system/handling_an_authentication_challenge
However, I could not understand this document...
So could you tell me how to use URLSession with URLCredential?
I tried URLSession like:
func startLoad() {
let url = URL(string: "https://www.abcde-test-url.com/")!
let task = URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
print("client error: \(error.localizedDescription) \n")
return
}
guard let data = data, let response = response as? HTTPURLResponse else {
print("no data or no response")
return
}
if response.statusCode == 200 {
print(data)
} else {
print("error status code: \(response.statusCode)\n")
}
}
task.resume()
}
But I couldn't understand the usage with URLCredential.
I have a singleton URLSession that is parsing the response data into a dictionary. I want to use a single value from that dictionary in a subsequent piece of code, but cannot figure out how to pass the value out from the scope it's currently in.
Here is the code as it stands now:
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard error == nil else {
debugPrint ("error: \(error!)")
return
}
guard let content = data else {
debugPrint("No data")
return
}
guard let json = (try? JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers)) as? [String: Any] else {
debugPrint("Not containing JSON")
return
}
if let idToken = json["id_token"] as? String {
let privateToken = idToken;
debugPrint("Gotten json response dictionary is \(idToken)")
}
}
task.resume()
return privateToken
Currently there is an IDE error on return privateToken saying that I am using an unresolved identifier: privateToken.
How can I take the string idToken and return it as a privateToken for use elsewhere?
Could you use a completion handler like:
func getPrivateToken(completion: #escaping(String) -> (), failure: #escaping (Error) -> ()) {
URLSession.shared.dataTask(with: request) { data, response, error in
guard error == nil else {
debugPrint ("error: \(error!)")
failure(error)
return
}
guard let content = data else {
debugPrint("No data")
failure(NSError(domain: "Your error message here.", code: 401, userInfo: nil))
return
}
guard let json = (try? JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers)) as? [String: Any] else {
debugPrint("Not containing JSON")
failure(NSError(domain: "Your error message here.", code: 401, userInfo: nil))
return
}
if let idToken = json["id_token"] as? String {
completion(idToken)
debugPrint("Gotten json response dictionary is \(idToken)")
}
}.resume()
}
And use it like so:
func exampleFunction() {
self.getPrivateToken(completion: { (token) in
// Do what ever you need with the token here.
print("ID token is: \(token)")
}) { (error) in
// Present error here
}
}
It's likely that I will receive an SSL error -1200 from an Alamofire request, if this occurs, I want to output the error to a text field.
I'm trying to catch the error I'm getting in my console window so that I can output it to the text field, but I'm getting this message from xcode:
'catch' block is unreachable because no errors are thrown in 'do' block
Here is how I'm structuring the do/try/catch with the AF request:
do{
try AF.request(host, method: .post, parameters: parameters, encoding:JSONEncoding.default)
.responseData{ response in
guard let responseData = response.data else { return }
let responseJSON = try? JSON(data:responseData)
if let responseJSONAsString = responseJSON?.rawString(){
self.output(text: responseJSONAsString + "\n\n\n")
}
}
}
catch {
self.textField.stringValue = ("Caught: " + error.localizedDescription)
}
You need
AF.request(host, method: .post, parameters:parameters,encoding:JSONEncoding.default)
.responseData { response in
do {
guard let responseData = response.data else { return }
let responseJSON = try JSON(data:responseData)
if let responseJSONAsString = responseJSON.rawString(){
///
}
}
catch {
print(error)
}
}
Alamofire does not throw errors – that's what the error says – but you should handle the passed error in the closure
AF.request(host, method: .post, parameters: parameters, encoding: .default)
.responseData { response in
switch response.result {
case .success(let data):
do {
let responseJSON = try JSON(data: data)
if let responseJSONAsString = responseJSON?.rawString(){
self.output(text: responseJSONAsString + "\n\n\n")
}
} catch {
self.textField.stringValue = ("Caught:", error.localizedDescription)
}
case .failure(let error):
self.textField.stringValue = ("Network Error:", error.localizedDescription)
}
}
I am trying to get data with flickr API and I wrote a simple code with Alamofire and swiftyJSON to get this data from flickr but I am able to print the data size but when I try to print the json, my catch block runs. my codes are shown below
func getPhotos(completion: #escaping CompletionHandler) -> Void {
let parameter: [String: Any] = [
"method": PHOTOS_METHOD,
"api_key": FLICKR_API_KEY,
"per_page": PER_PAGE,
"page": PAGE,
"format": FORMAT_TYPE,
"nojsoncallback": JSON_CALLBACK]
Alamofire.request(FLICKR_URL, method: .get, parameters: parameter, encoding: JSONEncoding.default, headers: HEADER).responseString { (response) in
if response.result.error == nil {
guard let data = response.data else {return}
do {
if let json = try JSON(data: data).array {
print(json)
}
completion(true)
} catch {
print("eroorrrre")
completion(false)
}
print("CALL CORRECT")
print(data)
completion(true)
}
else {
completion(false)
debugPrint(response.result.error as Any)
}
}
}
my console log
eroorrrre
CALL CORRECT
128 bytes
I am not sure what I am doing wrong here, any help would be appriciated
Try this
Alamofire.request(FLICKR_URL, method: .get, parameters: parameter, headers: HEADER).responseJSON { response in // call responseJSON instead of responseString
if response.result.isSuccess { // If http request is success
let json: JSON = JSON(response.result.value!) // JSON format from SwiftyJSON (I suppose you are using it)
guard let data = json.array else { // You suppose that json is array of objects
print("Unexpected JSON format")
completion(false)
}
print(data)
completion(true)
} else {
print(response.error)
completion(false)
}
}
I have an api manager class in my swift application and it has a server login with username and password.
I want to know how to create a completion handler for it that when the server responses with 200 status code, the function handles that response and for example performs a segue in the viewcontroller.
I did not find any tutorials for this. Thanks for your help!
EDIT 1:
What i need is: The completion handler is immediately run when the function is called. I want the completion handler run after server responds.
And this is my login function:
public class func Login(username: String, password: String, complitionHandler: #escaping (Int) -> Void) {
let urlS = "http://server.com/" + "login.php"
let url = URL(string: urlS)
var request = URLRequest(url: url!)
request.httpMethod = "POST"
let body = "username=\(username.lowercased())&password=\(password)"
request.httpBody = body.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data, error == nil else {
print(error!)
print("error")
logedIn = 2
return
}
do{
let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? NSDictionary
if let parseJson = json {
let code = parseJson["status"] as! String
if code == "200" {
print("loged inn")
logedIn = 1
}else if code == "400" {
print("uuuser/pass error")
logedIn = 0
}
}
}catch{
print("json error")
logedIn = 2
}
}
task.resume()
DispatchQueue.main.async {
complitionHandler(logedIn)
}
}
And how i call the function in my ViewController:
Manager.Login(username: "1", password: "1") { (i) in
switch i {
case 0:
print("user/pass error")
case 1:
print("loged in")
self.performSegue(withIdentifier: "toMain", sender: self)
case 2:
print("json error")
default:
()
}
}
You have all of the pieces in place. You just need to move your call to the completion handler to the correct place:
}catch{
print("json error")
logedIn = 2
}
DispatchQueue.main.async {
complitionHandler(logedIn)
}
}
task.resume()
Also note that method names should start with lowercase letters so your Login function should be named login.
Now you can use this login method like:
login(username: someUsername, password: somePassword) { (result) in
if result == 1 {
// success - do your segue
} else if result == 0 {
// bad username/password
} else {
// some error
}
}