Swift Convert Any To Data - swift

I'm using facebook sdk to log users in ,
every ting is going well except that after user is logged in i make a request to graph api so it returns user's data .
when i try to parse user data to codable using JSONEncoder() an error occurred !
the error is
Cannot convert value of type 'Any?' to expected argument type 'Data'
Full code :
import SwiftUI
import FBSDKLoginKit
struct AccountView: View {
#ObservedObject var loginManager = UserLoginManager()
var body: some View {
if(!loginManager.logged)
{
Button(action: {
self.loginManager.facebookLogin()
}) {
Text("Continue with Facebook")
}
}
else{
Text((loginManager.userData as AnyObject).email!)
}
}
}
struct AccountView_Previews: PreviewProvider {
static var previews: some View {
AccountView()
}
}
class UserLoginManager: ObservableObject {
#Published var logged:Bool = false
#Published var userData:Any = []
let loginManager = LoginManager()
func facebookLogin() {
// loginManager.set
loginManager.logIn(permissions: [.publicProfile, .email], viewController: nil) { loginResult in
switch loginResult {
case .failed(let error):
print(error)
case .cancelled:
print("User cancelled login.")
case .success(let grantedPermissions, let declinedPermissions, let accessToken):
print("Logged in! \(grantedPermissions) \(declinedPermissions) \(String(describing: accessToken))")
GraphRequest(graphPath: "me", parameters: ["fields": "name,picture,email"]).start(completionHandler: { (connection, result, error) -> Void in
if (error == nil){
let facebookResponse = try? newJSONDecoder().decode(FacebookResponse.self, from: result)
self.userData = facebookResponse!
self.logged = true
}
else{
print("\\\\\\\\")
print(error as Any)
}
})
}
}
}
}
// MARK: - FacebookResponse
struct FacebookResponse: Codable {
let email: String?
let id: Int?
let name: String?
let picture: Picture?
}
// MARK: - Picture
struct Picture: Codable {
let data: DataClass?
}
// MARK: - DataClass
struct DataClass: Codable {
let height, isSilhouette: Int?
let url: String?
let width: Int?
enum CodingKeys: String, CodingKey {
case height
case isSilhouette = "is_silhouette"
case url, width
}
}
and the newJSONDecoder():
func newJSONDecoder() -> JSONDecoder {
let decoder = JSONDecoder()
if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) {
decoder.dateDecodingStrategy = .iso8601
}
return decoder
}
Hint :
let facebookResponse = try? newJSONDecoder().decode(FacebookResponse.self, from: result as! Data)
Doesn’t worked

Use JSONSerialization.data( to convert Any to Data
do {
let data = try JSONSerialization.data(withJSONObject: result, options: [])
self.userData = try newJSONDecoder().decode(FacebookResponse.self, from: data)
self.logged = true
}
catch {
print(error)
}

Related

How to bind data to ViewModel for showing it on UI in MVVM?

In my app I am using MVVM pattern.
Below is my Model.
struct NewsModel: Codable {
let status: String
let totalResults: Int
let articles: [Article]
}
struct Article: Codable {
let source: Source
let author: String?
let title: String
let articleDescription: String?
let url: String
let urlToImage: String?
let publishedAt: Date
let content: String?
enum CodingKeys: String, CodingKey {
case source, author, title
case articleDescription = "description"
case url, urlToImage, publishedAt, content
}
}
struct Source: Codable {
let id: String?
let name: String
}
Below is my ViewModel. Which is used for show the data from API.
struct NewsArticleViewModel {
let article: Article
var title:String {
return self.article.title
}
var publication:String {
return self.article.articleDescription!
}
var imageURL:String {
return self.article.urlToImage!
}
}
Below is my API request class.
class Webservice {
func getTopNews(completion: #escaping (([NewsModel]?) -> Void)) {
guard let url = URL(string: "https://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=2bfee85c94e04fc998f65db51ec540bb") else {
fatalError("URL is not correct!!!")
}
URLSession.shared.dataTask(with: url) {
data, response, error in
guard let data = data, error == nil else {
DispatchQueue.main.async {
completion(nil)
}
return
}
let news = try? JSONDecoder().decode([NewsModel].self, from: data)
DispatchQueue.main.async {
completion(news)
}
}.resume()
}
}
After receiving response from my API I want to show it on screen. For this I added below ViewModel.
class NewsListViewModel: ObservableObject {
#Published var news: [NewsArticleViewModel] = [NewsArticleViewModel]()
func load() {
fetchNews()
}
private func fetchNews() {
Webservice().getTopNews {
news in
if let news = news {
//How to bind this data to NewsArticleViewModel and show it on UI?
}
}
}
}
Please let me know. What I have to write there for showing it on UI.
According to the documentation of newsapi.org your request will return one NewsModel object not an array. So change your Webservice class to:
class Webservice {
//Change the completion handler to return an array of Article
func getTopNews(completion: #escaping (([Article]?) -> Void)) {
guard let url = URL(string: "https://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=2bfee85c94e04fc998f65db51ec540bb") else {
fatalError("URL is not correct!!!")
}
URLSession.shared.dataTask(with: url) {
data, response, error in
guard let data = data, error == nil else {
DispatchQueue.main.async {
completion(nil)
}
return
}
// decode to a single NewsModel object instead of an array
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let news = try? decoder.decode(NewsModel.self, from: data)
DispatchQueue.main.async {
// completion with an optional array of Article
completion(news?.articles)
}
}.resume()
}
}
You would need to map those received values to NewsArticleViewModel types. For example:
Webservice().getTopNews { articles in
if let articles = articles {
self.news = articles.map{NewsArticleViewModel(article: $0)}
}
}
And remove let news: NewsModel from the NewsArticleViewModel struct as it is not needed.
Edit:
It seems:
let publishedAt: Date
is throwing an error. Jsondecoder fails to interpret the string to a date. Change your Webservice. I´ve updated it in my answer.
You could remove the legacy MVVM pattern and do it in proper SwiftUI like this:
struct ContentView: View {
#State private var articles = [Article]()
var body: some View {
NavigationView {
List(articles) { article in
Text(article.title)
}
.navigationTitle("Articles")
}
.task {
do {
let url = URL(string: "https://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=2bfee85c94e04fc998f65db51ec540bb")!
let (data, _) = try await URLSession.shared.data(from: url)
articles = try JSONDecoder().decode([Article].self, from: data)
} catch {
articles = []
}
}
}
}

Can't call the struct in the view

I have a code, that should match 2 JSON files and connect all data in one struct. I'm pretty sure that It works just fine, but I have faced very strange problem. I want to make a picker:
import SwiftUI
struct CurrencyView: View {
#ObservedObject var api = CurrencyViewModel()
#State private var pickerSelection1 = 1
var body: some View {
Text("f")
Picker("", selection: $pickerSelection1) {
ForEach(0..<self.api.currencies.fullName.count) { // Error here
let currency = api.currencies.fullName[$0] // and here
Text(currency)
}
}
.id(UUID())
.labelsHidden()
.padding(.leading)
}
}
struct CurrencyView_Previews: PreviewProvider {
static var previews: some View {
CurrencyView()
}
}
It shows this error:
Value of type '[Currency]' has no member 'fullName'
I know I'm missing smth and feel stupid, because I can't understand why. Thanks for the reply!)
Adding the rest of the code:
// Model
import Foundation
struct CurrencyModel: Codable {
var results: [String:Double]
}
struct CurrencyNewModel: Codable {
var currencies: [String:String]
}
struct Currency: Decodable {
let currencyCode: String
let fullName: String
var price: Double
}
// View Model
import SwiftUI
class CurrencyViewModel: ObservableObject {
#Published var currencies: [Currency] = []
init() {
fetchNewData { [self] (currency) in
switch currency {
case .success(let names):
print("Success")
DispatchQueue.main.async {
self.currencies = names.currencies.map {
Currency(currencyCode: $0.key, fullName: $0.value, price: 0)
}
}
fetchData { result in
switch result {
case .success(let prices):
print("Success")
for (index, value) in currencies.enumerated() {
if let price = prices.results.first(where: { $0.key == value.currencyCode }) {
DispatchQueue.main.async {
currencies[index].price = price.value
}
}
}
case .failure(let error):
print(error)
}
}
case .failure(let error):
print("Error", error)
}
}
}
func fetchData(completion: #escaping (Result<CurrencyModel,Error>) -> ()) {
guard let url = URL(string: "https://api.fastforex.io/fetch-all?from=USD&api_key=7ffe65c2ef-926f01d9e8-r7eql2") else { return }
URLSession.shared.dataTask(with: url) { data, responce, error in
if let error = error {
completion(.failure(error))
return
}
guard let safeData = data else { return }
do {
let currency = try JSONDecoder().decode(CurrencyModel.self, from: safeData)
completion(.success(currency))
}
catch {
completion(.failure(error))
}
}
.resume()
}
func fetchNewData(completion: #escaping (Result<CurrencyNewModel,Error>) -> ()) {
guard let url = URL(string: "https://api.fastforex.io/currencies?api_key=7ffe65c2ef-926f01d9e8-r7eql2") else { return }
URLSession.shared.dataTask(with: url) { data, responce, error in
if let error = error {
completion(.failure(error))
return
}
guard let safeData = data else { return }
do {
let currency = try JSONDecoder().decode(CurrencyNewModel.self, from: safeData)
completion(.success(currency))
}
catch {
completion(.failure(error))
}
}
.resume()
}
}
P.S. If you want to see the API, check the links in fetchData and fetchNewData, It's a free trial, so doesn't matter
Your error says:
Value of type '[Currency]' has no member 'fullName'
So it seems that api.currencies is an array – the array itself has no member fullName, only one single element of it has.
try this:
ForEach(api.currencies, id:\.currencyCode) { currency in
Text(currency.fullName)
}

Why am I not able to recieve any data from the open weather api?

I am using swift and I want to receive data of the temp and humidity but all I am receiving is nil. I have two objects temp and humdity in another swift file. What am I doing wrong in my code? Not sure what I am missing.
struct Weather: Codable {
var temp: Double?
var humidity: Int?
var name : String?
}
struct WeatherMain: Codable {
let main: Weather
}
ViewController
class ViewController: UIViewController, CLLocationManagerDelegate {
let locationManager = CLLocationManager()
var latitudeValue = Double()
var longitudeValue = Double()
#IBOutlet weak var humidityLabel: UILabel!
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let locValue: CLLocationCoordinate2D = manager.location?.coordinate else { return }
print("locations = \(locValue.latitude) \(locValue.longitude)")
latitudeValue = locValue.latitude
longitudeValue = locValue.longitude
}
func retrieve() {
fetchWeather(lat: latitudeValue, lon: longitudeValue)
{ (response , error ) in
for res in response! {
print("Humid value is \(res.humidity ?? 0)")
}
}
}
#IBAction func showData(_ sender: Any) {
retrieve()
}
}
extension ViewController {
func fetchWeather(lat: Double, //Required
lon: Double,
completionHandler: #escaping ([Weather]?, Error?) -> Void) {
// MARK: Retrieve
let apikey = "45345345345343454Fake API"
/// create URL
let baseURL = "https://api.openweathermap.org/data/2.5/weather?lat=\(lat)&lon=\(lon)&appid=\(apikey)"
let url = URL(string: baseURL)
print("this is the url for weather : \(url!)")
/// Creating request
var request = URLRequest(url: url!)
request.setValue("Bearer \(apikey)", forHTTPHeaderField: "Authorization")
request.httpMethod = "GET"
URLSession.shared.dataTask(with: request) { (data, response, error) in
if let err = error {
print(err.localizedDescription)
}
do {
/// Read data as JSON
let json = try JSONSerialization.jsonObject(with: data!, options: [])
/// Main dictionary
guard let resp = json as? NSDictionary else { return }
/// weather
guard let weatherDic = resp.value(forKey: "weather") as? [NSDictionary] else { return }
let weatherData = try? JSONDecoder().decode(WeatherMain.self, from: data!)
var weatherList: [Weather] = []
/// Accessing each weather
for weatherObject in weatherDic {
if let weatherData = weatherData {
var weather = weatherData.main
//print("This is the temp \(weather.temp!)")
//print("This is the humidity \(weather.humidity!)")
weather.temp = weatherObject.value(forKey: "temp") as? Double
weather.humidity = weatherObject.value(forKey: "humidity") as? Int
weather.name = weatherObject.value(forKey: "name") as? String
weatherList.append(weather)
}
}
completionHandler(weatherList, nil)
} catch {
print("Caught error")
completionHandler(nil, error)
}
}.resume()
}
}
Well, as I see there are few mistakes in your code.
You will never receive location updates due to that you haven't set CLLocationManagerDelegate, you haven't requested authorization to use location, you haven't asked location manager to start updating locations.
Your response parsing code doesn't seems to be correct. You need to learn how to use Codable to parse JSON responses.
I've modified a bit your code, so that it works. But prior copy-pasting please open your Info.plist and add the following keys and values for the keys. This is important step.
Privacy - Location Usage Description
Privacy - Location When In Use Usage Description
The next step is to create correct Response model. To simplify the process of creating Response models you can use a website https://quicktype.io
Here is what the website generated for that api response:
// This file was generated from JSON Schema using quicktype, do not modify it directly.
// To parse the JSON, add this file to your project and do:
//
// let weatherResponse = try? newJSONDecoder().decode(WeatherResponse.self, from: jsonData)
import Foundation
// MARK: - WeatherResponse
struct WeatherResponse: Codable {
let coord: Coord?
let weather: [Weather]?
let base: String?
let main: Main?
let visibility: Int?
let wind: Wind?
let clouds: Clouds?
let dt: Int?
let sys: Sys?
let timezone, id: Int?
let name: String?
let cod: Int?
}
// MARK: - Clouds
struct Clouds: Codable {
let all: Int?
}
// MARK: - Coord
struct Coord: Codable {
let lon, lat: Double?
}
// MARK: - Main
struct Main: Codable {
let temp, feelsLike, tempMin, tempMax: Double?
let pressure, humidity: Int?
enum CodingKeys: String, CodingKey {
case temp
case feelsLike = "feels_like"
case tempMin = "temp_min"
case tempMax = "temp_max"
case pressure, humidity
}
}
// MARK: - Sys
struct Sys: Codable {
let type, id: Int?
let country: String?
let sunrise, sunset: Int?
}
// MARK: - Weather
struct Weather: Codable {
let id: Int?
let main, weatherDescription, icon: String?
enum CodingKeys: String, CodingKey {
case id, main
case weatherDescription = "description"
case icon
}
}
// MARK: - Wind
struct Wind: Codable {
let speed, deg: Int?
}
And finally your updated ViewController
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var humidityLabel: UILabel!
let locationManager = CLLocationManager()
var location: CLLocation?
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self // set your CLLocationManagerDelegate to your ViewController instance
checkAuthorizationStatus() // Check current authorization status
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
location = locations.first
}
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
checkAuthorizationStatus()
}
private func checkAuthorizationStatus() {
var authorizationStatus: CLAuthorizationStatus!
if #available(iOS 14.0, *) {
authorizationStatus = locationManager.authorizationStatus
} else {
authorizationStatus = CLLocationManager.authorizationStatus()
}
switch authorizationStatus ?? .notDetermined {
case .authorizedAlways, .authorizedWhenInUse: // If authorized
locationManager.startUpdatingLocation() // request updating location
case CLAuthorizationStatus.denied, CLAuthorizationStatus.restricted: // if denied we are not able to receive location updates
print("Application doesn't have access to location.")
case CLAuthorizationStatus.notDetermined: // if not determined we can request authorization
locationManager.requestWhenInUseAuthorization() // request authorization
#unknown default:
print("Unknown authorization status")
}
}
func retrieve() {
guard let location = location else {
print("Location is nil.")
return
}
fetchWeather(forLocation: location) { [weak self] (result) in
switch result {
case .success(let weatherResponse):
print("WeatherResponse: \(weatherResponse)")
if let humidity = weatherResponse?.main?.humidity {
self?.humidityLabel.text = String(humidity)
}
case .failure(let error):
print("Error: \(error.localizedDescription)")
}
}
}
#IBAction func showData(_ sender: Any) {
retrieve()
}
}
extension ViewController {
func fetchWeather(forLocation location: CLLocation, completion: #escaping (Result<WeatherResponse?, Error>) -> Void) {
let apikey = "YOUR_API_KEY_HERE"
let url = URL(string: "https://api.openweathermap.org/data/2.5/weather?lat=\(location.coordinate.latitude)&lon=\(location.coordinate.longitude)&appid=\(apikey)")!
var request = URLRequest(url: url)
request.httpMethod = "GET"
print("Request: \(url.absoluteString)")
URLSession.shared.dataTask(with: request) { (data, response, error) in
if let error = error {
DispatchQueue.main.async { // Move completion to the main queue, so that you can work with UI stuff
completion(.failure(error))
}
}
guard let data = data else {
print("No response data.")
DispatchQueue.main.async { // Move completion to the main queue, so that you can work with UI stuff
completion(.success(nil))
}
return
}
if let responseString = String(data: data, encoding: .utf8) { // Move completion to the main queue, so that you can work with UI stuff
print("Response: \(responseString)")
}
do {
let response = try JSONDecoder().decode(WeatherResponse.self, from: data) // Here is the magic of Codable, Just simply set expected Codable type
DispatchQueue.main.async { // Move completion to the main queue, so that you can work with UI stuff
completion(.success(response))
}
} catch {
DispatchQueue.main.async { // Move completion to the main queue, so that you can work with UI stuff
completion(.failure(error))
}
}
}.resume()
}
}
Happy coding, don't give up)

SwiftUI and Combine not working smoothly when downloading image asynchrously

When I tried to use SwiftUI & Combine to download image asynchrously, it works fine. Then, I try to implement this into a dynamic list, and I found out there is only one row(the last row) will be show correctly, images in other cells are missing. I have trace the code with breakpoints and I'm sure the image download process is success in others, but only the last row will trigger the #ObjectBinding to update image. Please check my sample code and let me know if there's any wrong. Thanks!
struct UserView: View {
var name: String
#ObjectBinding var loader: ImageLoader
init(name: String, loader: ImageLoader) {
self.name = name
self.loader = loader
}
var body: some View {
HStack {
Image(uiImage: loader.image ?? UIImage())
.onAppear {
self.loader.load()
}
Text("\(name)")
}
}
}
struct User {
let name: String
let imageUrl: String
}
struct ContentView : View {
#State var users: [User] = []
var body: some View {
NavigationView {
List(users.identified(by: \.name)) { user in
UserView(name: user.name, loader: ImageLoader(with: user.imageUrl))
}
.navigationBarTitle(Text("Users"))
.navigationBarItems(trailing:
Button(action: {
self.didTapAddButton()
}, label: {
Text("+").font(.system(size: 36.0))
}))
}
}
func didTapAddButton() {
fetchUser()
}
func fetchUser() {
API.fetchData { (user) in
self.users.append(user)
}
}
}
class ImageLoader: BindableObject {
let didChange = PassthroughSubject<UIImage?, Never>()
var urlString: String
var task: URLSessionDataTask?
var image: UIImage? = UIImage(named: "user") {
didSet {
didChange.send(image)
}
}
init(with urlString: String) {
print("init a new loader")
self.urlString = urlString
}
func load() {
let url = URL(string: urlString)!
let task = URLSession.shared.dataTask(with: url) { (data, _, error) in
if error == nil {
DispatchQueue.main.async {
self.image = UIImage(data: data!)
}
}
}
task.resume()
self.task = task
}
func cancel() {
if let task = task {
task.cancel()
}
}
}
class API {
static func fetchData(completion: #escaping (User) -> Void) {
let request = URLRequest(url: URL(string: "https://randomuser.me/api/")!)
let task = URLSession.shared.dataTask(with: request) { (data, _, error) in
guard error == nil else { return }
do {
let json = try JSONSerialization.jsonObject(with: data!, options: []) as? [String: Any]
guard
let results = json!["results"] as? [[String: Any]],
let nameDict = results.first!["name"] as? [String: String],
let pictureDict = results.first!["picture"] as? [String: String]
else { return }
let name = "\(nameDict["last"]!) \(nameDict["first"]!)"
let imageUrl = pictureDict["thumbnail"]
let user = User(name: name, imageUrl: imageUrl!)
DispatchQueue.main.async {
completion(user)
}
} catch let error {
print(error.localizedDescription)
}
}
task.resume()
}
}
every images should be downloaded successfully no matter how many items in the list.
There seems to be a bug in #ObjectBinding. I am not sure and I cannot confirm yet. I want to create a minimal example code to be sure, and if so, report a bug to Apple. It seems that sometimes SwiftUI does not invalidate a view, even if the #ObjectBinding it is based upon has its didChange.send() called. I posted my own question (#BindableObject async call to didChange.send() does not invalidate its view (and never updates))
In the meantime, I try to use EnvironmentObject whenever I can, as the bug doesn't seem to be there.
Your code then works with very few changes. Instead of using ObjectBinding, use EnvironmentObject:
Code Replacing #ObjectBinding with #EnvironmentObject:
import SwiftUI
import Combine
struct UserView: View {
var name: String
#EnvironmentObject var loader: ImageLoader
init(name: String) {
self.name = name
}
var body: some View {
HStack {
Image(uiImage: loader.image ?? UIImage())
.onAppear {
self.loader.load()
}
Text("\(name)")
}
}
}
struct User {
let name: String
let imageUrl: String
}
struct ContentView : View {
#State var users: [User] = []
var body: some View {
NavigationView {
List(users.identified(by: \.name)) { user in
UserView(name: user.name).environmentObject(ImageLoader(with: user.imageUrl))
}
.navigationBarTitle(Text("Users"))
.navigationBarItems(trailing:
Button(action: {
self.didTapAddButton()
}, label: {
Text("+").font(.system(size: 36.0))
}))
}
}
func didTapAddButton() {
fetchUser()
}
func fetchUser() {
API.fetchData { (user) in
self.users.append(user)
}
}
}
class ImageLoader: BindableObject {
let didChange = PassthroughSubject<UIImage?, Never>()
var urlString: String
var task: URLSessionDataTask?
var image: UIImage? = UIImage(named: "user") {
didSet {
didChange.send(image)
}
}
init(with urlString: String) {
print("init a new loader")
self.urlString = urlString
}
func load() {
let url = URL(string: urlString)!
let task = URLSession.shared.dataTask(with: url) { (data, _, error) in
if error == nil {
DispatchQueue.main.async {
self.image = UIImage(data: data!)
}
}
}
task.resume()
self.task = task
}
func cancel() {
if let task = task {
task.cancel()
}
}
}
class API {
static func fetchData(completion: #escaping (User) -> Void) {
let request = URLRequest(url: URL(string: "https://randomuser.me/api/")!)
let task = URLSession.shared.dataTask(with: request) { (data, _, error) in
guard error == nil else { return }
do {
let json = try JSONSerialization.jsonObject(with: data!, options: []) as? [String: Any]
guard
let results = json!["results"] as? [[String: Any]],
let nameDict = results.first!["name"] as? [String: String],
let pictureDict = results.first!["picture"] as? [String: String]
else { return }
let name = "\(nameDict["last"]!) \(nameDict["first"]!)"
let imageUrl = pictureDict["thumbnail"]
let user = User(name: name, imageUrl: imageUrl!)
DispatchQueue.main.async {
completion(user)
}
} catch let error {
print(error.localizedDescription)
}
}
task.resume()
}
}

How do I put a picture from a JSON URL in the background of a UIViewController?

I have a ViewController and in these I would like to set an image as a background image via JSON URL.
I also wanted to present a picture of this JSON request with my JSON request which I already used for my News UITableViewController, but that did not work
Here is my code:
var courses = [Course]()
var activityIndicatorView: UIActivityIndicatorView!
var rows: [String]?
let dispatchQueue = DispatchQueue(label: "Example Queue")
let borderwidth = 10
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.hidesBackButton = true
fetchJSON()
}
// MARK: - Courses
struct Course: Codable {
let guid: GUID
let links: Links
enum CodingKeys: String, CodingKey {
case guid
case links = "_links"
}
}
// MARK: - GUID
struct GUID: Codable {
let rendered: String
}
// MARK: - Links
struct Links: Codable {
}
fileprivate func fetchJSON() {
let urlString = "EXAMPLE_URL"
guard let url = URL(string: urlString) else { return }
URLSession.shared.dataTask(with: url) { (data, _, err) in
DispatchQueue.main.async {
if let err = err {
print("Failed to get data from url:", err)
return
}
guard let data = data else { return }
do {
self.courses = try JSONDecoder().decode([Course].self, from: data)
self.tableView.reloadData()
} catch let jsonErr {
print("Failed to decode:", jsonErr)
}
}
}.resume()
}
I would like that the image occupies the entire ViewController and in the middle of a transparent box with welcome text
However, I do not know how to load a picture from a post.