Hello @Audrey, @kentoh, can you explain the use of [weak var] in the code snippet below? Why is weak self needed at all? If it is definitely needed to not get into a strong reference cycle, would unowned not be better?
Thanks in advance!
Chris
// 4
if let index = download?.track.index {
DispatchQueue.main.async { [weak self] in
self?.tableView.reloadRows(at: [IndexPath(row: index, section: 0)],
with: .none)
}
}
Hi @audrey, thanks for the quick reply and link. I still don’t understand where the need of [weak self] arises as I cannot see where the strong reference in this closure is located. The closure itself is not referenced as a property of the class itself, which I understood from Apple’s Swift programming guide to be the reason for strong references in closures.
I believe @Audrey is correct. If we have already release this controller then we don’t do anything due to the optional chaining. To do things without the optional we’d do he if-let unwrap as mentioned before.
While I see why some people prefer unowned as it removes optionality, I always go for weak because there is always a chance that self has been released by the time you get to your closure. If that’s the case, unowned will cause a crasher as it’s not optional, where as with weak you may simply not get past the guard statement or the optional chaining.
You’re certainly free to use unowned if you are fully aware and comfortable with your object’s lifecycles
Is there no smarter way than dynamically allocating a custom URLSession in the ViewController if I need a delegate? Isn’t there a memory leak in this case because neither invalidateAndCancel() nor finishTasksAndInvalidate() is called on the dynamically created URLSession in the SearchViewController.
If I have multiple ViewControllers which all need the same URLSession configuration but each of them has to be the respective delegate, is there a way to define a “global URLSession” that automatically adapts the delegate to the ViewController that is currently creating a DataTask? Being able to store this type of URLSession as a static shared property of the URLSession class would be even better…
The URLSession is not dynamically created every time we use it, it’s created once, when needed, and then we reuse the same session unless a new instance of this controller gets created.
Since that means we’re not losing the variable or reference to this session, then canceling or doing other operations on the session won’t result in leaks.
As for having different delegates. A single session can only have one delegate, so if you are looking at using URLSession with delegation and not completion-based calls, then only one object can be its delegate. You could create a global configuration and reuse it in different controllers that have their own URLSession, alternatively you could also create a manager or helper class that has a URLSession, a delegate (unless using completion-based data tasks), and then just performing new data tasks or network requests with it.
In my experience, completion-based calls are better than delegates for this last example. You can use your networking layer and simply handle things in your completion handlers wherever you make use of a network call.
Hi, the following query urlComponents.query = "media=music&entity=songs&term=\(searchTerm)"
returns response with status 400 with following body:
{
“errorMessage”: “Invalid value(s) for key(s): [resultEntity]”,
“queryParameters”: {
“output”: “json”,
“callback”: “A javascript function to handle your search results”,
“country”: “ISO-2A country code”,
“limit”: “The number of search results to return”,
“term”: “A search string”,
“lang”: “ISO-2A language code”
}
}
I changed the query to urlComponents.query = "term=\(searchTerm)"
and I got the response status 200 with app showing the results. Please update for posterity. Thanks. Very useful tutorial though.
I’m located in Pakistan. Well I opened the url you mentioned in my browser and it downloaded the .txt file with valid results. But it didn’t work in the app with this query. Strange. May be we should keep the query as it is but add some note that for some regions try alternate api query. I thought other people might also be facing this issue. Thats why I posted it on the forum.
thanks Hasaan! the error message you got indicates something different about how the API works for your location or internet provider. I’ll add a note.