UPDATE:
It was pointed out to me that in my example outlined earlier (see below), I’m checking for nil but the JSON value would actually be an empty string. So I realize that I have a new question: Is there a way in Swift to check for an empty string and handle it with a default value within the view itself, as you can with the nil-coalescing operator? I haven’t found anything like that yet.
========================
Hi all,
Having trouble figuring out why code won’t display default value when variable is nil. Here’s the context below. Any pointers would be greatly appreciated.
Thanks!
// EXAMPLE OF DATA FROM JSON API:
// NOTE: image_url is just the base name, not the full path or file extension.
[
{
"id": 1,
"title": "Autumn in New York",
"image_url": ""
}
]
////////////////////////////
// DATA MODEL:
import Foundation
struct Challenge: Codable, Hashable, Identifiable {
let id: Int
let title: String
let imageURL: String?
private enum CodingKeys: String, CodingKey {
case id
case title
case imageURL = "image_url"
}
}
////////////////////////////
// CODE FOR VIEW AND VIEW MODEL:
import SwiftUI
struct JSONChallengeV2: View {
@State private var challenge: [Challenge] = []
var body: some View {
ScrollView {
VStack(alignment: .leading, spacing: 5) {
ScrollView(.horizontal, showsIndicators: true) {
HStack() {
ForEach (challenge) { challenge in
NavigationLink(
destination:
PlayerView(),
label: {
// PROBLEMS OCCUR IN THIS VIEW (see view code below)
JSONChallengeRowView(challenge: challenge)
})
}
}
}
}
.onAppear {
getData()
}
}
}
func getData() {
let url = URL(string: "https://mydomain.com/jsonapi")
URLSession.shared.dataTask(with: url!) { (data, response, error) in
guard error == nil else {
print(error?.localizedDescription ?? "")
return
}
guard data != nil else {
print("No data")
return
}
let decoder = JSONDecoder()
do {
let loaded = try decoder.decode([Challenge].self, from: data!)
challenge = loaded
} catch {
print("Can't decode data")
}
}.resume()
}
}
////////////////////////////
// CODE FOR SUB-VIEW "JSONChallengeRowView"
import SwiftUI
struct JSONChallengeRowView: View {
var challenge: Challenge
var body: some View {
let thumbnailPrefix = "https://mydomain.com/" // EXAMPLE ONLY
let thumbnailSuffix = "-001.jpg"
VStack(alignment: .leading) {
// WORKS: Hardcoding a known image base (i.e., "autumn-default":
RemoteImageView(url: ("\(thumbnailPrefix)\(String(describing: "autumn-default"))\(thumbnailSuffix)"))
.scaledToFit()
.cornerRadius(10)
Link("Go", destination: (URL(string: "\(thumbnailPrefix)\("autumn-default")\(thumbnailSuffix)") ?? URL(string: "https://google.com"))!)
// DOESN'T WORK: build succeeds but no default image appears when no "imageURL" value can be found:
RemoteImageView(url: ("\(thumbnailPrefix)\(String(describing: challenge.imageURL ?? "autumn-default" ))\(thumbnailSuffix)"))
.scaledToFit()
.cornerRadius(10)
Link("Go", destination: URL(string: "\(thumbnailPrefix)\(String(describing: challenge.imageURL ?? "autumn-default"))\(thumbnailSuffix)")!)
// AND WHILE THESE WORK:
Text("\(challenge.title)")
Text(challenge.title)
// THESE SIMILARLY DISPLAY NOTHING (despite values in the "title" variable, used as a default value here for testing only):
Text("\(challenge.imageURL ?? challenge.title)")
Text(challenge.imageURL ?? challenge.title)
}
}
}