Bei
Bei

Reputation: 59

SwiftUI Text View: When optional string is nil, expected default value is not working

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://example.com/jsonapi") // EXAMPLE ONLY
        
        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" referenced in above view):

import SwiftUI

struct JSONChallengeRowView: View {

    var challenge: Challenge
    
    var body: some View {

        let thumbnailPrefix = "https://example.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)

        }
    }
}

Upvotes: 0

Views: 2169

Answers (1)

Bei
Bei

Reputation: 59

Nick's point about image_url containing an empty string, not nil, pointed me in the right direction, and with a tip from my Swift learner's forum elsewhere, I used this modification to fix the sections that weren't working:

challenge.imageURL.isEmpty ? "autumn-default" : "\(challenge.imageURL)"

For example, here:

RemoteImageView(url: "\(thumbnailPrefix)" + (challenge.imageURL.isEmpty ? "autumn-default" : "\(challenge.imageURL)") + "\(thumbnailInfix)" + (challenge.imageURL.isEmpty ? "autumn-default" : "\(challenge.imageURL)") + "\(thumbnailSuffix)")

I also applied this syntax to the Link and Text views successfully.

Thanks again, everyone!

Upvotes: 1

Related Questions