So am making a login application that sends username and password, and the server replies with access token....am trying to save this token for later use but i really cant. here is my code, and the server response incase you need it
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var PhoneNumber: UITextField!
#IBOutlet weak var Password: UITextField!
//***************************************LogIn**********************************************\\
#IBAction func Login(_ sender: UIButton) {
guard let url = URL(string: "https://goollyapp.azurewebsites.net/Token") else {return}
var request = URLRequest(url: url)
request.httpMethod = "POST"
let postString = "username=" + PhoneNumber.text! + "&password="+Password.text!+"&grant_type=password"
print(postString)
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let response = response {
print(response)
}
}
task.resume()
}
}
Where you declare the json variable replace with:
let json = try? JSONSerialization.jsonObject(with: data, options: []) as! [String: Any]
Then you can access the token with:
let token = json["access_token"] as! String
(after receiving a successful JSON response)
You can then implement a Singleton as follows:
class Token {
// Can't init a singleton
private init() { }
static let sharedInstance = Token()
var tokenString = ""
}
If you want to save the token in a variable for using it later , try this
(key being the corresponding name of the key in your response object)
let token = httpResponse?.allHeaderFields["SECURITY-TOKEN"] as? String
let task = URLSession.shared.dataTask(with: request) { data, response, error in
let httpResponse = response as? HTTPURLResponse
let token = httpResponse?.allHeaderFields["SECURITY-TOKEN"] as? String
print(token)
}
task.resume()
Related
How would I get it so I can receive specific information, for example, the "username" and put it on the userName.text label. (The Google.com string I put in is just for simplicity.)
I haven't been able to find a solution that fits my problem exactly. Thank you!
The following is the code in my class:
#IBOutlet weak var myData: UITextView!
#IBOutlet weak var userName: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "https://google.com")!
var request = URLRequest(url: url)
request.httpMethod = "GET"
NSURLConnection.sendAsynchronousRequest(request, queue: OperationQueue.main) {
(response, data, error) in
if let data = data {
do {
let json = try JSONSerialization.jsonObject(with: data, options: [])
print(json)
} catch {
print(error)
}
...
You can try
let url = String(format: "your url")
guard let serviceUrl = URL(string: url) else { return }
var request = URLRequest(url: serviceUrl)
request.httpMethod = "GET"
request.setValue("Application/json", forHTTPHeaderField: "Content-Type")
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
if let response = response {
print(response)
}
if let data = data {
do {
let json = try JSONSerialization.jsonObject(with: data, options: []) as! [String:[[String:String]]]
let arr = json["data"]!
print(arr.first!["username"])
print(arr.first!["password"])
} catch {
print(error)
}
}
}.resume()
Or better
struct Root: Codable {
let data: [Datum]
}
struct Datum: Codable {
let username, password: String
}
With
let json = try JSONDecoder().decode(Root.self,from: data)
print(json.data.first?.usernamae)
print(json.data.first?.password)
I am trying to figure out how to send a verification code to a user when signing up to verify their number. I am trying to follow online resources (code below), but it doesn't seem to work. When I put in a phone number as an 'xxxyyyzzzz' or 'xxx-yyy-zzzz' number (with a country code formatted just as the number, no '+') I get an error in my console that the phone number is not properly formatted. I'm not sure if this is the source of my issue, but as of now it seems the most probable. What confuses me about this is that online I am told that either of these formats will work. Any help? Code:
static let path = Bundle.main.path(forResource: "Config", ofType: "plist")
static let config = NSDictionary(contentsOfFile: path!)
private static let baseURLString = config!["serverUrl"] as! String
#IBOutlet var countryCodeField: UITextField! = UITextField()
#IBOutlet var phoneNumberField: UITextField! = UITextField()
#IBAction func sendVerification(_ sender: Any) {
if let phoneNumber = phoneNumberField.text,
let countryCode = countryCodeField.text {
SignUp2ViewController.sendVerificationCode(countryCode, phoneNumber)
}
}
static func sendVerificationCode(_ countryCode: String, _ phoneNumber: String) {
let parameters = [
"via": "sms",
"country_code": countryCode,
"phone_number": phoneNumber
]
let path = "start"
let method = "POST"
let urlPath = "\(baseURLString)/\(path)"
var components = URLComponents(string: urlPath)!
var queryItems = [URLQueryItem]()
for (key, value) in parameters {
let item = URLQueryItem(name: key, value: value)
queryItems.append(item)
}
components.queryItems = queryItems
let url = components.url!
var request = URLRequest(url: url)
request.httpMethod = method
let session: URLSession = {
let config = URLSessionConfiguration.default
return URLSession(configuration: config)
}()
let task = session.dataTask(with: request) {
(data, response, error) in
if let data = data {
do {
let jsonSerialized = try JSONSerialization.jsonObject(with: data, options: []) as? [String : Any]
print(jsonSerialized!)
} catch let error as NSError {
print(error.localizedDescription)
}
} else if let error = error {
print(error.localizedDescription)
}
}
task.resume()
}
You are calling a POST but passing the values into the URL as if it's a GET. You should use the httpBody for POST.
I was following a tutorial (https://www.simplifiedios.net/swift-php-mysql-tutorial/) and I hit a dead end.
I keep getting this error:
2018-11-10 19:34:31.931565-0500 team[85540:1441900] [MC] Reading from private effective user settings.
Error Domain=NSCocoaErrorDomain Code=3840 "No value." UserInfo={NSDebugDescription=No value.}
This is my code:
import UIKit
class ViewController: UIViewController {
let URL_SAVE_TEAM = "http://cgi.soic.indiana.edu/~kim882/journey/createteam.php"
#IBOutlet weak var textFieldName: UITextField!
#IBOutlet weak var textFieldMember: UITextField!
#IBAction func Login(_ sender: UIButton) {
//created NSURL
let requestURL = URL(string: URL_SAVE_TEAM)
//creating NSMutableURLRequest
let request = NSMutableURLRequest(url: requestURL!)
//setting the method to post
request.httpMethod = "POST"
//getting values from text fields
let teamName = textFieldName.text
let memberCount = textFieldMember.text
//creating the post parameter by concatenating the keys and values from text field
let postParameters = "name="+teamName!+"&member="+memberCount!;
//adding the parameters to request body
request.httpBody = postParameters.data(using: String.Encoding.utf8)
//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 \(String(describing: error))")
return
}
do { //parsing the response
let myJSON = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary //converting resonse to NSDictionary
//parsing the json
if let parseJSON = myJSON {
//creating a string
var msg : String!
//getting the json response
msg = parseJSON["message"] as! String?
//printing the response
print(msg)
}
} catch {
print(error)
}
}
//executing the task
task.resume()
}
}
am making a post request to a server and the server responds with some data,am storing the recived data in a variable named json now am trying to access this variable from other functions but i get an error : "use of unresolved identifier "json"
here is the code incase u need it
#IBAction func Login(_ sender: UIButton) {
guard let url = URL(string: "url was here..lol") else {return}
var request = URLRequest(url: url)
request.httpMethod = "POST"
let postString = "data to be posted"
print(postString)
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let response = response {
print(response)
}
if let data = data {
do {
let json = try? JSONSerialization.jsonObject(with: data, options: []) as! [String: Any]
let token = json?["access_token"] as! String
print (json)
}
}
}
task.resume()
}
You need to declare the variables you want to share between functions on the class level so they can be accessed by each function in the class. token is an instance property of the class with this implementation, so each class instance has its own variable called token that can be accessed anywhere inside the class.
class MyViewController: UIViewController {
var token = ""
#IBAction func Login(_ sender: UIButton) {
guard let url = URL(string: "url was here..lol") else {return}
var request = URLRequest(url: url)
request.httpMethod = "POST"
let postString = "data to be posted"
print(postString)
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let response = response {
print(response)
}
if let data = data {
guard let json = (try? JSONSerialization.jsonObject(with: data, options: [])) as? [String: Any] else {return}
guard let receivedToken = json["access_token"] as? String else {return}
self.token = receivedToken
otherFunction()
}
}
task.resume()
}
func otherFunction(){
print(token)
}
}
I have a performance problem implementing a REST client related with long delays. Problem is not present on my Android app or any REST client adding to browsers so it is not related with backend issues.
this is my function for executing API call:
func getRecordsMethod(completion: #escaping ((_ result: Data) -> Void)){
let defaults = UserDefaults.standard
let username = defaults.object(forKey: "username") as! String
let password = defaults.object(forKey: "password") as! String
let loginString = String(format: "%#:%#", username, password).description
let loginData = loginString.data(using: String.Encoding.utf8)
let base64LoginString = loginData?.base64EncodedString()
let url = URL (string: apiURL + getPersonalBests )
var request = URLRequest(url: url!)
request.httpMethod = "GET"
request.setValue("Basic " + base64LoginString!, forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode == 200 {
completion(data!)
}
}
task.resume()
}
and how I call it in my ViewController :
override func viewDidLoad() {
super.viewDidLoad()
populateRecords()
}
func populateRecords(){
self.records.removeAll()
apiRestManager.getRecordsMethod() {
(result: Data) in
let json = JSON(data: result)
for (_, subJson) in json {
// processing response- adding to personalBestTable
}
DispatchQueue.main.async {
self.personalBestTable.reloadData()
}
}
}
The biggest issue is that after function populateRecords is being started there is delay approx 2-3 seconds after a call is visible on my backend (after that processing and table reload is made instantly)
Can anyone give me a hint how I can optimize requests speed?
Getting the data from UserDefault on main threat may cause the delay.
Change your viewDidLoad method with following code
override func viewDidLoad() {
super.viewDidLoad()
let concurrentQueue = DispatchQueue(label: "apiQueue", attributes: .concurrent)
concurrentQueue.async {
populateRecords()
}
}