Posting data to database with Alamofire failed - ios

I am having an issue with posting data using Alamofire. I am making a comment box. I grab user data from the server and post his comment using his information with his comment on the article id, but when I post it sends no information to the server! I see only empty data.
The user data are successfully loaded from the server and I can see it in the console using the print accountDetails but after posting nothing is shown!
Breakpoint gives valid data too!
My code:
class DetailsViewController: UIViewController {
var data: JSON?
var userData = [JSON]()
var accountDetails = ["name": "", "email": "", "phone": ""]
#IBOutlet weak var CommentTableView: UITableView!
#IBOutlet weak var CommentTXTField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
getUserData()
print("Account:\(accountDetails)")
if let id = Helper.getUserId() {
ContactBtn.isHidden = false
} else {
ContactBtn.isHidden = true
}
}
#IBAction func AddCommentBTN(_ sender: Any) {
let commentTXT = CommentTXTField.text
print(commentTXT!)
let name = self.accountDetails["name"]
let mobile = self.accountDetails["phone"]
let email = self.accountDetails["email"]
let articleId = data!["id"].string!
API.AddComment(articleId: articleId, name: name!, email: email!, phone: mobile!, message: commentTXT!) { (error: Error?, success: Bool) in
if success {
print("Registerd Successfuly")
} else {
print("Faile To Comment")
}
}
}
func getUserData() {
guard let UserId = Helper.getUserMob() else { return }
let url = "https://site.co/apis/getprofile.php?mob=" + UserId
AF.request(url).validate().responseJSON { [self] response in
switch response.result
{
case .failure(let error):
print(error)
case .success(let value):
let json = JSON(value)
if let id = json["data"]["id"].string {
print("id: \(id)")
}
self.accountDetails["name"] = json["data"]["name"].string
self.accountDetails["email"] = json["data"]["email"].string
self.accountDetails["phone"] = json["data"]["phone"].string
}
}
}
}
API.AddComment function
class func AddComment(articleId: String, name: String, email: String, message: String, completion: #escaping (_ error: Error?, _ success: Bool)->Void){
let url = URLs.AddComment
let parameters = [
"article_id": articleId,
"name": name,
"email": email,
"message": message
]
AF.request(url, method: .post, parameters: parameters, encoding: URLEncoding.default , headers: nil)
.validate(statusCode: 200..<300)
.responseJSON { response in
switch response.result
{
case .failure(let error):
completion(error, false)
print(error)
case .success(let value):
let json = JSON(value)
if let id = json["data"]["id"].string {
print("id: \(id)")
completion(nil, true)
}
}
}
}

Related

passing data (json) to another controller in swift 5.2 con Alamofire

I have a Login view that asks for a card and password. I consult an API and if the entered data is correct, it sends me a JSON like this. Which return has the button method? How do I send that data to the other view? I occupy Alamofire 5.0 and have my Model class.
#IBAction func myButtonIngresarAction(_ sender: Any) {
guard let carnet = self.txtCarnet.text else {return}
guard let contrasena = self.txtPassword.text else {return}
let ingresologinmodel = IngresoLoginModel(usuario: carnet, password: contrasena)
self.apiCall(IngresoLoginModel: ingresologinmodel){
(result) in
switch result{
case .success(let json):
print(json)
**//This is where I want to send that json with the data to the other view. ******
case .failure(let err):
print(err.localizedDescription)
}
}
}
enum ApiErros: Error {
case custom(message : String)
}
typealias Handler = (Swift.Result<Any?, ApiErros>) -> Void
func apiCall(IngresoLoginModel: IngresoLoginModel, completionHandler: #escaping Handler)
{
let header: HTTPHeaders = [
.contentType("application/json")
]
AF.request("https://url/xxxx/api/Login", method: .post, parameters: IngresoLoginModel,
encoder: JSONParameterEncoder.default, headers: header).response{ response in
debugPrint(response)
switch response.result{
case .success(let data):
do{
let json = try JSONDecoder().decode([LoginModel].self, from: data!)
print(json)
if response.response?.statusCode == 200{
completionHandler(.success(json))
}else{
completionHandler(.failure(.custom(message: "Por favor verifica tu internet")))
}
}
catch
{
print(error)
completionHandler(.failure(.custom(message: "Problemas")))
}
case .failure(let err):
print(err.localizedDescription)
}
}
}
Class model
struct LoginModel: Codable {
let idEmpleado: Int
let Nombre: String
let CodEmpleado: String
let password: String
let idPerfil: Int
let activo: Int
let Descripcion: String
let idRegion: Int
let correo: String
}
This is the json that the Api sends me the data changes them for these example
{
"idEmpleado": 1,
"nombre": “test”,
"codEmpleado": “000000”,
"password": “123”,
"idPerfil": 4,
"activo": 1,
"Descripcion": “test”,
"idregion": 1,
"correo": “test#test.com"
}
many way like create a variable to save this json in OtherViewController and call, self?.otherViewController.json = json
https://learnappmaking.com/pass-data-between-view-controllers-swift-how-to/
use didSet
var page = [Datas]() {
didSet {
self.myVariable = page[0].date!
}
}
typealias Handler = (Swift.Result <[LoginModel]?, ApiErros>) -> Void
#IBAction func myButtonIngresarAction(_ sender: Any) {
guard let carnet = self.txtCarnet.text else {return}
guard let contrasena = self.txtPassword.text else {return}
let ingresologinmodel = IngresoLoginModel(usuario: carnet, password: contrasena)
self.apiCall(IngresoLoginModel: ingresologinmodel){
(result) in
switch result{
case .success(let json):
print(json)
//Here is that I do not know how to send it to the other controller all the json
let viewControllerB = HomeMenuViewController()
viewControllerB.datosPersonales = json!
self.navigationController?.pushViewController(viewControllerB, animated: true)
case .failure(let err):
print(err.localizedDescription)
}
}
}
second controller
class HomeMenuViewController: UIViewController {
#IBOutlet weak var mylabel: UILabel!
var datosPersonales = [LoginModel]()
override func viewDidLoad() {
super.viewDidLoad()
print("***************")
print(datosPersonales)
print("***************")
}
}

Wait response result before proceeding next code iOS swift

I'm beginner in iOS swift.
I have a problem: when I do a network request, the compiler executed the code below without waiting the server response.
func callingRiderLoginCopy(userID: String, Password:String, completeCode: Int) {
print("I am in callingRiderLoginCopy And Complete verification Code is \(completeCode)")
let parameters : [String : Any] = ["userId": userID, "password": Password, "verificationCode": completeCode]
guard let url = URL(string: "\(Constents.baseURL)/rider/logIn") else {
print("Invalid URL")
return
}
AF.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default)
.responseJSON { response in
switch response.result {
case .success:
if let result = response.data {
do {
let resultIs = try JSONDecoder().decode(RiderLoginCopy.self, from:result)
self.riderSuc = resultIs.success // Strore the success state in riderSuc
print("Data is riderSuc ** \(self.riderSuc)")
if let results = resultIs.user {
print("This data came from RiderLoginCopy API : \(resultIs)")
self.setToken = KeychainWrapper.standard.set(resultIs.token!, forKey: "token")
self.retrivedToken = KeychainWrapper.standard.string(forKey: "token")!
print("Retrived Token ::: \(self.retrivedToken)")
}
} catch {
print(error)
}
}
case .failure(let error):
print(error)
}
}
}
#IBAction func verifyAct(_ sender: UIButton) {
let userId = enteredUserID
KeychainWrapper.standard.string(forKey: "Password")!
let password = enteredPassword
KeychainWrapper.standard.string(forKey: "UserID")!
let completeCode:Int = Int(textField1.text! + textField2.text! + textField3.text! + textField4.text!)!
self.callingRiderLoginCopy(userID: userId, Password: password, completeCode: completeCode)
if self.riderSuc == 1 {
let storyboard = UIStoryboard(name: "Rider", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "signin2VC") as! SignIn2VC
vc.verifyCode = completeCode
self.navigationController?.pushViewController(vc, animated: true)
}else{
print("Plese Try Try again RiderSuc is not equal to 1 !: ")
}
}
Use a closure completionHandler: parameter in your function definition of type (String?) -> Void to know when the response is received and then proceed with the rest of the code.
Modify your function from:
func callingRiderLoginCopy(userID: String, Password: String, completeCode: Int) {
To this:
func callingRiderLoginCopy(userID: String, Password:String, completeCode: Int, completionHandler: #escaping (String?) -> Void) {
And return the retrivedToken when it's received successfully and return nil when it's not.
And when you call this method modify your call from this:
self.callingRiderLoginCopy(userID: userId, Password: password, completeCode: completeCode)
To this:
self.callingRiderLoginCopy(userID: userId, Password: password, completeCode: completeCode) { token in
// Do stuff related to token
}

Realm with Alamofire and Swift

I am making my first attempt at using Realm in Swift. I have my model setup and I successfully receive the response using Alamofire and I map it to the object. I am then attempting to store the data in realm. It creates the object, but the values are the default values and not what is received from the backend. What am I missing? Here's the model:
import Foundation
import ObjectMapper
import RealmSwift
#objcMembers class LoginResponseModel: Object, Mappable {
dynamic var status = ""
dynamic var id = UUID().uuidString
dynamic var userId = 0
dynamic var authToken = ""
required convenience init?(map: Map) {
self.init()
}
convenience init(status: String, userId: Int, authToken: String) {
self.init()
self.status = status
self.userId = userId
self.authToken = authToken
}
override static func primaryKey() -> String? {
return "id"
}
func mapping(map: Map) {
status <- map["status"]
userId <- map["user_id"]
authToken <- map["auth_token"]
}
}
Here is where I attempt to save it:
APIHelper.shared.login(username: username!, password: password!, success: { (result) in
if let login = result {
if (login.status != "failed") {
let userId = login.userId
let authToken = login.authToken
UserDefaults.standard.setValue(String(userId), forKey: "USERID")
UserDefaults.standard.setValue(authToken, forKey: "AUTHTOKEN")
UserDefaults.standard.synchronize()
vc.modalPresentationStyle = .fullScreen
do {
let realm = try! Realm()
try realm.write {
realm.add(login)
}
} catch(let error) {
print(error)
}
InstanceID.instanceID().instanceID { (result, error) in
if let error = error {
print(error)
} else if let result = result {
self.sendToken(userId: String(userId), authToken: authToken, fcmToken: result.token)
}
}
self.present(vc, animated: true, completion: nil)
}
}
Any ideas?
API call:
public func login(username: String, password: String, success: #escaping(_ response: LoginResponseModel?) -> Void, failure: #escaping(_ error: Error?) -> Void) {
let url = "\(baseUrl)appLogin"
AF.request(url, method: .post, parameters: ["emailOrPhone": username, "password": password]).responseString { response in
print(type(of: response).self)
switch response.result {
case .success(let json):
let resp = LoginResponseModel(JSONString: json)
success(resp)
case .failure(let error):
failure(error)
}
}
}
I get the object here:
let login = realm.objects(LoginResponseModel.self).first
Value of object:
status = ""
id = "1820A5D4-A714-4774-9707-4709ED39B570"
userId = 0
authToken = ""

Token not getting empty after logout swift

i have a swift application which uses API for authentication everything works fine and when users logout, the login token is supposed to get cleared so that the new user's details can be collected and the new Token passed into the header but i noticed that when I try login in another user, the previous users token remains in the header and thereby preventing the new user from login in. I clear the login values on logout button pressed but i have no idea why the token value remains in the header. my codes are shown below
let defaults = UserDefaults.standard
var isLoggedIn : Bool {
get {
return defaults.bool(forKey: LOGGED_IN_KEY)
}
set {
defaults.set(newValue, forKey: LOGGED_IN_KEY)
}
}
var authToken: String {
get {
return defaults.value(forKey: TOKEN_KEY) as? String ?? ""
}
set {
defaults.set(newValue, forKey: TOKEN_KEY)
}
}
var userUsername: String {
get {
return defaults.value(forKey: USER_USERNAME) as? String ?? ""
}
set {
defaults.set(newValue, forKey: USER_USERNAME)
}
}
//MARK :- LOGGIN
func findUserByUserName(completion: #escaping CompletionHandler) -> Void {
Alamofire.request(URL_USER_BY_USERNAME, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: TOKEN_HEADER).validate().responseJSON { (response) in
print("URL USER BY HEADER \(self.authToken)")
if response.result.error == nil {
guard let data = response.data else {return}
let jsonString = String(data: data, encoding: .utf8)
print(jsonString as Any)
self.setUserInfo(data: data)
completion(true)
}
else {
completion(false)
debugPrint("ERROR 22222\(response.result.error as Any)")
}
}
}
func setUserInfo(data: Data) -> Void {
do {
let json = try JSON(data: data)
let pk = json["pk"].intValue
let username = json["username"].stringValue
let email = json["email"].stringValue
let firstName = json["first_name"].stringValue
let lastName = json["last_nameme"].stringValue
print("THE USERNAME IZZZZ \(username)")
UserDataService.instance.setUserData(pk: pk, username: username, email: email, firstName: firstName, lastName: lastName)
} catch {
print(error)
}
func loginUser(email: String, password: String, completion: #escaping CompletionHandler) -> Void {
let usernameEmail = email.lowercased()
let body: [String: Any] = [
"username": usernameEmail,
"email": "",
"password": password,
]
Alamofire.request(URL_LOGIN, method: .post, parameters: body, encoding: JSONEncoding.default, headers: HEADER).validate().responseJSON { (response) in
if response.result.error == nil {
print("LOGIN SUCCESFULL \(self.authToken)")
do {
guard let data = response.data else {return}
let jsonString = String(data: data, encoding: .utf8)
print("HELLOOO \(jsonString as Any)")
let json = try JSON(data: data)
self.authToken = json["key"].stringValue
self.userUsername = email
self.isLoggedIn = true
completion(true)
print("LOGIN SUCCESFULL TOKEN1111 \(self.authToken)")
} catch {
print("errorrrrr")
}
} else {
completion(false)
debugPrint("ERROR YENNNNN \(response.result.error as Any)")
}
}
}
//MARK :- LOGGIN
func findUserByEmail(completion: #escaping CompletionHandler) -> Void {
let body: [String: Any] = [
"username": AuthService.instance.userUsername,
]
Alamofire.request(URL_USER_BY_EMAIL, method: .put, parameters: body, encoding: JSONEncoding.default, headers: TOKEN_HEADER).validate().responseJSON { (response) in
print("URL USER BY HEADER \(self.authToken)")
if response.result.error == nil {
guard let data = response.data else {return}
print("USERUSERNAME \(self.authToken)")
let jsonString = String(data: data, encoding: .utf8)
print(jsonString as Any)
self.setUserInfo(data: data)
completion(true)
}
else {
completion(false)
debugPrint("ERROR 22222\(response.result.error as Any)")
}
}
}
Token Constant
let TOKEN_HEADER = [
"Authorization": "Token \(AuthService.instance.authToken)",
"Content-Type": "application/json; charset=utf-8"
]
UserService
func setUserData(pk: Int, username: String, email: String, firstName: String, lastName: String) -> Void {
self.pk = pk
self.username = username
self.email = email
self.firstName = firstName
self.lastName = lastName
}
func logoutUser() -> Void {
self.pk = 0
self.username = ""
self.email = ""
self.firstName = ""
self.lastName = ""
AuthService.instance.isLoggedIn = false
AuthService.instance.authToken = ""
AuthService.instance.userUsername = ""
}
Logout
#IBAction func logoutPressed(_ sender: Any) {
UserDataService.instance.logoutUser()
print("LOGOUT TOKEN \(AuthService.instance.authToken)")
UserDataService.instance.setUserData(pk: 0, username: "", email: "", firstName: "", lastName: "")
AuthService.instance.authToken = ""
NotificationCenter.default.post(name: NOTIFY_USER_DATA_DID_CHANGE, object: nil)
dismiss(animated: true, completion: nil)
}
further codes would be supplied on request
The problem is you think that whenever you call TOKEN_HEADER you get the lastest value from
let TOKEN_HEADER = [
"Authorization": "Token \(AuthService.instance.authToken)",
"Content-Type": "application/json; charset=utf-8"
]
but this doesn't happen as the variable get it's value from first initialization whatever the token value was , so you have to refactor sending the the header to Alamofire , by hardcoding the string again like this
func findUserByUserName(completion: #escaping CompletionHandler) -> Void {
let updated_HEADER = [
"Authorization": "Token \(AuthService.instance.authToken)",
"Content-Type": "application/json; charset=utf-8"
]
Alamofire.request(URL_USER_BY_USERNAME,
method: .get, parameters: nil, encoding: JSONEncoding.default,
headers:updated_HEADER).validate().responseJSON { (response) in }
}

how to get JSON data from login?

I am able to fetch data using Oauth in Alamofire for login successfully but how to get JSON data in Another viewController.
func loginAccess(){
let headers = [
"Content-Type": "application/x-www-form-urlencoded"
]
let parameters = [
"UserName": username_textfield.text! as String,
"Password": password_textfield.text! as String,
"grant_type": "password",
]
// let url = NSURL(string: "http://192.168.100.5:84/Token")!
Alamofire.request("http://192.168.100.5:84/Token", method: .post, parameters: parameters, encoding: URLEncoding.httpBody, headers: headers).responseJSON { (response:DataResponse<Any>) in
switch(response.result) {
case .success(_):
if response.result.value != nil{
let statusCode = (response.response?.statusCode)!
print("...HTTP code: \(statusCode)")
if let JSON = response.result.value {
print("JSON: \(JSON)")
// }
}
if statusCode == 200{
self.view.makeToast(message: "Welcome !!")
self.performSegue(withIdentifier: "mainview", sender: self)
}else{
self.view.makeToast(message: "Username or password invalid")
}
}
break
case .failure(_):
print(response.result.error!)
break
}
}
}
modal class
class Login{
var access_token = String()
var token_type = String()
var expire_in = String()
var username = String()
var masterid = String()
var name = String()
var access = String()
var issued = String()
var expries = String()
init(loginJson:JSON){
self.access_token = loginJson["access_token"].stringValue
self.token_type = loginJson["token_type"].stringValue
self.expire_in = loginJson["expires_in"].stringValue
self.username = loginJson["userName"].stringValue
self.masterid = loginJson["MasterID"].stringValue
self.name = loginJson["Name"].stringValue
self.access = loginJson["Access"].stringValue
self.issued = loginJson[".issued"].stringValue
self.expries = loginJson[".expires"].stringValue
}
}
is this able to access JSON data in Another ViewController or we need another function? if this is possible in same function then how
it could be solved?
Replace this with your code
func getlogin(){
let headers = [
"Content-Type": "application/x-www-form-urlencoded"
]
let parameters = [
"UserName": username_textfield.text! as String,
"Password": password_textfield.text! as String,
"grant_type": "password",
]
// let url = NSURL(string: "http://192.168.100.5:84/Token")!
Alamofire.request("http://192.168.100.5:84/Token", method: .post, parameters: parameters, encoding: URLEncoding.httpBody, headers: headers).responseJSON { (response:DataResponse<Any>) in
switch(response.result) {
case.success(let data):
print("success",data)
let statusCode = (response.response?.statusCode)!
if statusCode == 200{
self.view.makeToast(message: "Welcome !!")
// self.performSegue(withIdentifier: "mainview", sender: self)
}else{
self.view.makeToast(message: "Username or password invalid")
}
self.myResponse = JSON(data)
let login = Login(loginJson: self.myResponse)
DispatchQueue.main.async(execute: { () -> Void in
self.performSegue(withIdentifier: "pass_data", sender: login)
})
case.failure(let error):
print("Not Success",error)
}
}
}
you can add this also
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "pass_data" {
if let eventsVC = segue.destination as? secondViewController,
let loginData = sender as? Login {
eventsVC.login_details = loginData
}
}
}
in your second view controller you shuold add variable like this var
login_details : Login? to get JSON data
You can pass value using closure .
Create Method
func loginAccess(callBack: (_ responseObject : [Any]) -> Void) -> Void{
if let JSON = response.result.value {
callBack(JSON as Any) // here data passed
}
}
if statusCode == 200{
self.view.makeToast(message: "Welcome !!")
self.performSegue(withIdentifier: "mainview", sender: self)
}else{
self.view.makeToast(message: "Username or password invalid")
callBack([:] as Any)
}
}
Calling method
self.loginAccess { (responseObject) in
print(responseObject) // this is your data
//create your model here
}
How to get data from this login?
func onlinecheckin(){
self.password.resignFirstResponder()
let password1 = password.text;
if let user1 = user.text {
// To trim the characters to remove the empty space
let username = user1.trimmingCharacters(in: CharacterSet.whitespaces)
let passwordnya = password1!.trimmingCharacters(in: CharacterSet.whitespaces)
//Send user data to server side
let myUrl = URL(string: "https://link/jgcm/login.php")!
var request = URLRequest(url: myUrl)
request.httpMethod = "POST"
let postString = "user=\(username) & password=\(passwordnya)"
request.httpBody = postString.data(using: String.Encoding.utf8)
task = URLSession.shared.dataTask(with: request as URLRequest) { data, response, error in
print("response online checking =\(String(describing: response))")
if error != nil {
task.cancel() // To cancel uploading the task.
self.AlertMessage("Error. Please press Login button again.");
print("error=\(String(describing: error))")
return
}
if let datadownload = data {
resultlogin = NSString(data: datadownload, encoding: String.Encoding.utf8.rawValue)!.replacingOccurrences(of: " ", with: "");
print("result of online checking:\(resultlogin)")
}
DispatchQueue.main.async(execute: { () -> Void in
if resultlogin.contains("already") {
let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "menu")
self.present(secondViewController!,animated: true,completion: nil)
} else {
self.AlertMessage("User atau Password Salah");
}
})
}
task.resume()
}}

Resources