Swift : football-data API doesn't work - json

I'm trying to use football-data.org api. I wrote some code same with before I did sample. But this api is using token and I didn't figured out how to add and do that.
I did these code and nothing happens :
func getData(){
let url = NSMutableURLRequest(URL: NSURL(string: "http://api.football-data.org/v1/soccerseasons/424/fixtures"))
url.addValue("my token is here", forHTTPHeaderField: "X-Auth-Token")
url.HTTPMethod = "GET"
let task = NSURLSession.sharedSession().dataTaskWithRequest(url) { (data, response, error) in
self.setLabels(data!)
}
task.resume()
}
func setLabels(MatchData: NSData){
//var jsonError: NSError?
do{
let json = try NSJSONSerialization.JSONObjectWithData(MatchData, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
if let sys = json["soccerseason"] as? NSDictionary{
if (sys["href"] as? String) != nil{
let seasonsUrl = sys["href"] as! String
print(seasonsUrl)
}
}
}
catch{
//error
}
}
I'm not getting value or something. I'm new with json. What's wrong in my code?

"soccerseason" is in "_links", like this:
if let links = json["_links"] as? [String:AnyObject],
sys = links["soccerseason"] as? [String:String],
seasonsUrl = sys["href"] {
print(seasonsUrl)
}
This is for the main one.
I've also noticed there's one (the same one, actually) in each dictionary in the main array:
if let fixtures = json["fixtures"] as? [[String:AnyObject]] {
for fixture in fixtures {
if let links = fixture["_links"] as? [String:AnyObject],
sys = links["soccerseason"] as? [String:String],
seasonsUrl = sys["href"] {
print(seasonsUrl)
}
}
}
The URLs are in the _links part in each dictionary in the fixtures array:
if let fixtures = json["fixtures"] as? [[String:AnyObject]] {
for fixture in fixtures {
if let links = fixture["_links"] as? [String:[String:String]],
season = links["soccerseason"],
seasonsUrl = season["href"],
awayTeam = links["awayTeam"],
awayTeamUrl = awayTeam["href"] {
print(seasonsUrl)
print(awayTeamUrl)
}
}
}
And awayTeamName and homeTeamName are at the same level than _links inside the array of dictionaries:
if let fixtures = json["fixtures"] as? [[String:AnyObject]] {
for fixture in fixtures {
if let awayTeamName = fixture["awayTeamName"] as? String,
homeTeamName = fixture["homeTeamName"] as? String {
print(awayTeamName)
print(homeTeamName)
}
}
}

Related

How can I restore my old task with a new one in swift?

I have question about tasks. I need to restore my request, I change link and fetch some new data to that link and show them on my table view. User can change link according to picker view, I have a variable for it and I replaced in link and thats working correct too but in second request can make a thread I assume it is very bad question but I am new in swift. How can I make second or more request in one function.
Here my function code :
func fetchArticles(){
let urlRequest = URLRequest(url: URL(string: "my_api_link_is_here")!)
let task = URLSession.shared.dataTask(with: urlRequest) { (Data,URLResponse,Error) in
if Error != nil {
print(Error!)
}
self.articles = [Article]()
do{
let json = try JSONSerialization.jsonObject(with: Data!, options: .mutableContainers) as! [String: AnyObject]
if let articlesFromJson = json["articles"] as? [[String:AnyObject]] {
for articleFromJson in articlesFromJson {
let article = Article()
let source = articleFromJson["source"] as![String: AnyObject]
let name = source["name"]
if let title = articleFromJson["title"] as? String, let author = name as? String , let desc = articleFromJson["description"] as? String, let url = articleFromJson["url"] as? String, let imageToUrl = articleFromJson["urlToImage"] as? String {
article.author = author as String
if articleFromJson.index(forKey: "description") != nil {
article.desc = desc as String
}else{
article.desc = "empty"
}
article.headline = title as String
article.imageUrl = imageToUrl as String
article.url = url as String
}
self.articles?.append(article)
}
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}catch let Error {
print(Error)
}
}
task.resume()
}

how to get the indexpath of selected Action sheet picker Swift

I have got myself into confusion.I need someone to help me.
I have been trying to use Action sheet picker and everything was good but I need to get the selected item. How can I do it?
ActionSheetMultipleStringPicker.show(withTitle: "Select Country", rows: [
countriesArray,], initialSelection: [0],
doneBlock: {
picker, indexes, values in
print("values = \(values)")
print("indexes = \(indexes)")
print("picker = \(picker)")
DispatchQueue.main.async {
// Update UI
self.performSegue(withIdentifier: "pdfsegue", sender: nil)
}
return
}, cancel:
{
ActionMultipleStringCancelBlock in return
}, origin: sender)
these are my arrays:
var emiratesArray = [String]()
var emiratesIdArray = [Int]()
I am getting values into my arrays from JSON:
let url = NSURL(string: EMIRATES_URL)
URLSession.shared.dataTask(with: (url as?URL)!, completionHandler: {(data,response,error) ->
Void in
if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary
{
print(jsonObj.value(forKey: "data")!)
if let messageArray = jsonObj.value(forKey: "data") as? NSArray
{
for message in messageArray
{
if let messageDict = message as? NSDictionary
{
if let data = data {
let successmessage = jsonObj.value(forKey: "success") as? Int
if(successmessage == 1)
{
if let emirate_name = messageDict.value(forKey: "emirate_name")
{
self.emiratesArray.append(emirate_name as! String)
print(emirate_name)
}
if let company_id = messageDict.value(forKey: "id")
{
self.emiratesIdArray.append(company_id as! Int)
print(company_id)
}
} else
{
}
}
}
}
}
}
}).resume()
someone help me How to get the selected item?If i were using tableview then I would have taken the id from the [indexpath.row] but in UIActionsheet picker,I dont know how get the id of selected value. Please someone help me please
I didn't found any Custom Class in your given code. You can create a class like below:
class Emirate: NSObject {
var id: Int
var name: String
init(id: Int, name: String) {
self.id = id
self.name = name
}
override var description: String {
return self.name
}
}
I have override the description property because ActionSheetMultipleStringPicker shows description of object given in the array if it is not String.
Declare your Emirate array
var emiratesArray = [Emirate]()
Your API request and Parsing should be like this:
let url = NSURL(string: "EMIRATES_URL")
URLSession.shared.dataTask(with: (url as?URL)!, completionHandler: {(data,response,error) ->
Void in
if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary
{
print(jsonObj.value(forKey: "data")!)
if let messageArray = jsonObj.value(forKey: "data") as? NSArray
{
for message in messageArray
{
if let messageDict = message as? NSDictionary
{
if let data = data {
let successmessage = jsonObj.value(forKey: "success") as? Int
if(successmessage == 1)
{
if let emirate_name = messageDict.value(forKey: "emirate_name") as? String, let company_id = messageDict.value(forKey: "id") as? Int
{
self.emiratesArray.append(Emirate(id: company_id, name: emirate_name))
print(emirate_name)
}
} else
{
}
}
}
}
}
}
}).resume()
Now feed your action sheet self.emiratesArray
ActionSheetMultipleStringPicker.show(withTitle: "Select Country", rows: [
self.emiratesArray], initialSelection: [0],
doneBlock: {
picker, indexes, values in
print("values = \(values)")
print("indexes = \(indexes)")
print("picker = \(picker)")
DispatchQueue.main.async {
// Update UI
self.performSegue(withIdentifier: "pdfsegue", sender: nil)
}
return
}, cancel:
{
ActionMultipleStringCancelBlock in return
}, origin: sender)
You will now get the selected Emirate class objects in values array.
N.B- This code is just to give you an idea about how it can work.

Struct Init with JSON and flatMap

I'm having a problem with the following code. I'm downloading a list of actors in JSON and I want to populate Struct Actor with the received data. Everything works great until I try to flatMap on the received data and try to initialize the struct Actor. When I try to compile the code i get the error: Cannot assign value of type '()' to type [Actor]. The error corresponds to a line in viewDidLoad actorsList = downloadActors() Would anybody have any recommendation who to solve this?
import UIKit
func downloadActors() {
var request = URLRequest(url: URL(string: "url...")!)
request.httpMethod = "POST"
let postString = "actorGroup=\("Superhero")"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
DispatchQueue.main.async {
guard let data = data, error == nil else {
print("error=\(error)")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
print("error : statusCode should be 200 but is \(httpStatus.statusCode)")
print("response = \(response)")
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode == 200 {
do {
let json = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String: AnyObject]
guard let actorsJSON = json?["response"] as? [[String : AnyObject]] else {
return
}
} catch {
print("catch error")
}
}
}
}
task.resume()
}
func loadActors() -> [Actor] {
if let actors = actorsJSON as? [[String : AnyObject]] {
return actors.flatMap(Actor.init)
}
}
let actorsArray = loadActors()
class MasterViewController: UITableViewController {
var actorsList = [Actor]()
var detailViewController: DetailViewController? = nil
var objects = [Any]()
override func viewDidLoad() {
super.viewDidLoad()
actorsList = downloadActors()
print(actorsList)
Struct Actors is as follows:
struct Job {
let actorGroup: String
let actorName: String
}
extension Actor: JSONDecodable {
init?(JSON: [String : AnyObject]) {
guard let actorGroup = JSON["actorGroup"] as? String, let actorName = JSON["actorName"] as? String else {
return nil
}
self. actorGroup = actorGroup
self. actorName = actorName
}
}
let listActors = actorsJSON as? [[String : AnyObject]] {
Should be:
if let listActors = actorsJSON as? [[String : AnyObject]] {
Edit: For more info I'd like to add Vadian's comment:
Very confusing code. What does the function in the middle of the do block? Why do you type-check actorsJSON twice? The computed property is let listActors... which should be probably an optional binding (if let ... ). Further .mutableContainers is completely nonsense in Swift. And finally a JSON dictionary is [String:Any] in Swift 3.

parsing a JSON array in Swift

I have this working but it seems like a very manual process and I can't work out how to loop inside a loop (or if I should). Right now I am just testing this with 3 variables, but there will ultimately be about 100. Here's my playground. Is there a way to simplify this so I don't have to manually add each array name?
import Foundation
var json_data_url = "216.92.214.107/data_test.json"
var LRKSFOweekdayDep : [String] = [String]()
var LRKSFOweekendDep : [String] = [String]()
var SFOLRKweekdayDep : [String] = [String]()
let journeysURL:NSURL = NSURL(string: json_data_url)!
let data = NSData(contentsOfURL: journeysURL)!
do {
let json = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
print(json)
if let dep_obj = json as? NSDictionary {
if let array_journey = dep_obj["journey"] as? NSArray{
if let journies = array_journey[0] as? NSDictionary {
if let array_dep = journies["LRKSFOweekdayDep"] as? NSDictionary{
if let dep = array_dep["dep"] as? NSArray {
for var i = 0; i < dep.count; ++i
{
let add = dep[i] as! String
LRKSFOweekdayDep.append(add)
}
print(LRKSFOweekdayDep)
}
}
}
if let journies = array_journey[1] as? NSDictionary {
if let array_dep = journies["LRKSFOweekendDep"] as? NSDictionary{
if let dep = array_dep["dep"] as? NSArray {
for var i = 0; i < dep.count; ++i
{
let add = dep[i] as! String
LRKSFOweekendDep.append(add)
}
print(LRKSFOweekendDep)
}
}
}
if let journies = array_journey[2] as? NSDictionary {
if let array_dep = journies["SFOLRKweekdayDep"] as? NSDictionary{
if let dep = array_dep["dep"] as? NSArray {
for var i = 0; i < dep.count; ++i
{
let add = dep[i] as! String
SFOLRKweekdayDep.append(add)
}
print(SFOLRKweekdayDep)
}
}
}
}
}
} catch {
print("error serializing JSON: \(error)")
}
You might want to look at using SwiftyJSON to make the parsing easier.
Right now, you have something like:
if let dep = array_dep["dep"] as? NSArray {
for var i = 0; i < dep.count; ++i {
let add = dep[i] as! String
LRKSFOweekendDep.append(add)
}
}
That can be simplified to:
LRKSFOweekendDep = array_dep["dep"] as? [String]
That assumes of course, that you define LRKSFOweekendDep to be optional. If it's not optional, you can do:
LRKSFOweekendDep = array_dep["dep"] as? [String] ?? []
But, it should be optional.
In a comment, you say that there are going to be 100 of these. Rather than having a variable for each, I would have thought that you'd rather keep an array of objects. For example, consider:
struct Journey {
let name: String
let departures: [String]
}
Then, to parse your JSON, you could iterate through the results:
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: [])
var journeys = [Journey]()
if let results = json as? [String: AnyObject], let array = results["journey"] as? [[String: AnyObject]] {
for dictionary in array {
for (name, departures) in dictionary {
if let departureDictionary = departures as? [String: [AnyObject]], let departureList = departureDictionary["dep"] as? [String] {
journeys.append(Journey(name: name, departures: departureList))
}
}
}
}
Finally, I would advise against NSData(contentsOfURL:), because that's synchronous. Use NSURLSession's dataTaskWithURL, which is asynchronous. Also, if you use data! pattern, first check to make sure it's not nil. Otherwise, if data was nil for any reason outside of your control (e.g. the web server is down, internet is temporarily interrupted, etc.), the app will crash rather than handling it gracefully.
Putting that all together, you get something like:
func retrieveJourneys(completionHandler: ([Journey]?, NSError?) -> ()) {
let task = NSURLSession.sharedSession().dataTaskWithURL(journeysURL) { data, response, error in
guard error == nil && data != nil else {
completionHandler(nil, error)
return
}
var json: [String: AnyObject]?
do {
json = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? [String: AnyObject]
} catch let parseError as NSError {
completionHandler(nil, parseError)
}
var journeys = [Journey]()
if let array = json!["journey"] as? [[String: AnyObject]] {
for dictionary in array {
for (name, departures) in dictionary {
if let departureDictionary = departures as? [String: [AnyObject]], let departureList = departureDictionary["dep"] as? [String] {
journeys.append(Journey(name: name, departures: departureList))
}
}
}
}
completionHandler(journeys, nil)
}
task.resume()
}
And then you'd use it like so:
var journeys: [Journey]?
override func viewDidLoad() {
super.viewDidLoad()
retrieveJourneys { journeys, error in
guard error == nil && journeys != nil else { // make sure it didn't have network problem
print(error)
return
}
dispatch_async(dispatch_get_main_queue()) { // now update model on main queue
self.journeys = journeys
// and, for giggles and grins, this is how you might grab the first one and examine it:
let someJourney = self.journeys![0]
print(someJourney.name)
print(someJourney.departures)
}
}
}
Now, the above assumes that you wanted an ordered list of journeys, sorted by the order you received them.
On the other hand, if you didn't care about the order, but wanted an efficient way to retrieve the departures associated with a given key, you might use a dictionary, instead:
func retrieveDepartures(completionHandler: ([String: [String]]?, NSError?) -> ()) {
let task = NSURLSession.sharedSession().dataTaskWithURL(journeysURL) { data, response, error in
guard error == nil && data != nil else {
completionHandler(nil, error)
return
}
var json: [String: AnyObject]?
do {
json = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? [String: AnyObject]
} catch let parseError as NSError {
completionHandler(nil, parseError)
}
var departures = [String: [String]]()
if let array = json!["journey"] as? [[String: AnyObject]] {
for dictionary in array {
for (name, departureObject) in dictionary {
if let departureDictionary = departureObject as? [String: [AnyObject]], let departureList = departureDictionary["dep"] as? [String] {
departures[name] = departureList
}
}
}
}
completionHandler(departures, nil)
}
task.resume()
}
And then:
var departures: [String: [String]]?
override func viewDidLoad() {
super.viewDidLoad()
retrieveDepartures { departures, error in
guard error == nil && departures != nil else {
print(error)
return
}
dispatch_async(dispatch_get_main_queue()) {
self.departures = departures
// and, for giggles and grins, this is how you might grab a list of departures given a particular key
let departureTimes = self.departures!["LRKSFOweekdayDep"]
print(departureTimes)
}
}
}

Grab data from JSON file doesn't work

I try to grab data from JSON (http://www.openligadb.de/api/getmatchdata/bl1/2014/15). I want to get every single game with the goals, location, team ...
I tried this but it won't work.
let url = "http://www.openligadb.de/api/getmatchdata/bl1/2014/15"
//parse url
if let JSONData = NSData(contentsOfURL: NSURL(string: url)!) {
if let json = (try? NSJSONSerialization.JSONObjectWithData(JSONData, options: [])) as? NSDictionary {
//handle json
}
}
It doesn't steps in the 2nd if-statement (if let json = (try?...).
I hope you could help me.
Edit get data of dictionaries:
//Data Team1
if let team1 = object["Team1"] as? NSDictionary {
if let name = team1["TeamName"] as? String {
print("Name Team1: \(name)")
}
if let logo = team1["TeamIconUrl"] as? String {
print("Logo Team1: \(logo)")
}
// Etc.
}
What you need to do is to understand your JSON structure: you have an array first, not a dictionary.
This array has dictionaries, each of them holding an array of dictionaries.
It may sound complex but it's actually simple, you just follow the structure of your JSON and decode the values with the correct type.
In JSON, an array starts with [ and a dictionary starts with { (also, be careful not to confuse this JSON syntax with Swift's arrays and dictionaries one).
Your code could be something like this, for example:
do {
let url = "http://www.openligadb.de/api/getmatchdata/bl1/2014/15"
if let url = NSURL(string: url),
JSONData = NSData(contentsOfURL: url),
jsonArray = try NSJSONSerialization.JSONObjectWithData(JSONData, options: []) as? NSArray {
for object in jsonArray {
if let goalsArray = object["Goals"] as? NSArray {
// Each "goal" is a dictionary
for goal in goalsArray {
print(goal)
if let name = goal["GoalGetterName"] as? String {
print("Name: \(name)")
}
if let ID = goal["GoalID"] as? Int {
print("ID: \(ID)")
}
// Etc.
}
}
}
}
} catch {
print(error)
}
UPDATE: you're almost there! But "Team1" is a dictionary, not an array. :)
Here's the solution:
do {
let url = "http://www.openligadb.de/api/getmatchdata/bl1/2014/15"
if let url = NSURL(string: url),
JSONData = NSData(contentsOfURL: url),
jsonArray = try NSJSONSerialization.JSONObjectWithData(JSONData, options: []) as? NSArray {
for object in jsonArray {
if let team1 = object["Team1"] as? NSDictionary {
if let name = team1["TeamName"] as? String {
print("Name Team1: \(name)")
}
if let logo = team1["TeamIconUrl"] as? String {
print("Logo Team1: \(logo)")
}
}
}
}
} catch {
print(error)
}