NSUserdefault to same data from JSON - json

Good morning, I have this block of code that I am using to get exchange rates from an API JSON file. I use this function to convert a result to different currencies. I am trying to add functionality to store the data so, when offline, it still shows a result with the last downloaded JSON file data.
I was thinking maybe use NSUserdefault? but not too sure where...
I am already using this to check if online or not.
if Reachability.isConnectedToNetwork(){
// connected do something}
else{
// do something else }
Thank you for any pointer and any kind of help that could send me in the right direction.
func exchangeRatefunc (mycurrency: String, mapaye: Double) {
let apiEndPoint = "https://api.fixer.io/latest?base=USD"
guard let url = NSURL(string: apiEndPoint) else {
self.infoLabel.text = NSLocalizedString("Error getting exchange rates.", comment: "")
print("Url is not valid")
return
}
let urlRequest = NSURLRequest(url: url as URL)
let session = URLSession.shared
let task = session.dataTask(with: urlRequest as URLRequest) { (data, response, error) in
guard error == nil else {
print(error?.localizedDescription ?? 0)
return
}
guard let data = data else {
print("No data received")
self.infoLabel.text = NSLocalizedString("You appear to be offline!", comment: "")
return
}
do {
guard let exchangeDict = try JSONSerialization.jsonObject(with: data, options: []) as? [String: AnyObject] else {
print("Could not convert JSON to dictionary")
self.infoLabel.text = NSLocalizedString("No conversion Available.", comment: "")
return
}
print(exchangeDict.values)
if let rates = exchangeDict["rates"] {
let currencies = [mycurrency]
for currency in currencies {
if let rate = rates[currency] as? Double {
self.exchangeRates.append("1 USD = \(rate) " + currency)
let myprefcurdisplay = mapaye * rate
OperationQueue.main.addOperation({
self.myPreferedCurrencyPayLabel.updateWithText("\(myprefcurdisplay.roundTo(places: 2)) \(currency)")
if let date = exchangeDict["date"] as? String {
self.infoLabel.text = "\(currency)/USD" + NSLocalizedString(" rates updated on" + " \(date)", comment: "")
}
})
}
}
}
}
catch {
print("Error trying to convert JSON to dictionary")
}
}
task.resume()
}

Related

How else can I format the data? swift parse json - The data couldn’t be read because it isn’t in the correct format

The JSON data is
[
{"id":0,"temperature":77,"humidity":0.22,"timeCaptured":"2020-09-25T19:33:27.9733333"},
{"id":0,"temperature":77,"humidity":0.22,"timeCaptured":"2020-09-25T20:38:53.3"},
{"id":0,"temperature":85,"humidity":0.25,"timeCaptured":"2020-09-25T20:38:53.3"},
{"id":0,"temperature":88,"humidity":0.22,"timeCaptured":"2020-09-28T15:30:00"},
// ...
]
My structs look like this
struct TemperatureDataModel: Codable{
let id: Int?
let temperature: Double?
let humidty: Double?
let timeCaptured: String?
}
My function looks like this
func getTemperData(){
//Create the URLs
let temperatureDataUrl = URL(string: "https://weatherstationapi.azurewebsites.net/api/TemperatureSensor/GetData")
// let WindDataUrl = URL(string: "https://weatherstationapi.azurewebsites.net/api/WindData/GetAllData")
guard let requestURLTemp = temperatureDataUrl else { fatalError() }
//Create URL request
var request = URLRequest(url: requestURLTemp)
//Specifiy HTTP Method to use
request.httpMethod = "GET"
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.setValue("Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiaWxpci50YWlyaUB0dHUuZWR1IiwiaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvbmFtZWlkZW50aWZpZXIiOiI4MjEzYzhhMy1iODgxLTQ4NmUtOGUyMC1mZmNlMDlmNGY0ZjgiLCJuYmYiOiIxNjAyNTI2NDI1IiwiZXhwIjoiMTYwNTExODQyNSJ9.t1qnYyXLpRRJ3YQfhgLrylBqL_pdKOnKVMgOfG9IuVc", forHTTPHeaderField: "Authorization")
//Send HTTP Request
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data else {return}
print(data)
//Use parseJSON to convert data
let TemperatureData = parseJSON(data: data)
// for singleValue in TemperatureData {
// print(singleValue.temperautre)
// }
//read list
guard let TemperatureDataModel = TemperatureData else {return}
print("Temperature is : \(TemperatureDataModel.temperature)")
// Check if error took place
if let error = error {
print("Error took place \(error)")
return
}
//Read HTTP Response Status Code
// if let data = data, let dataString = String(data: data, encoding: .utf8) {
// print("Response data string:\n \(dataString)")
// }
}
task.resume()
}
and then my JSON decoder function looks like this
func parseJSON(data: Data) -> TemperatureDataModel? {
var returnValue: TemperatureDataModel?
do {
let returnValue = try JSONDecoder().decode([TemperatureDataModel].self, from: data)
} catch {
print("Error took place \(error).")
}
return returnValue
}
I've looked at 6+ stack overflow posts now and still cannot figure It out. Ive tried putting my model in [] for an array, moving where the function is called, changing the jsondecoder function and more and nothing works.
I think you have to give a format to the date before you parse the data
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
Your issue there is that you are creating another returnValue that is not being returned. You need also change the return type to [TemperatureDataModel]
func parseJSON(data: Data) -> [TemperatureDataModel]? {
do {
return try JSONDecoder().decode([TemperatureDataModel].self, from: data)
} catch {
print("Error took place \(error).")
return nil
}
}

Parsed JSON not updating on api call for a long time

For some reason the JSON object from parsing doesnt update after network calls to and api we built. I check the endpoint and now for a fact it updates right away. I have a timer being called every 10 sec to make the call but the parsed json doesnt update until after a minute or so. I have tried putting it on the main thread and that still doesnt work. Here is my code:
#objc func getLaunches() {
let simulator = UserDefaults.standard.string(forKey: self.launchSimulator)
if(simulator == self.password){
print("they are the same")
}
guard let launchUrl = URL(string: launchesURL) else {
return
}
let request = URLRequest(url: launchUrl)
DispatchQueue.main.async { [weak self] in
let task = URLSession.shared.dataTask(with: request, completionHandler: {
(data, response, error) -> Void in
if let error = error {
print(error)
return
}
// Parse JSON data
if let data = data {
self?.launches.removeAll()
self?.launches = (self!.parseJsonData(data: data))
let nextlaunch = self?.launches[0]
// Reload table view
self?.hours = nextlaunch?.time
self?.yearMonth = nextlaunch?.date
var fulltime = self?.yearMonth
fulltime!.insert("-", at: fulltime!.index(fulltime!.startIndex, offsetBy: 4))
fulltime!.insert("-", at: fulltime!.index(fulltime!.startIndex, offsetBy: 7))
fulltime = fulltime! + " "
fulltime = fulltime! + self!.hours
let fullFormatter = DateFormatter()
fullFormatter.dateFormat = "YYYY-MM-dd HH:mm"
fullFormatter.timeZone = TimeZone(abbreviation: "EST")
self?.launchDate = fullFormatter.date(from: fulltime!)
self?.getCountdown()
}
})
task.resume()
}
}
//parse launch info from json to dictionary into launches object
func parseJsonData(data: Data) -> [NextLaunch] {
var launches = [NextLaunch]()
do {
let jsonResult = try JSONSerialization.jsonObject(with: data, options:
JSONSerialization.ReadingOptions.allowFragments) as? NSDictionary
let jsonLaunches = jsonResult?["launches"] as! [NSDictionary]
for jsonLaunch in jsonLaunches {
let launch = NextLaunch()
launch.date = jsonLaunch["date"] as! String
launch.time = jsonLaunch["time"] as! String
if(launch.time == ""){
launch.time = "00:00"
}
launch.mission = jsonLaunch["mission"] as! String
launch.launchpad = jsonLaunch["launch_pad"] as! String
launch.image = jsonLaunch["image"] as! String
launch.delay = jsonLaunch["delayed"] as! String
//show delay image if it is delayed
if(launch.delay == "1"){
self.delayed()
}else{
self.notDelayed()
}
launches.append(launch)
}
} catch {
print(error)
}
return launches
}
You need
DispatchQueue.main.async {
self?.getCountdown()
}
As the response of URLSession.shared.dataTask(with: occurs in a background thread

Having trouble with a json-xcode/swift

I am trying to add values from what
was printed in the json shown by my code
to specific arrays. For example I want
the lat / lng /name from the JSon file and
add it to an array. How would I go about doing this
? I am new to swift and would appreciate the help.
My Json code is in the comments! Thanks
func getBurritosInArea() {
let keyword:String = "burrito"
let urlString =
"https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=\(latitude),\(longitude)&&fields=formatted_address,name,rating&radius=1500&type=restaurant&keyword=(\apikey)"
guard let request = URL(string:urlString) else { return }
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data, error == nil,
let json = try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers),
let results = json as? [String: Any] else { //error handling
return
}
if let placeResults = results["results"] as? [[String: Any]]{
for placeResult in results{
print(placeResult)
}
}
}
}
}
json code:
viewport = {
northeast = {
lat = "40.74642527989272";
lng = "-73.97449797010727"; };
southwest = {
lat = "40.74372562010728";
lng = "-73.97719762989271"; };
};
};
icon = "maps.gstatic.com/mapfiles/place_api/icons/restaurant-71.png"; id = c884c332c5cc1578d0c1d4d7f4d4ad451358c9e6;
name = "Baby Bo's Cantina"; "opening_hours" = { "open_now" = 1; };
Hi Please try below code,
First Create an Array Named aryDict,
func getBurritosInArea()
{
guard let url = URL(string: "your url") else {return}
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let dataResponse = data,
error == nil else {
print(error?.localizedDescription ?? "Response Error")
return }
do{
//here dataResponse received from a network request
let jsonResponse = try JSONSerialization.jsonObject(with:
dataResponse, options: []) as? NSArray
// print(jsonResponse?.value(forKey: STR_NAME) as Any )
let array = NSArray.init(array: jsonResponse ?? [])
var aryDict = NSMutableArray.init(array: array)
// self.tblView.reloadData()
print(aryDict)
} catch let parsingError {
print("Error", parsingError)
}
}
task.resume()
}

Swift 3 - How can i extract elements from a json?

Hello i want to extract certain elements from a json .
CODE: .
var datas:[Usuario]?
struct Usuario : Codable {
let correo: String?
let contrasena: String?
}
let urlString = "http://localhost:8080/swiftdb/logear.php"
guard let url = URL(string: urlString) else { return }
URLSession.shared.dataTask(with: url) { (data, response, error) in
if error != nil {
print(error!.localizedDescription)
}
guard let data = data else { return }
//Implement JSON decoding and parsing
do {
//Decode retrived data with JSONDecoder and assing type of Article object
let articlesData = try JSONDecoder().decode([Usuario].self, from: data)
//Get back to the main queue
DispatchQueue.main.async {
}
} catch let jsonError {
print(jsonError)
}
}.resume()
What i want to do, is compare what it is in the json with a textfield ,so it can go to a different view.
Json Contains:
[{"correo":"unknown11#hotmail.com","contrasena":"12345"},{"correo":"lalo123#hotmail.com","contrasena":"12121"},{"correo":"kokunz#hotmail.com","contrasena":"11111"},{"correo":"a","contrasena":"a"}]
Textfield Contains: {Something which the user writes in in. txtEmail.text Ex.}
Before the answer, you can check the Apple Reference about JSON and parsing . https://developer.apple.com/swift/blog/?id=37
if let dictionary = netoxJsonVariable as? [String: Any] {
for (key, value) in dictionary {
// access all key / value pairs in dictionary
// I am not sure that you can reach key with string but I think you are searching for this.
//if(value == "searchedMailAddress"){//then}
//if(key == "correoLikeKey"){//then}
}
}
I used a for statement so
let {newVar} = self.{yourJson}
for item in {newVar}! {
let {anotherVar} = item.{field}
let {anotherVar2} = item.{field2}

Cannot convert JSON Data in Swift 3

I'm converting a project from Obj-c to Swift 3 and I can't get it to read JSON responses from our web methods. As far as I can see, the code looks like a good conversion from it's Obj-c counterpart, but the JSONSerilaization is having trouble.
I would post the old Obj-c, but it's spread across several NSURLConnection delegate methods. I can post this if required?
Swift 3:
// Set up the URL request
var getString : String = "https://TheWebMethod"
guard let url = URL(string: getString) else {
print("Error: cannot create URL")
return
}
let urlRequest = URLRequest(url: url)
// set up the session
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
// make the request
let task = session.dataTask(with: urlRequest) {
(data, response, error) in
// check for any errors
guard error == nil else {
print("error calling GET on Method")
print(error)
return
}
// make sure we got data
guard let responseData = data else {
print("Error: did not receive data")
return
}
// parse the result as JSON, since that's what the API provides
do {
guard let result = try JSONSerialization.jsonObject(with: responseData, options: []) as? [String: AnyObject] else {
print("error trying to convert data to JSON")
return
}
print("The result is: " + result.description)
guard let resultTitle = result["title"] as? String else {
print("Could not get title from JSON")
return
}
print("The title is: " + resultTitle)
} catch {
print("error trying to convert data to JSON")
return
}
}
task.resume()
Example JSON output when run through browser:
[{"id":"3","Initials":"TL","FullName":"Tony Law","LoginName":"test","Password":"password","EmailAddress":"myemailaddress","MobileTelNo":"0123456789","SecToken":"Secret"}]