UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: How to add a URL selection to use with url.lines

Forums > SwiftUI

Paul's recent article on his favorite new Swift API from iOS 15 was about url.lines. In the first portion, where he lists quotes from a hard-coded URL (URL(string: "https://hws.dev/quotes.txt")!. If, instead of a hard-coded URL, the user had a choice, eg. from a local or iCloud file, what would be the best way to make such a choice. I've been trying with .fileImporter, but getting confused...

3      

My question was likely too vague to get a response. Here is the code I've been trying. if I uncomment the portion that Paul uses in his example, it works as expected. However, if I comment that out and use my line: let url = URL(string: String(describing: settings.fileURL))! then it does not list the contents of the file. Any suggestions?

Here is the full code for ContentView:

//  ContentView.swift
//  URLlines
//
// Based on Paul Hudson code:
// https://www.hackingwithswift.com/articles/241/how-to-fetch-remote-data-the-easy-way-with-url-lines
// trying to import the URL for use with url.lines

import SwiftUI

class Settings: ObservableObject {
    @Published var fileURL: URL?
}

struct ContentView: View {

    @State var imported = false
    @ObservedObject var settings = Settings()
    @State private var contents = [String]()

    var body: some View {
        VStack (spacing: 30) {
            Button(action: {imported.toggle()}, label: {
                Text("Push to browse to the location of the data input file")
                    .padding(/*@START_MENU_TOKEN@*/.all/*@END_MENU_TOKEN@*/)
                    .background(Color(red: 0, green: 0.5, blue: 0.0))
                    .foregroundColor(.white)
                    .clipShape(Capsule())
            })

            if imported {

                List(contents, id: \.self, rowContent: Text.init)

                    .task {
                        do {
//                       let url = URL(string: "https://hws.dev/quotes.txt")!   //This works, from HWS
                     let url = URL(string: String(describing: settings.fileURL))! //This is what I'm trying, and doesn't work
                            imported = true
                            for try await line in url.lines {
                                contents.append(line)
                            }
                        } catch {
                            // Stop adding content when an error is thrown
                        }
                    }
            }
        }

        .fileImporter(
            isPresented: $imported,
            allowedContentTypes: [.plainText]) { res in
            do {
                settings.fileURL = try res.get()
                print("---> fileURL: \(String(describing: settings.fileURL))")
            } catch {
                print ("error reading: \(error.localizedDescription)")
            }
        }
    }
}

3      

let url = URL(string: String(describing: settings.fileURL))!

Why are you doing this? fileURL is already a URL? so all you need to do is unwrap it and use it rather than go through this complicated dance of turning URL? into a String and then into a URL.

Something like what Paul is doing is what you need to do. So force unwrap settings.fileURL or safely unwrap it with an if let or use nil coalescing.

At any rate, you are running into problems because String(describing: settings.fileURL) returns something like Optional(...) with whatever the URL path is and that can't be converted into a URL.

3      

Thank you, roosterboy! I've used your suggestion to get this past the url hurdle. (I'm currently in an absurd situation where I click on the button to go to the file, choose the file, but then am presented with the button again, choose it, and then finally the List of contents shows up, but with the menu to choose a file still there. I've been staring at this to long...)

Anyway, for those interested here's the code that sort of works, except for the absurdity...

//  ContentView.swift
//  URLlines
//
// Based on Paul Hudson code:
// https://www.hackingwithswift.com/articles/241/how-to-fetch-remote-data-the-easy-way-with-url-lines
// trying to import the URL for use with url.lines

import SwiftUI

class Settings: ObservableObject {
    @Published var fileURL: URL?
}

struct ContentView: View {

    @State var imported = false
    @ObservedObject var settings = Settings()
    @State private var contents = [String]()

    var body: some View {
        VStack (spacing: 30) {

            if !imported {
                Button(action: {imported.toggle()}, label: {
                    Text("Push to browse to the location of the data input file")
                        .padding(/*@START_MENU_TOKEN@*/.all/*@END_MENU_TOKEN@*/)
                        .background(Color(red: 0, green: 0.5, blue: 0.0))
                        .foregroundColor(.white)
                        .clipShape(Capsule())
                })

            } else {

                Text("Count: \(contents.count)")
                List(contents, id: \.self, rowContent: Text.init)

                    .task {
                        do {
                            if let url = settings.fileURL {
                                for try await line in url.lines {
                                    contents.append(line)
                                }
                            }
                            imported = true
                        } catch {
                            // Stop adding content when an error is thrown
                        }
                    }
            }
        }

        .fileImporter(
            isPresented: $imported,
            allowedContentTypes: [.plainText]) { res in
                do {
                    settings.fileURL = try res.get()
                    print("---> fileURL: \(String(describing: settings.fileURL))")
                } catch {
                    print ("error reading: \(error.localizedDescription)")
                }
            }
    }
}

3      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.