Home > Net >  SwiftUI - string constant to URL link in List
SwiftUI - string constant to URL link in List

Time:12-22

I'm trying to create a list with the rows linkable to a YouTube video URL (stored as a string). I'm just learning SwiftUI and Swift language, so even an external link to Safari would suffice.

I've tried both navigation links and navigation views with no luck.

I tried the below version, but it gives an error for the record.videour as an argument. I'm assuming it's because record.videourl is not a "view".

Is there a way to do this without using @state or @observableObjects?

import SwiftUI

struct ContentView: View {
    
    var body: some View {
        List(records, id: \.id) { record in
            NavigationLink(destination: record.videourl){
                VStack {
                    HStack{
                        AsyncImage(url: URL(string: record.imagefile))
                            .cornerRadius(4)
                        Text(record.title)
                            .padding(3)
                            .font(.custom("AmericanTypewriter", fixedSize: 15))
                    }
                }
            }
            .navigationTitle("CradleToGrave R")
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

I know the string is valid when I print the output. For context, here is how it's loaded and the structure.

import Foundation

struct Record: Codable, Identifiable {
    let id = UUID()
    let title: String
    let description: String
    let imagefile: String
    let videourl: String
}

let records = loadCSV(fileName: "Manual_Playlist")

func parseCSV(contents: String) -> [Record] {
    let rows = contents.components(separatedBy: "\n")
    var records: [Record] = []
    for row in rows {
        let columns = row.components(separatedBy: ",")
        if columns.count == 4 {
            let record = Record(title: columns[0],
                                description: columns[1],
                                imagefile: columns[2],
                                videourl: columns[3])
            
            records.append(record)
        }
    }
    return records
}

func loadCSV(fileName: String) -> [Record] {
    if let fileURL = Bundle.main.url(forResource: fileName, withExtension: "csv") {
        do {
            let contents = try String(contentsOf: fileURL)
            return parseCSV(contents: contents)
        } catch {
            print("Error reading file: \(error)")
        }
    }
    return []
}

I've even tried using videourl as a URL object with no luck.

CodePudding user response:

For that, you can use the Link or openURL environment key. NavigationLink is used to push a new view.

Using Link

Link("Visit Google", destination: URL(string: "https://www.google.com")!)
   .font(.title)
   .foregroundColor(.green)

//Or with custom view

Link(destination: URL(string: "https://www.google.com")!) {
    Image(systemName: "link.circle.fill")
       .font(.title)
}

Using openURL

struct ContentView: View {
    @Environment(\.openURL) var openURL

    var body: some View {
        Button("Visit Google") {
            openURL(URL(string: "https://www.google.com")!)
        }
    }
}
  • Related