I am trying to read json date from url and parse it in Tableview using swift. how can I make variable "jsonResult " as global ?
or please guide me how can I populate the tableview with this data from json.
let urlPath = "http://omanevents.net/OmanEventsApp/testPullDate.php"
let url = NSURL(string: urlPath)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url!, completionHandler: {data, response, error -> Void in
if (error != nil) {
println("error")
}else {
let jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
for var index = 0; index < jsonResult["Events"]?.count ; ++index {
println(jsonResult["Events"]?[index]["Location"])
}
}
})
task.resume()
I would highly recommend that you have a look at this tutorial.
http://www.raywenderlich.com/85578/first-core-data-app-using-swift
It shows you how to deal with core data but in the example it uses adding things to tableView, and saving data for use of the app at later stages. Ray Wnderlich is a great website.
Related
I am trying to get JSON image urls from a different endpoint. At the moment I am able to call first endpoint fetching data for exercise name, description and id. Then for each exercise I am trying to call to a different endpoint using an ID value so then I can get image url for the specific exercise.
The only idea I had is to create nested API call to a different endpoint, but I am getting too many syntax errors and it does not work.
The question is how can I reformat my code to remove existing syntax errors.
Here is my code. I never actually seen a way to do this type of API calls.
func parseData() {
fetchedExercise.removeAll()
let url = URL(string: urlPath)!
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
if error != nil {
print("Error while parsing JSON")
}
else {
do {
if let data = data,
let fetchedData = try JSONSerialization.jsonObject(with: data, options: .mutableLeaves) as? [String:Any],
let exercises = fetchedData["results"] as? [[String: Any]] {
for eachExercise in exercises {
if eachExercise["license_author"] as! String == "wger.de" {
let name = eachExercise["name"] as! String
let description = eachExercise["description"] as! String
let id = eachExercise["id"] as! Int
}
It has been fixed by adding missing closure brackets at the end which were causing syntax error while trying to run the code.
I am getting unexpected values back when i am parsing my json data from my api, i may be doing something wrong here as i'm quite new to swift but i was getting correct values before when i was receiving one "key" but now i have added two i cannot seem to parse the values properly.
This is the json collected from the address my code is receiving, (sorry if its hard to read havn't worked out how to do line breaks yet in my ruby api)(as long as its functional im not too worried at the moment)
{
"ratings":{
"elements":{"Ready Position":[{"description":"Neutral Grip","values":"1,2,3,4,5"},{"description":"Back Straight (Concave ir Convex?)","values":"1,2,3,4,5"},{"description":"Body Low \u0026 Feet a little more than sholder width apart","values":"1,2,3,4,5"},{"description":"Weight on Balls of Feet","values":"1,2,3,4,5"},{"description":"Head Up","values":"1,2,3,4,5"},{"description":"Sholder Blades Close","values":"1,2,3,4,5"},{"description":"Eyes Drilled","values":"1,2,3,4,5"}],"Split Step":[{"description":"Ready Position Conforms","values":"Yes,No"},{"description":"Body Position Low","values":"1,2,3,4,5"},{"description":"Legs Loaded/Prepared","values":"1,2,3,4,5"}]}
},
"comments":{}
}
Now, My swift code looks like this
let playerAPIurl = "http://linkcoachuat.herokuapp.com/api/v1/session/element?organisation=" + userorganisation + "&group=" + urlGroupSelected + "&sport=" + usersport
print(playerAPIurl)
var request = URLRequest(url: URL(string: playerAPIurl)!)
request.httpMethod = "GET"
let configuration = URLSessionConfiguration.default
let session = URLSession(configuration: configuration, delegate: nil, delegateQueue: OperationQueue.main)
let task = session.dataTask(with: request) { (data, response, error) in
if error != nil {
print("ERROR")
}
else{
do {
let json = try JSONSerialization.jsonObject(with: data!) as? [String: AnyObject]
print(json)
And this is the output im getting from this print(json)
Optional({
comments = {
};
ratings = {
};
})
I know i shouldnt be getting anything more in the comments part, but in the ratings part there should be some data?
so after recieving the json and dealing with parsing it i need to access this part of it ["ratings"]["elements"] and after that im all good
thanks in advance and please bare in mine im very new to swift
Thanks
Try the below code. The url used in below code has your JSON data. This code is printing the output correctly.
func testApi(){
let url = URL(string: "https://api.myjson.com/bins/jfccx")
let session = URLSession.shared
let request = URLRequest(url: url!)
//create dataTask using the session object to send data to the server
let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
guard let data = data, error == nil else {
return
}
do {
//create json object from data
if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
print(json)
}
} catch let error {
print(error.localizedDescription)
}
})
task.resume()
}
I'm new to Swift and while making one of the tutorials (fairly old) which involves getting credentials from a server through php which returns a JSON, but I'm stuck with the error Ambiguous reference to member jsonObject(with:options:) in the json var, I've searched and trying applying the different solutions but to no avail. :(
Thank you for your time and help.
here is my code:
let userEmail = userEmailTextField.text;
let userPassword = userPasswordTextField.text;
if((userEmail?.isEmpty)! || (userPassword?.isEmpty)!) {
displayMyAlertMessage(userMessage: "All Fields are required.")
return;
}
let myUrl = URL(string: "/UserLogin.php");
var request = URLRequest(url:myUrl!);
request.httpMethod = "POST";
let postString = "email\(userEmail)&password=\(userPassword)";
request.httpBody = postString.data(using: String.Encoding.utf8);
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, URLResponse, error in
if error != nil {
//print = ("error=\(error)");
return
}
var err: Error?
var json = JSONSerialization.jsonObject(with: data, options: .mutableContainers, error: &err) as? NSDictionary
if let parseJSON = json {
var resultValue:String = parseJSON["status"] as String!;
print("result: \(resultValue)")
if(resultValue == "Success") {
//Login Succesful
UserDefaults.standard.set(true, forKey:"isUserLoggedIn");
UserDefaults.standard.synchronize();
self.dismiss(animated: true, completion: nil);
}
}
}
task.resume()
There are two major issues:
The actual error occurs because the response parameter in the completion block is wrong. Rather than the type URLResponse it must be a parameter label / variable.
let task = URLSession.shared.dataTask(with: request) { data, response, error in
Since you are using Swift 3 there is no error parameter in jsonObject(with. The method does throw, you need a do - catch block. And – as always – the option .mutableContainers is completely useless in Swift. Omit the parameter.
do {
if let parseJSON = try JSONSerialization.jsonObject(with: data) as? [String:Any],
let resultValue = parseJSON["status"] as? String {
print("result: ", resultValue)
if resultValue == "Success" {
//Login Succesful
UserDefaults.standard.set(true, forKey:"isUserLoggedIn")
self.dismiss(animated: true, completion: nil)
}
}
} catch {
print(error)
}
Some other notes:
To check the text fields safely use optional binding
guard let userEmail = userEmailTextField.text, !userEmail.isEmpty, let userPassword = userPasswordTextField.text, !userPassword.isEmpty else {
displayMyAlertMessage(userMessage: "All Fields are required.")
return
}
Declare Swift constants always as let (for example resultValue)
Do not use NSArray / NSDictionary in Swift. Use native types.
Do not use parentheses around if conditions and trailing semicolons. They are not needed in Swift.
UserDefaults.standard.synchronize() is not needed either.
String.Encoding.utf8 can be reduced to just .utf8.
I am trying to populate a UITable with a json result. I call a function that gets the json from the server and stores the result in NSDictionary. I want to be able to use this collection, and then populate a table. I run into a problem however because for the func numberOfRowsInSection I need the count of the collection, and since my json result is within another function inside a try/catch I cant seem to return the value.
This is what I have for the function which I call in ViewDidLoad():
func getSubjects() -> NSDictionary{
let myUrl = NSURL(string: "www.mydomain.com/script.php");
let request = NSMutableURLRequest(url:myUrl as! URL)
let user_id = UserDetails[0]
request.httpMethod = "POST";
let postString = "user_id=\(user_id)";
request.httpBody = postString.data(using: String.Encoding.utf8);
let task = URLSession.shared.dataTask(with: request as URLRequest){
data, response, error in
if error != nil {
print("error=\(error)")
return
}
var err: NSError?
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
if let parseJSON = json {
let resultValue: NSDictionary = parseJSON["subjects"] as! NSDictionary
}
} catch let error as NSError {
err = error
print(err!);
}
}
task.resume();
}
If I print resultValue I get what I need, in this example being:
{
1 = (
Maths,
Lecture
);
2 = (
Science,
Lecture
);
3 = (
English,
Seminar
);
}
But the confusion is, how do I go about returning this value? and where? and how would I implement it in the table? If I try to return resultValue when I parse the JSON I get the error that it is unexpected non-void return in void function and if I try to return the value at the end of the function, I get an unresolved identifier error
I feel I am implementing this incorrectly. I have checked many tutorials on this, and no one seems to populate a table with a POST JSON so I don't know how to go about returning the value, or the proper method of implementation. Any help would be greatly appreciated!
The problem your having is that the dictionary hasn't been retrieved by the time you try to return it. You can use an asynchronous callback to get the dictionary after it has been retrieved from your database.
func getSubjects(callback: #escaping (NSDictionary)-> Void){
let myUrl = NSURL(string: "www.mydomain.com/script.php");
let request = NSMutableURLRequest(url:myUrl as! URL)
let user_id = UserDetails[0]
request.httpMethod = "POST";
let postString = "user_id=\(user_id)";
request.httpBody = postString.data(using: String.Encoding.utf8);
let task = URLSession.shared.dataTask(with: request as URLRequest){
data, response, error in
if error != nil {
print("error=\(error)")
return
}
var err: NSError?
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
if let parseJSON = json {
let resultValue: NSDictionary = parseJSON["subjects"] as! NSDictionary
callback(resultValue)
}
} catch let error as NSError {
err = error
print(err!);
}
}
task.resume();
}
and then you would call this function like...
getSubjects(callback: {(resultValue)-> Void in
print(resultValue)
//here you could set your tableView data equal to the values in the dictionary that was just received and then call self.tableView.reloadData to update your table view
})
So perhaps in the viewDidLoad() function of you UITableViewController or in the viewDidAppear(_:), depending on the life cycle of your view, you would call getSubjects(...) as i have shown above and then when the callback is called you call self.tableView.reloadData() as I have explained in the function call. If you are unsure how to setup a tableview datasource and delegate then you should probably open another question for that
EDIT
In response to your comment asking how to use the retrieved value from your server as a variable available to your whole class, you could do something like this...
class: ExampleViewController {
var resultsDictionary: [Int: [String: String]]?
override func viewDidLoad(){
getSubjects(callback: {(resultValue)-> Void in
resultsDictionary = resultValue
})
}
//Use the actual getSubjects function I have already shown you above
func getSubjects(){...}
}
I am trying to follow a tutorial - which failed and having found some code on stack over flow Make REST API call in Swift decided to try this approach instead. The following code is a copy and paste (I know!) with a change of URL yet I seem to be getting an error printed to the console rather than the JSON - the error being largely unhelpful - 0x0000000000000000
The JSON appears to print to the browser window so I am not fully sure what might be wrong with this approach? Please could someone provide some help as to why this might not be working?
Thanks
var url : String = "http://www.flickr.com/services/rest/?method=flickr.test.echo&format=json&api_key=d6e995dee02d313a28ed4b799a09b869"
var request : NSMutableURLRequest = NSMutableURLRequest()
request.URL = NSURL(string: url)
request.HTTPMethod = "GET"
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(), completionHandler:{ (response:NSURLResponse!, data: NSData!, error: NSError!) -> Void in
var error: AutoreleasingUnsafeMutablePointer<NSError?> = nil
let jsonResult: NSDictionary! = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.MutableContainers, error: error) as? NSDictionary
if (jsonResult != nil) {
println(jsonResult);
} else {
// couldn't load JSON, look at error
println(error);
}
})
The problem is that the call returns data in JSONP not JSON
Your code would work ok if tested with a correct JSON like http://ip.jsontest.com
To make it work with Flickr you have to modify it as follows:
var json_str:NSString = NSString(data: data, encoding: NSUTF8StringEncoding)
json_str = json_str.substringFromIndex(14)
json_str = json_str.substringToIndex(json_str.length-1)
let new_data:NSData = json_str.dataUsingEncoding(NSUTF8StringEncoding)!
var error: AutoreleasingUnsafeMutablePointer<NSError?> = nil
let jsonResult: NSDictionary! = NSJSONSerialization.JSONObjectWithData(new_data, options:NSJSONReadingOptions.MutableContainers, error: error) as? NSDictionary
if (jsonResult != nil) {
println(jsonResult);
} else {
// couldn't load JSON, look at error
println(error);
}