When trying to create my own session object NSURLSession() and request an url I get an unrecognized selector exception but when I use the shared session NSURLSession.sharedSession() everything works fine. How come?
var url = NSURL(string: "http:/www.google.com")
if url != nil {
//throws unrecognized selector when dataTaskWithURL is called
let session=NSURLSession()
session.dataTaskWithURL(url!)
//works
let sharedSession=NSURLSession.sharedSession()
sharedSession.dataTaskWithURL(url!)
}
You have to init URLSession with a configuration:
URLSession(configuration: .default)
or use shared session
URLSession.shared
In SWIFT 3.0 and up:
URLSession.shared.dataTask(with: url, completionHandler:
{
(data, response, error) in
//Your code
}).resume()
Aside from the shared session NSURLSession must be initialized with one of these two methods
init(configuration configuration: NSURLSessionConfiguration)
init(configuration configuration: NSURLSessionConfiguration,
delegate delegate: NSURLSessionDelegate?,
delegateQueue queue: NSOperationQueue?)
Do the initialization while declaration :-
var session = URLSession(configuration: .default)
Related
For client certificate authentication I've to use URLSessionDelegate in the custom class for handling all requests. The problem is the class is not deinitialize after a request made.
Code:
class Request: NSObject, URLSessionDelegate, URLSessionTaskDelegate{
func request(){
let url:URL = URL(string: "https://stackoverflow.com")!
let config = URLSessionConfiguration.default
URLSession(configuration: config, delegate: self, delegateQueue: .main).dataTask(with: url) { (data, response, error) in
print("Received")
}.resume()
}
func request2(){
let url:URL = URL(string: "https://stackoverflow.com")!
let config = URLSessionConfiguration.default
URLSession(configuration: config).dataTask(with: url) { (data, response, error) in
print("Received")
}.resume()
}
deinit {
print("Class deinit...")
}
}
When calling Request().request() then deinit is not called. Calling Request().request2() then deinit is called.
I am not sure how to resolve this problem. Please help me to find out the solution. Thank you...
URLSession keeps a strong reference to its delegate (self in your case). Check the official documentation:
The session object keeps a strong reference to the delegate until your app exits or explicitly invalidates the session. If you don’t invalidate the session, your app leaks memory until the app terminates.
You can invalidate the session using its methods finishTasksAndInvalidate() or invalidateAndCancel(). After that URLSession will release the strong reference to its delegate.
I guess you code example is just to demonstrate the behavior, but anyway I have to mention it's not a good practice to create a new URLSession for every single URLRequest.
In request() when assigning self to the delegate you are creating a strong reference to the instance of the class. This causes a retention cycle and stops the instance being deinitialised. The answer is to weekly capture the delegate:
URLSession(configuration: config, delegate: self, delegateQueue: .main).dataTask(with: url) { [weak self] (data, response, error) in
print("Received")
}.resume()
In request2() without a delegate this obviously isn't happening.
There are numerous blogs and tutorials about this, so rather than repeating them all I'll let you google for the detail about capture list and strong and weak references :-)
This question already has answers here:
How to download file in swift?
(16 answers)
Closed 6 years ago.
I'm trying to download a file using Swift. This is the downloader class in my code:
class Downloader {
class func load(URL: URL) {
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil)
let request = NSMutableURLRequest(url: URL)
request.httpMethod = "GET"
let task = session.dataTask(with: URL)
task.resume()
}
}
I call the function like this:
if let URL = URL(string: "https://web4host.net/5MB.zip") {
Downloader.load(URL: URL)
}
but this error message pops up:
2017-02-16 04:27:37.154780 WiFi Testing[78708:7989639] [] __nw_connection_get_connected_socket_block_invoke 2 Connection has no connected handler
2017-02-16 04:27:37.167092 WiFi Testing[78708:7989639] [] __nw_connection_get_connected_socket_block_invoke 3 Connection has no connected handler
2017-02-16 04:27:37.169050 WiFi Testing[78708:7989627] PAC stream failed with
2017-02-16 04:27:37.170688 WiFi Testing[78708:7989639] [] nw_proxy_resolver_create_parsed_array PAC evaluation error: kCFErrorDomainCFNetwork: 2
Could someone tell me what I'm doing wrong and how I could fix it? Thanks!
The code to receive the data is missing.
Either use delegate methods of URLSession or implement the dataTask method with the completion handler.
Further for a GET request you don't need an URLRequest – never use NSMutableURLRequest in Swift 3 anyway – , just pass the URL and don't use URL as a variable name, it's a struct in Swift 3
class Downloader {
class func load(url: URL) { // better func load(from url: URL)
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil)
let task = session.dataTask(with: url) { (data, response, error) in
// handle the error
// process the data
}
task.resume()
}
}
I'm currently starting to learn swift.
My first "test-app" is a simple application, which does a NSURL Session request on startup and displays the received data in a tableview.
So far, my tableView does work and also my request method runs without any compilation errors.
My problem now is, that the event handler is not being called:
func doRequest(url: String) -> String
{
var url = NSURL(string: url);
var request = NSURLRequest(URL: url!);
var config = NSURLSessionConfiguration.defaultSessionConfiguration();
var session = NSURLSession(configuration: config);
var task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
println("CALLED");
});
return "";
}
The above method doesn't print anything into the console.
Since using google did not help me to find a solution, I try my luck here.
What's the issue with my code? Am I doing something wrong without realising it?
The URL for my tests is: api.football-data.org/alpha/soccerseasons/354/leagueTable
which returns a simple json object.
Any help is appreciated!
Add task.resume() to start the download.
After you create the task, you must start it by calling its resume method.
var task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
println("CALLED");
});
task.resume()
I'm using Swift in Xcode 6.2 (beta) but had the same problem on the 6.1 release version. I'm trying to use NSURLSession and believe I have it set up correctly (see code below). The problem is that I have a delegate setup to deal with a redirect happening through the code. I actually need to capture the cookies prior to the final redirection and I'm doing this through the delegate:
func URLSession(_:NSURLSession, task:NSURLSessionTask, willPerformHTTPRedirection:NSHTTPURLResponse, newRequest:NSURLRequest, completionHandler:(NSURLRequest!) -> Void )
This works and I'm able to execute code successfully and capture the cookies I need. The problem is that I need to add task.cancel() at the end of the function or else it never seems to complete and return to the delegator (parent?) function. Because of this I lose the results from the redirect URL (although in my current project it is inconsequential). The strange thing is that this was working for a while and seemingly stopped. I don't believe I entered any code that changed it, but something had to happen. Below is the relevant code.
NSURLSession Function:
func callURL (a: String, b: String) -> Void {
// Define the URL
var url = NSURL(string: "https://mycorrecturl.com");
// Define the request object (via string)
var request = NSMutableURLRequest(URL: url!)
// Use default configuration
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
// Create the NSURLSession object with default configuration, and self as a delegate (so calls delegate method)
let session = NSURLSession(configuration: config, delegate: self, delegateQueue: nil)
// Change from default GET to POST (needed to call URL properly)
request.HTTPMethod = "POST"
// Construct my parameters to send in with the URL
var params = ["a":a, "b":b] as Dictionary<String, String>
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err)
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
// Do some other stuff after delegate has returned...
})
task.resume()
return
}
The delegate code:
func URLSession(_:NSURLSession, task:NSURLSessionTask, willPerformHTTPRedirection:NSHTTPURLResponse, newRequest:NSURLRequest, completionHandler:(NSURLRequest!) -> Void ) {
// Check Cookies
let url = NSURL(string: "https://mycorrecturl.com")
var all = NSHTTPCookie.cookiesWithResponseHeaderFields(willPerformHTTPRedirection.allHeaderFields, forURL: url!)
// Get the correct cookie
for cookie:NSHTTPCookie in all as [NSHTTPCookie] {
if cookie.name as String == "important_cookie" {
NSHTTPCookieStorage.sharedHTTPCookieStorage().setCookie(cookie)
}
}
task.cancel()
}
It used to return to the calling function without calling task.cancel(). Is there anything that looks wrong with the code that would cause it to just hang in the delegate function if task.cancel() isn't called?
Edit: What code would I add to fix this.
If you are not canceling the request, your willPerformHTTPRedirection should call the completionHandler. As the documentation says, this completionHandler parameter is:
A block that your handler should call with either the value of the request parameter, a modified URL request object, or NULL to refuse the redirect and return the body of the redirect response.
I want to send http request on every myapp-starting.
How to do this? I try:
class MainViewController: UITableViewController {
func my_request(){
let url = NSURL(string: "http://www.stackoverflow.com")
let request = NSURLRequest(URL: url)
let connection = NSURLConnection(request: request, delegate:nil, startImmediately: true)
println(connection)
}
let lol = my_request()
}
But I have an error: Missing argument for parameter #1 in call
How to fix that?
Thanks!
my_request() returns nothing, if you just want to call the function, use only
my_request()
I would suggest to put this in the ViewDidLoad function (on your Main ViewController of your App)