Call two API's and build structure - iOS - Swift - ios

i know this is common but couldn't find answers. I thought of using dispatchGroups but not sure how I could do
Requirement: API 1 gives id, I need to construct url with that id and call another API to fetch imageUrl and then build struct with imageUrl
struct Item {
let itemId: String?
let quantity: String?
let itemImageUrl: String?
}
struct InitialDetails: Codable {
let id: String
let quantity: String
}
struct ImagePathData: Codable {
let imageUrl: String
}
API 1:
{
items: [{
id: "1",
quantity: "10"
}]
}
API 2
{
itemImagePath: "https://itemizedUrl/fish.png"
}
Code
func fetchData() -> [Item] {
URLSession.shared.dataTask(with: url) { (data, response, error) in
var items: [Items] = []
let initialData = try JSONDecoder().decode([InitialDetails].self, from: data)
for info in initialData {
var imageUrlPath: String?
let imageDataUrl = "https://itemizedUrl.com/\(info.id)"
URLSession.shared.dataTask(with: imageDataUrl) { (data, response, error) in
imageUrlPath = try JSONDecoder().decode(ImagePathData.self, from data)
}
let item = Item(itemId: initialData.id,
quantity: initialData.quantity,
itemImageUrl: imageUrlPath)
items.append(item)
}
return items
}
}
I know this is not right..pls advice how I could achieve this scenario

You need a completion with a dispachGroup
func fetchData(completion:#escaping([Item]) -> ()) {
var items: [Items] = []
let g = DispatchGroup()
URLSession.shared.dataTask(with: url) { (data, response, error) in
do {
let initialData = try JSONDecoder().decode([InitialDetails].self, from: data)
for info in initialData {
g.enter()
let imageDataUrl = "https://itemizedUrl.com/\(info.id)"
URLSession.shared.dataTask(with: imageDataUrl) { (data, response, error) in
do {
let imageUrlPath = try JSONDecoder().decode(ImagePathData.self, from data)
let item = Item(itemId: initialData.id,
quantity: initialData.quantity,
itemImageUrl: imageUrlPath.imageUrl)
items.append(item)
g.leave()
} catch {
print(error)
}
}
}
} catch {
print(error)
}
g.notify(queue:.main) {
completion(items)
}
}
}

Related

How can i use this new get method for other models?

class Network {
func getingData(completion : #escaping ([Model]) -> ()) async {
guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else { return }
do {
let (data, _) = try await URLSession.shared.data(from: url)
if let posts = try? JSONDecoder().decode([Model].self, from: data) {
completion(posts)
}
}
catch {
print("error")
}
}
}
You could try something like this approach, where getData works with Decodable, as was mentioned in the previous answer.
In this particular example an array of Decodable.
struct Post: Decodable, Identifiable {
let userId: Int
let id: Int
let title: String
let body: String
var comments: [Comment]?
}
struct Comment: Decodable, Identifiable {
let postId: Int
let id: Int
let name: String
let email: String
let body: String
}
struct ContentView: View {
let client = Network()
#State var posts: [Post] = []
var body: some View {
List {
ForEach(posts, id: \.id) { post in
Text(post.title)
}
}
.task {
posts = await client.getData(from: "https://jsonplaceholder.typicode.com/posts")
// all comments from the first post
let comments: [Comment] = await client.getData(from: "https://jsonplaceholder.typicode.com/posts/\(posts[0].id)/comments")
print("\n---> comments: \(comments)")
}
}
}
class Network {
func getData<T: Decodable>(from urlString: String) async -> [T] {
guard let url = URL(string: urlString) else {
print(URLError(.badURL))
return [] // <-- todo, deal with errors
}
do {
let (data, response) = try await URLSession.shared.data(for: URLRequest(url: url))
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
print(URLError(.badServerResponse))
return [] // <-- todo, deal with errors
}
let results = try JSONDecoder().decode([T].self, from: data)
return results
}
catch {
return [] // <-- todo, deal with errors
}
}
}
Is it what you're looking for?
import Foundation
class Network {
func getingData<Model: Decodable>(completion : #escaping ([Model]) -> ()) async {
guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else {
return
}
do {
let (data, _) = try await URLSession.shared.data(from: url)
if let posts = try? JSONDecoder().decode([Model].self, from: data) {
completion(posts)
}
} catch {
print("error")
}
}
}
If so, you only need to declare the Model type as generic. The only thing you need Model to conform is Decodable (the requirement of the JSONDecoder().decode([Model].self, from: data) call).

JSON Decode Function From File Versus Web

SwiftUI is supposed to simplify things- I am bit frustrated as I have been working on the URLSession+JSONDecoder for weeks, I really need some help!
I have a function to load JSON data from a file in Swift and it works as expected. I copy/pasted the function and updated it to get the data via an API, however I receive a compile time error: "Unexpected non-void return value in void function". Is my approach wrong to use a function for JSON over the web?
JSON response:
{
"T":"CSU",
"v":468303,
"vw":1.2838,
"o":1.31,
"c":1.24,
"h":1.38,
"l":1.2001,
"t":1607374800000,
"n":994
}
struct Root2: Codable {
var T: String
var v: Double
var vw: Double
var o: String
var c: String
var h: Double
var l: Double
var t: Double
}
This file-based function works as expected:
let symbolData: [Root2] = load("symbolData.json")
func load<T: Decodable>(_ filename: String) -> T {
let data: Data
guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
else {
fatalError("Couldn't find \(filename) in main bundle.")
}
do {
data = try Data(contentsOf: file)
} catch {
fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}
do {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
} catch {
fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
}
For the web version, I receive compile time error: "Unexpected non-void return value in void function".
Line: return try decoder.decode(T.self, from: data)
func loadURL<T: Decodable>() -> T {
guard let url = URL(string: """)
else {
fatalError("Invalid URL in main bundle.")
}
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) { data, response, error in
do {
if let data = data {
let stringData = String(decoding: data, as: UTF8.self)
print("1 Fetched: \(url)")
print("2 Response: \(stringData)")
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
}
}
catch {
fatalError("Couldn't parse as :\n\(error)")
}
}.resume()
}
Working version after Leo's help!
class Manager: ObservableObject {
#Published var symbols: [Symbol] = []
func loadURL<T: Decodable>(using decoder: JSONDecoder = .msSince1970, completion: #escaping ((T?, Error?) -> Void)) {
let url = URL(string: """)!
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data else {
print("ops")
completion(nil, error)
return
}
print("1 Fetched: \(url)")
print("2 Response:", String(data: data, encoding: .utf8) ?? "")
_ = Data("""
[
{
"open": {
"price": 124.02,
"time": 1657105851499
},
"close": {
"price": 124.96,
"time": 1618647822184
},
"high": 124.64,
"low": 124.65,
"volume": 75665274,
"symbol": "AAPL"
}
]
""".utf8)
do {
completion(try decoder.decode(T.self, from: data), nil)
//completion(try decoder.decode(T.self, from: tempDataForTesting), nil)
} catch {
completion(nil, error)
}
}.resume()
}
}
extension JSONDecoder {
static let msSince1970: JSONDecoder = {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .millisecondsSince1970
return decoder
}()
}
You can't wait for an asynchronous task to finish and return the result. What you need is a completion handler. You would need also to explicitly set the resulting type if you don't pass the resulting type to your decode method and you need to call resume to start your url session data task:
import SwiftUI
struct ContentView: View {
#ObservedObject var manager = Manager()
#State var string: String = "Hello, world!"
var body: some View {
Text(manager.symbol)
.padding()
.onAppear {
manager.load(symbol: manager.symbol) { (symbols: [Symbol]?, error: Error?) in
guard let symbols = symbols else {
print("error:", error ?? "")
string = "JSON could not be parsed"
return
}
for symbol in symbols {
print(symbol.open.price)
print(symbol.open.time)
print(symbol.close.price)
print(symbol.close.time)
print(symbol.high)
print(symbol.low)
print(symbol.volume)
print(symbol.symbol)
DispatchQueue.main.async {
manager.symbols = symbols
}
}
string = "JSON was successufly parsed"
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
class Manager: ObservableObject {
#Published var symbols: [Symbol] = []
#Published var symbol: String = "IBM"
func load<T: Decodable>(symbol: String, using decoder: JSONDecoder = .msSince1970, completion: #escaping ((T?, Error?) -> Void)) {
guard let url = URLComponents(symbol: symbol).url else {
completion(nil, URL.Error.invalidURL)
return
}
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data else {
print("ops")
completion(nil, error)
return
}
print("1 Fetched: \(url)")
print("2 Symbol: \(symbol)")
print("3 Response:", String(data: data, encoding: .utf8) ?? "")
do {
completion(try decoder.decode(T.self, from: data), nil)
} catch {
completion(nil, error)
}
}.resume()
}
}
struct Symbol: Codable {
let open, close: Price
let high, low: Double
let volume: Int
let symbol: String
}
struct Price: Codable {
let price: Double
let time: Date
}
extension JSONDecoder {
static let msSince1970: JSONDecoder = {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .millisecondsSince1970
return decoder
}()
}
extension URLComponents {
init(scheme: String = "https",
host: String = "sandbox.iexapis.com",
path: String = "/stable/stock/market/ohlc",
symbol: String,
token: String = "YOUR_API_TOKEN") {
self.init()
self.scheme = scheme
self.host = host
self.path = path
self.queryItems = [URLQueryItem(name: "symbols", value: symbol),
URLQueryItem(name: "token", value: token)]
}
}
extension URL {
enum Error: String, Swift.Error {
case invalidURL = "Invalid URL"
}
}
This will print
1 Fetched: https://sandbox.iexapis.com/stable/stock/market/ohlc?symbols=IBM&token=YOUR_API_TOKEN
2 Symbol: IBM
3 Response: [{"open":{"price":128.9,"time":1636600302693},"close":{"price":131.44,"time":1662259300134},"high":132.517,"low":130.074,"volume":3403359,"symbol":"IBM"}]
128.9
2021-11-11 03:11:42 +0000
131.44
2022-09-04 02:41:40 +0000
132.517
130.074
3403359
IBM

Swift - parsing wikidata with urlsession and json decoder not working

I'm trying to build a engine that will take a few pieces of data and parse them through a wikidata query...there are two url session tasks here is my code, but for some reason I can't get the functions to perform the networking to execute...what am I missing?
struct BDayWikiDataManager {
func fetchBDayDataFromWikipedia(numMonth: String, numDay: String) -> (String, String, String) {
var personLabelCode = "no value"
var occupationLabelCode = "no value"
var dob = "no value"
var personName = "no value"
var occupationName = "no value"
let firstURL = "https://query.wikidata.org/sparql?query=SELECT%20distinct%20%3Fperson%20%3FpersonLabel%20%3Fdob%20%3Foccupation%20%3FoccupationLabel%20%3Fawards%20%3FawardsLabel%0AWHERE%0A{%0A%20%20%3Fperson%20wdt%3AP31%20wd%3AQ5%3B%0A%20%20%20%20%20%20%20%20%20%20wdt%3AP27%20wd%3AQ30%3B%0A%20%20%20%20%20%20%20%20%20%20wdt%3AP569%20%3Fdob%3B%0A%20%20%20%20%20%20%20%20%20%20wdt%3AP166%20%3Fawards%3B%0A%20%20%20%20%20%20%20%20%20%20wdt%3AP106%20%3Foccupation.%0A%20%20OPTIONAL%20{%3Fperson%20wdt%3AP166%20%3Fawards}%0A%20%20FILTER(DAY(%3Fdob)%20%3D%20\(numDay)).%0A%20%20FILTER(MONTH(%3Fdob)%20%3D%20\(numMonth)).%0A%20%20FILTER(YEAR(%3Fdob)%20%3E%3D%201940).%0A%20%20FILTER%20(%3Foccupation%20in%20(%20wd%3AQ33999%2C%20wd%3AQ639669%2C%20wd%3AQ2066131%2C%20wd%3AQ947873%2C%20wd%3AQ15265344%20)%20)%0A%20%20SERVICE%20wikibase%3Alabel%20{%20bd%3AserviceParam%20wikibase%3Alanguage%20%22[AUTO_LANGUAGE]%22.%20}%20%0A}%0ALIMIT%2050&format=json"
performRequestFirstURL(with: firstURL) { (data, error) in
if error != nil {
print(error as Any)
}
personLabelCode = data!.personLabel
print(personLabelCode)
occupationLabelCode = data!.occupationLabel
dob = data!.dob
}
print(personLabelCode)
let secondUrl = "https://www.wikidata.org/w/api.php?action=wbgetentities&ids=\(personLabelCode)|\(occupationLabelCode)&format=json&props=labels&languages=en"
let _ = performRequestSecondURL(with: secondUrl, personLabel: personLabelCode, occupationLabel: occupationLabelCode) { (data, error) in
if error != nil {
fatalError("performRequestSecondURL failed, error = \(String(describing: error))")
}
personName = data!.personName
occupationName = data!.occupationName
}
return (personName, occupationName, dob)
}
func performRequestFirstURL(with urlString: String, userCompletionHandler: #escaping (FirstURLData?, Error?) -> Void) {
if let url = URL(string: urlString) {
URLSession.shared.dataTask(with: url, completionHandler: { data, response, error in
if let data = data {
let jsonDecoder = JSONDecoder()
do {
let parsedJSON = try jsonDecoder.decode(FirstURLIncomingData.self, from: data)
print(parsedJSON)
let numberOfBindings = parsedJSON.results.bindings.count
let randomBindingNumber = Int.random(in: 0...(numberOfBindings - 1))
let dob = parsedJSON.results.bindings[randomBindingNumber].dob.value
let personLabel = parsedJSON.results.bindings[randomBindingNumber].personLabel.value
let occupationLabel = parsedJSON.results.bindings[randomBindingNumber].occupationLabel.value
let finalData = FirstURLData(dob: dob, personLabel: personLabel, occupationLabel: occupationLabel)
userCompletionHandler(finalData, nil)
} catch {
print(error)
userCompletionHandler(nil,error)
}
}
})
.resume()
}
}
func performRequestSecondURL(with urlString: String, personLabel: String, occupationLabel: String, userCompletionHandler: #escaping (SecondURLData?, Error?) -> Void) {
if let url = URL(string: urlString) {
URLSession.shared.dataTask(with: url, completionHandler: { data, response, error in
if let data = data {
let jsonDecoder = JSONDecoder()
do {
let parsedJSON = try jsonDecoder.decode(SecondURLIncomingData.self, from: data)
print(parsedJSON)
let name = parsedJSON.entities[personLabel]?.labels.en.value
let occupation = parsedJSON.entities[occupationLabel]?.labels.en.value
let finalData = SecondURLData(personName: name!, occupationName: occupation!)
userCompletionHandler(finalData, nil)
} catch {
print(error)
userCompletionHandler(nil,error)
}
}
})
.resume()
}
}
}
//MARK: - incoming data model - first url
struct FirstURLIncomingData: Codable {
let results: Results
}
struct Results: Codable {
let bindings: [Bindings]
}
struct Bindings: Codable {
let dob: DOB
let personLabel: PersonLabel
let occupationLabel: OccupationLabel
}
struct DOB: Codable {
let value: String
}
struct PersonLabel: Codable {
let value: String
}
struct OccupationLabel: Codable {
let value: String
}
//MARK: - incoming data model - second url
struct SecondURLIncomingData: Decodable {
let entities: [String : Locator]
}
struct Locator: Decodable {
let labels: Labels
}
struct Labels: Decodable {
let en: EN
}
struct EN: Decodable {
let value: String
}
//MARK: - model of data for both urls
struct FirstURLData: Decodable {
let dob: String
let personLabel: String
let occupationLabel: String
}
struct SecondURLData {
let personName: String
let occupationName: String
}
let manager = BDayWikiDataManager()
let data = manager.fetchBDayDataFromWikipedia(numMonth: "8", numDay: "13")
print(data) //prints "no data" for everything, which means the values didnt update
Worth noting: when I go to the url's manually, I get json responses in my browser, so I know the url's are correct...

How do I parse this nested JSON using Codable with Swift?

I am trying to parse this JSON using Codable:
{
"users": [
{
"id": 1,
"name": "Allen Carslake",
"userName": "acarslake0",
"profileImage": "https://source.unsplash.com/random/400x400",
"createdDate": "2019-07-08T00:00:00.000+0000"
},
{
"id": 2,
"name": "Revkah Antuk",
"userName": "rantuk1",
"profileImage": "https://source.unsplash.com/random/400x400",
"createdDate": "2019-07-05T00:00:00.000+0000"
},
{
"id": 3,
"name": "Mirna Saffrin",
"userName": "msaffrin2",
"profileImage": "https://source.unsplash.com/random/400x400",
"createdDate": "2019-05-19T00:00:00.000+0000"
},
{
"id": 4,
"name": "Haily Eilers",
"userName": "heilers3",
"profileImage": "https://source.unsplash.com/random/400x400",
"createdDate": "2019-06-28T00:00:00.000+0000"
},
{
"id": 5,
"name": "Oralie Polkinhorn",
"userName": "opolkinhorn4",
"profileImage": "https://source.unsplash.com/random/400x400",
"createdDate": "2019-06-04T00:00:00.000+0000"
}
]
}
I am keeping the URL private on here but it is returning JSON above. So far this is my code:
import UIKit
struct User: Codable {
let id: Int
let name: String
let userName: String
let profileImage: String
let createdDate: String
}
struct Users: Codable {
let users: String
}
let url = URL(string: "")!
URLSession.shared.dataTask(with: url) { data, _, _ in
if let data = data {
let users = try? JSONDecoder().decode([User].self, from: data)
print(users)
}
}.resume()
I need to be able to access the User properties but I think the nesting is making it difficult for me. Any help is awesome!! Thank you!!
First of all: Catch always the DecodingError and print it. It tells you exactly what's wrong.
The error occurs because you are ignoring the root object Users. Your code works if you decode(Users.self.
My suggestions:
Decode createdDate as Date adding a appropriate date decoding strategy.
Decode profileImage as URL (for free).
Handle all errors.
struct Root : Decodable { // `Users` and `User` is too confusing
let users: [User]
}
struct User : Decodable {
let id: Int
let name: String
let userName: String
let profileImage: URL
let createdDate: Date
}
URLSession.shared.dataTask(with: url) { data, _, error in
if let error = error { print(error); return }
do {
let decoder = JSONDecoder()
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
decoder.dateDecodingStrategy = .formatted(dateFormatter)
let result = try decoder.decode(Root.self, from: data!)
for user in result.users {
print(user.userName, user.id, user.createdDate)
}
} catch {
print(error)
}
}.resume()
The root of the json is a dictionary not an array you can write a root class but it will be useless , so you need
URLSession.shared.dataTask(with: url) { data, _, _ in
do {
if let data = data {
let res = try JSONSerialization.jsonObject(with: data) as! [String:Any]
let usersData = try JSONSerialization.data(withJSONObject: res["users"])
let users = try JSONDecoder().decode([User].self, from: usersData)
print(users)
}
}
catch {
print(error)
}
}.resume()
Your Users struct (I renamed it to UsersResponse) should contain a users property of type [User]. Then you can do the following:
struct UsersResponse: Codable {
let users: [User]
}
URLSession.shared.dataTask(with: url) { data, _, _ in
guard let data = data else { return }
if let users = try? JSONDecoder().decode(Users.self, from: data).users {
users.forEach { user in
print("A user called \(user.name) with an id of \(user.id).")
}
}
}.resume()
Please try the below code. This is working for me.
Model Class:
struct UsersResponse: Codable {
let users: [User]
}
struct User: Codable {
let id: Int
let name: String
let userName: String
let profileImage: String?
let createdDate: String
}
Network class:
public enum EndPoints: String {
case prod = "ProdURL"
case test = "testURL"
}
public enum Result<T> {
case success(T)
case failure(Error)
}
final public class Networking: NSObject {
// MARK: - Private functions
private static func getData(url: URL,
completion: #escaping (Data?, URLResponse?, Error?) -> ()) {
URLSession.shared.dataTask(with: url, completionHandler: completion).resume()
}
/// fetchUsersResponse function will fetch the User Response and returns
/// Result<UsersResponse> as completion handler
public static func fetchUsersResponse(shouldFail: Bool = false, completion: #escaping (Result<UsersResponse>) -> Void) {
var urlString: String?
if shouldFail {
urlString = EndPoints.test.rawValue
} else {
urlString = EndPoints.prod.rawValue
}
guard let mainUrlString = urlString, let url = URL(string: mainUrlString) else { return }
Networking.getData(url: url) { (data, response, error) in
if let error = error {
completion(.failure(error))
return
}
guard let data = data, error == nil else { return }
do {
let decoder = JSONDecoder()
//decoder.dateDecodingStrategy = .millisecondsSince1970
decoder.dateDecodingStrategy = .formatted(setDateFormat())
let json = try decoder.decode(UsersResponse.self, from: data)
completion(.success(json))
} catch let error {
completion(.failure(error))
}
}
}
func setDateFormat() -> DateFormatter {
let dateFormat = DateFormatter()
dateFormat.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
return dateFormat
}

Swift 4 adding parameters to URLRequest completion handler

I'm trying to return some data from a URLRequest in Swift 4, and to do so I've added a completion handler to my function signature, just with a Bool for the time being. This is the function:
func getJson(completionHandler: #escaping (Bool) -> ()) {
let jsonUrlString = "https://api.nytimes.com/svc/topstories/v1/business.json?api-key=f4bf2ee721031a344b84b0449cfdb589:1:73741808"
guard let url = URL(string: jsonUrlString) else {return}
URLSession.shared.dataTask(with: url) { (data, response, err) in
guard let data = data, err == nil else {
print(err!)
return
}
do {
let response = try
JSONDecoder().decode(TopStoriesResponse.self, from: data)
print(response.results)
// Pass results into arrays (title, abstract, url, image)
completionHandler(true)
DispatchQueue.main.async {
self.tableView.reloadData()
}
} catch let jsonErr {
print("Error serializing JSON", jsonErr)
}
}.resume()
}
and I call it in viewDidLoad like so:
getJson { (success) in
print("Success")
}
Nothing is printing to the console so I'm wondering if I am using the completion handler correctly? But ultimately I'd like to switch out the Bool and instead pass a few values out of the request, back into arrays that I have in my view controller.
These are the structs I'm using to grab the pieces of JSON that i want:
struct TopStoriesResponse: Decodable {
let status: String
let results: [Story]
}
struct Story: Decodable {
let title: String
let abstract: String
let url: String
}
And I'm ultimately trying to fill these arrays in my view controller with the parsed JSON so I can arrange them in a table view:
var headlines = [String]()
var abstracts = [String]()
var urls = [URL]()
EDIT: Full code in case I'm going wrong somewhere else: https://pastebin.com/r402GKej
try creating the struct TopStoriesResponse and Story seperately from the ViewController and add the Networking struct to load data from the API
struct TopStoriesResponse: Decodable {
let status: String
let copyright: String
let num_results: Int
let results: [Story]
}
struct Story: Decodable {
let title: String
let abstract: String
let url: String
}
struct Networking {
static func getJson(completionHandler: #escaping (Bool) -> ()) {
let jsonUrlString = "https://api.nytimes.com/svc/topstories/v1/business.json?api-key=f4bf2ee721031a344b84b0449cfdb589:1:73741808"
guard let url = URL(string: jsonUrlString) else {
return
}
URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let data = data, error == nil else {
print(error!.localizedDescription)
return
}
do {
let response: TopStoriesResponse = try JSONDecoder().decode(TopStoriesResponse.self, from: data)
print(response.results.count)
completionHandler(true)
} catch {
print(error.localizedDescription)
completionHandler(false)
}
}.resume()
}
}
Now try calling Networking.getJson from the ViewController
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
loadData()
}
func loadData() {
Networking.getJson { (result) in
print(result)
}
}
}

Resources