Novice SwiftUI developer can't make network call

I'm trying to use URL structure in the foundation framework and it is failing to build, returning a nil value. Could it be trying to evaluate the string I am giving it as a variable for its argument at build time? Is there a test argument I can give URL to see if it can return a non-nil value? (of URL type)?

Answered by DTS Engineer in 857889022

Thank you for the post regarding the issue you are experiencing with the URL structure in the Foundation framework.

Based on your description, it is possible that the string you are using as an argument is evaluated at build time, particularly if it involves compile-time constants or conditions that are not resolved correctly.

Could you please provide the code you are using? Is it something like this and returns nil?

let testURL = URL(string: "https://www.example.com")
print(testURL)

The more information you can provide, the better I can assist you. Please share the code you are using to construct the URL. Thank you.

Albert Pascual
  Worldwide Developer Relations.

Accepted Answer

Thank you for the post regarding the issue you are experiencing with the URL structure in the Foundation framework.

Based on your description, it is possible that the string you are using as an argument is evaluated at build time, particularly if it involves compile-time constants or conditions that are not resolved correctly.

Could you please provide the code you are using? Is it something like this and returns nil?

let testURL = URL(string: "https://www.example.com")
print(testURL)

The more information you can provide, the better I can assist you. Please share the code you are using to construct the URL. Thank you.

Albert Pascual
  Worldwide Developer Relations.

var myString = "https://www.example.com" var banjo = URL(string: myString) let task = URLSession.shared.dataTask(with:banjo ) { myDatastring , response , error in}

I am programming in swiftUI and I think can't do print statements like in your example.

I should also add that I have a free api key for stock info. I have used that URL, which I know works in a browser. If that helps understanding my issue there it is.

Hey Albert did you see my response?

Indeed, I have reviewed your response. Print statements are indeed supported in SwiftUI and are displayed on the Xcode console. However, I am still unclear about your request for a “free API key for stock info.” Could you please provide additional details? Are the sample request I have provided effective for you?

Albert Pascual
  Worldwide Developer Relations.

let myString = "https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=AAPL&apikey= *********" var banjo = URL(string: myString) let task = URLSession.shared.dataTask(with:banjo ) { myDatastring , response , error in} //task.resume()

I have pasted the offending code to this forum.

The error is:Value of optional type 'URL?' must be unwrapped to a value of type 'URL'. It is tied to the line beginning "let task" and to the first mention of "banjo". Does that help?

var banjo = URL(string: myString)

is using this initializer for URL:

init?(string: String)

The ? after init means that it returns an optional URL. If it can't create a URL from your string, it will return nil.

Your next line,

let task = URLSession.shared.dataTask(with:banjo )

is using this function of URLSession:

func dataTask(with url: URL) -> URLSessionDataTask

which takes a URL, not an optional URL. You've got to decide what to do in your code if you get a nil in banjo.

the simplest thing to do is use

if let banjo = URL(string: myString) {
 // do stuff with banjo
} else {
 // whatever you want to do if you've made a
// string that can't be turned into a URL
}

if let binds a non-nil result from the URL initializer to banjo. It is fine to use let here because you're not going to alter banjo after you've created it.

I am not having trouble deciding what to do in my code if I get a non URL value in banjo. I'm using the same URL that I think I will always use, and that won't change. And that I'm checking is valid.

That being the case I've tried pasting the code you gave me into xcode and it still won't build.

Here's what I put in xcode

let myString = "https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=AAPL&apikey= *********" if let banjo = URL(string: myString) { let Lulah = URLSession.shared.dataTask(with:banjo ) { myDatastring , response , error in} Lulah.resume() } else { myDatastring="nil url" }

I'm getting a build error on the line starting "if let banjo". The build error is: "Statements are not allowed at the top level" and is tied to the first word, if.

Thank you for your generous help.

Also if you can point me to documentation that describes what the URL structure does, that might help me too. I was trying to find out why it was returning a nil value. Also what in the shared task was failing. So i was struggling to find documentation on the shared task. Again, thanks for your generous help.

"Statements are not allowed at the top level" occurs because you put the code into a file but didn't wrap it in a func. The line if let banjo = URL(string: ... etc is a statement, not a declaration. Swift wants you to be clear about when that statement should be executed. You can sprinkle declarations around your program more or less wherever you like, because (generally) a declaration just makes a thing exist as a named object in your program, and doesn't have side effects which may differ depending on order of instantiation.

There is built-in documentation in Xcode. Window / Developer Documentation. Type URL into the search field, choose Swift as the language. You can also search on https://developer.apple.com/documentation/ . Click on the magnifying glass icon.

The documentation for URL is surprisingly difficult to find on the web site, but it is here:

https://developer.apple.com/documentation/foundation/url

There is some more comprehensive documentation about using URLSession to download files here: https://developer.apple.com/documentation/foundation/downloading-files-from-websites

To your question about the "shared task" - there isn't a shared task. What is shared is the URLSession. Read the documentation for URLSession.

https://developer.apple.com/documentation/foundation/urlsession/

URLSession.shared returns a URLSession. You're making a request to the URLSession (a class, which is a collection of functions) to get its shared instance, which is a single URLSession object (a class instance, which is a collection of functions and state).

https://developer.apple.com/documentation/foundation/urlsession/shared

"For basic requests, the URLSession class provides a shared singleton session object that gives you a reasonable default behavior for creating tasks. Use the shared session to fetch the contents of a URL to memory with just a few lines of code."

From that single URLSession object you are creating a dataTask with a URL called "banjo".

https://developer.apple.com/documentation/foundation/urlsession/datatask(with:)-10dy7

The dataTask "Creates a task that retrieves the contents of the specified URL."

But that task won't do anything until you tell it to, by calling resume() on it.

Please, when you post code, wrap it in a code block, using the Code Block widget under the Reply box on this forum. Otherwise your code is difficult to read.

You can post up to 7000 characters in a reply - it is easier for us to help you if you post a complete code snippet.

if let banjo = URL(string: myString) {
    let Lulah = URLSession.shared.dataTask(with:banjo ) { myDatastring , response , error in}
            Lulah.resume()
} else {
 myDatastring="nil url"
}

the if let banjo... line was written by you (I think). What function shouuld I enclose it in? Or do I need to make a new function that includes all we have discussed, then execute it after it's written?

I have wrapped the (if let banjo) block in a dummy function and it builds. Only issue is where to run the function. I'd be happy with it running first in the program. As soon as I boot up. I suppose I could put a button in the content view that runs the function, which I assume would make the network call. Is that ok?

Novice SwiftUI developer can't make network call
 
 
Q