ios sharedsession error on completion - ios

I am blocked by this nasty error while learning iOS sharedSession singleton and async calls
here is my code
let baseUrl = NSURL(string: "https://api.forecast.io/forecast/\(apiKey)/")
let forecast = NSURL(string: "47.856223,-122.272590", relativeToURL: baseUrl)
let sharedSession = NSURLSession.sharedSession()
let downloadTask: NSURLSessionDownloadTask =
sharedSession.downloadTaskWithURL( forecast, completionHandler:
{ (loction: <#NSURL!#>, response: <#NSURLResponse!#>, error: <#NSError!#>) -> Void in
println(response);
})
}
here is where error happens
{ (loction: <#NSURL!#>, response: <#NSURLResponse!#>, error: <#NSError!#>) -> Void in
println(response);
})
here is error
1-expected an identifier to name generic parameter
2- expect parameter type following :

You need to add placeholders with appropriate variables.Replace your code with following
sharedSession.downloadTaskWithURL(forecast , completionHandler:{(location:NSURL!, response:NSURLResponse!, error:NSError!) -> Void in
println(response);
})

Related

What could be best way to reduce redundant code

I wanted to reduce repetition in this code which I got from ExDeveloper. I have a server model where I've all my networking code. Now I've just shown 3 methods here. But eventually it'll grow & there would be 70+ methods. I don't want to repeat task code which is common in all methods.
What is the best way to do it without using a 3rd party like Alamofire, etc.?
func login(userName: String, password: String, onSuccess: #escaping(JSON) -> Void, onFailure: #escaping(Error) -> Void){
let url : String = ""
let request: NSMutableURLRequest = NSMutableURLRequest(url: NSURL(string: url)! as URL)
request.httpMethod = "GET"
let session = URLSession.shared
let task = session.dataTask(with: request as URLRequest, completionHandler: {data, response, error -> Void in
if(error != nil){
onFailure(error!)
} else{
print(response as Any)
}
})
task.resume()
}
//====================
func signUp(userName: String, password: String, email: String, onSuccess: #escaping(JSON) -> Void, onFailure: #escaping(Error) -> Void){
let url : String = ""
let request: NSMutableURLRequest = NSMutableURLRequest(url: NSURL(string: url)! as URL)
request.httpMethod = "GET"
let session = URLSession.shared
let task = session.dataTask(with: request as URLRequest, completionHandler: {data, response, error -> Void in
if(error != nil){
onFailure(error!)
} else{
print(response as Any)
}
})
task.resume()
}
//====================
func forgot(email: String, onSuccess: #escaping(JSON) -> Void, onFailure: #escaping(Error) -> Void){
let url : String = ""
let request: NSMutableURLRequest = NSMutableURLRequest(url: NSURL(string: url)! as URL)
request.httpMethod = "GET"
let session = URLSession.shared
let task = session.dataTask(with: request as URLRequest, completionHandler: {data, response, error -> Void in
if(error != nil){
onFailure(error!)
} else{
print(response as Any)
}
})
task.resume()
}
You could split up the requests into more modular components like network layers.
Check out this guide: https://medium.com/#danielemargutti/network-layers-in-swift-7fc5628ff789
As you've written the above code, each function is exactly identical. So put that in a separate function that they all call. If there are parts that aren't identical (that you didn't provide), then pass those to the shared function. If there is code that changes, pass that as a function parameter.
In short: extract the parts that don't change, and pass the parts that do as parameters.

How to solve Xcode error message 'url' instance member cannot be used on type 'view controller'

I typed the following swift code in Xcode and it shows error message
'url' instance member cannot be used on type 'view controller'
here's my code-
let url = NSURL(string: "http://www.stackoverflow.com")!
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) -> Void in
}
Here's the code for Swift 3 and the error message of Xcode 8.2.1 (current version):
let url = URL(string: "http://www.stackoverflow.com")!
var task = URLSession.shared.dataTask(with: url) {
(data: Data?, response: URLResponse?, error: Error?) in
}
and the error message in line 2 is now:
Cannot use instance member 'url' within property initializer; property initializers run before 'self' is available
This makes it more clear, I think. Creating the task must be done later in a function like viewDidLoad.
This code would work (well, at least it compiles):
var task: URLSessionTask?
override func viewDidLoad() {
super.viewDidLoad()
if let url = URL(string: "http://www.stackoverflow.com") {
task = URLSession.shared.dataTask(with: url) {
(data: Data?, response: URLResponse?, error: Error?) in
// Handle response and errors here
}
}
// Do any additional setup after loading the view.
}
It should be called in the below way.
let url = "www.example.com"
let urlRequest = URLRequest(url: URL(string: url)! )
let urlSession = URLSession.shared
let task = urlSession.dataTask(with: rssRequest) { (data, response, error) in
//get your response and error here
}
Steps:
Create the URL request
Create the shared session
download the contents from the URL

SWIFT: session.dataTaskWithURL

I am trying to follow a tutorial on Swift, but the code does not work in Swift 3. Can anyone help update the code?
let url = NSURL(string: path)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url!) {
(data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
print(">>>>> \(data)")
}
I have tried following the suggestions by the compiler, and have changed several of the keywords. The code now looks like this:
let url = NSURL(string: path)
let session = URLSession.shared
let task = session.dataTaskWithURL(url! as URL) {
(data: NSData?, response: URLResponse?, error: NSError?) -> Void in
print(">>>>> \(data)")
}
The error message is:
Cannot convert value of type '(NSData?, URLResponse?, NSError?) -> Void' to expected argument type '(Data?, URLResponse?, Error?) -> Void'
Source Tutorial: Build a simple weather App https://www.youtube.com/watch?v=AoYTuhWZFqM&list=PLoN_ejT35AEjBQ33-L8h2IwG11amXssGk#t=540.527064
let url = URL(string:path)
let session = URLSession.shared
let task = session.dataTask(with: url!) { (data:Data?, response:URLResponse?, error:Error?) in
print()
}

Swift 3 getURL Ambiguous Data [duplicate]

Hello I have working json parsing code for swift2.2 but when i use it for Swift 3.0 gives me that error
ViewController.swift:132:31: Ambiguous reference to member 'dataTask(with:completionHandler:)'
My code is here:
let listUrlString = "http://bla.com?batchSize=" + String(batchSize) + "&fromIndex=" + String(fromIndex)
let myUrl = URL(string: listUrlString);
let request = NSMutableURLRequest(url:myUrl!);
request.httpMethod = "GET";
let task = URLSession.shared().dataTask(with: request) {
data, response, error in
if error != nil {
print(error!.localizedDescription)
DispatchQueue.main.sync(execute: {
AWLoader.hide()
})
return
}
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSArray
if let parseJSON = json {
var items = self.categoryList
items.append(contentsOf: parseJSON as! [String])
if self.fromIndex < items.count {
self.categoryList = items
self.fromIndex = items.count
DispatchQueue.main.async(execute: {
self.categoriesTableView.reloadData()
AWLoader.hide()
})
}else if( self.fromIndex == items.count){
DispatchQueue.main.async(execute: {
AWLoader.hide()
})
}
}
} catch {
AWLoader.hide()
print(error)
}
}
task.resume()
Thanks for ideas.
The compiler is confused by the function signature. You can fix it like this:
let task = URLSession.shared.dataTask(with: request as URLRequest) {
But, note that we don't have to cast "request" as URLRequest in this signature if it was declared earlier as URLRequest instead of NSMutableURLRequest:
var request = URLRequest(url:myUrl!)
This is the automatic casting between NSMutableURLRequest and the new URLRequest that is failing and which forced us to do this casting here.
You have init'd myRequest as NSMutableURLRequest, you need this:
var URLRequest
Swift is ditching both the NSMutable... thing. Just use var for the new classes.
Xcode 8 and Swift 3.0
Using URLSession:
let url = URL(string:"Download URL")!
let req = NSMutableURLRequest(url:url)
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)
let task : URLSessionDownloadTask = session.downloadTask(with: req as URLRequest)
task.resume()
URLSession Delegate call:
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask,
didWriteData bytesWritten: Int64, totalBytesWritten writ: Int64, totalBytesExpectedToWrite exp: Int64) {
print("downloaded \(100*writ/exp)" as AnyObject)
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL){
}
Using Block GET/POST/PUT/DELETE:
let request = NSMutableURLRequest(url: URL(string: "Your API URL here" ,param: param))!,
cachePolicy: .useProtocolCachePolicy,
timeoutInterval:"Your request timeout time in Seconds")
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers as? [String : String]
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest) {data,response,error in
let httpResponse = response as? HTTPURLResponse
if (error != nil) {
print(error)
} else {
print(httpResponse)
}
DispatchQueue.main.async {
//Update your UI here
}
}
dataTask.resume()
Working fine for me.. try it 100% result guarantee
This problem is caused by URLSession has two dataTask methods
open func dataTask(with request: URLRequest, completionHandler: #escaping (Data?, URLResponse?, Error?) -> Swift.Void) -> URLSessionDataTask
open func dataTask(with url: URL, completionHandler: #escaping (Data?, URLResponse?, Error?) -> Swift.Void) -> URLSessionDataTask
The first one has URLRequest as parameter, and the second one has URL as parameter, so we need to specify which type to call, for example, I want to call the second method
let task = URLSession.shared.dataTask(with: url! as URL) {
data, response, error in
// Handler
}
In my case error was in NSURL
let url = NSURL(string: urlString)
In Swift 3 you must write just URL:
let url = URL(string: urlString)
Tested xcode 8 stable version ; Need to use var request variable with URLRequest() With thats you can easily fix that (bug)
var request = URLRequest(url:myUrl!) And
let task = URLSession.shared().dataTask(with: request as URLRequest) { }
Worked fine ! Thank you guys, i think help many people. !
For Swift 3 and Xcode 8:
var dataTask: URLSessionDataTask?
if let url = URL(string: urlString) {
self.dataTask = URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in
if let error = error {
print(error.localizedDescription)
} else if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 {
// You can use data received.
self.process(data: data as Data?)
}
})
}
}
//Note: You can always use debugger to check error
In swift 3 the compiler is confused by the function signature. Specifying it will clear the error. Also convert the url string to type URL. The following code worked for me.
let urlString = "http://bla.com?batchSize="
let pathURL = URL(string: urlString)!
var urlRequest = URLRequest(url:pathURL)
let session = URLSession.shared
let dataTask = session.dataTask(with: urlRequest as URLRequest) { (data,response,error) in
Short and concise answer for Swift 3:
guard let requestUrl = URL(string: yourURL) else { return }
let request = URLRequest(url:requestUrl)
URLSession.shared.dataTask(with: request) {
(data, response, error) in
...
}.resume()
// prepare json data
let mapDict = [ "1":"First", "2":"Second"]
let json = [ "title":"ABC" , "dict": mapDict ] as [String : Any]
let jsonData : NSData = NSKeyedArchiver.archivedData(withRootObject: json) as NSData
// create post request
let url = NSURL(string: "http://httpbin.org/post")!
let request = NSMutableURLRequest(url: url as URL)
request.httpMethod = "POST"
// insert json data to the request
request.httpBody = jsonData as Data
let task = URLSession.shared.dataTask(with: request as URLRequest){ data,response,error in
if error != nil{
return
}
do {
let result = try JSONSerialization.jsonObject(with: data!, options: []) as? [String:AnyObject]
print("Result",result!)
} catch {
print("Error -> \(error)")
}
}
task.resume()
To load data via a GET request you don't need any URLRequest (and no semicolons)
let listUrlString = "http://bla.com?batchSize=" + String(batchSize) + "&fromIndex=" + String(fromIndex)
let myUrl = URL(string: listUrlString)!
let task = URLSession.shared.dataTask(with: myUrl) { ...
let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: { data,response,error in
if error != nil{
print(error!.localizedDescription)
return
}
if let responseJSON = (try? JSONSerialization.jsonObject(with: data!, options: [])) as? [String:AnyObject]{
if let response_token:String = responseJSON["token"] as? String {
print("Singleton Firebase Token : \(response_token)")
completion(response_token)
}
}
})
task.resume()
Xcode 10.1 Swift 4
This worked for me:
let task: URLSessionDataTask = session.dataTask(with: request as URLRequest) { (data, response, error) -> Void in
...
The key was adding in the URLSessionDataTask type declaration.
For me I do this to find,
let url = URL(string: urlString)
URLSession.shared.dataTask(with: url!) { (data, response, error) in ...}
Can't use
"let url = NSURL(string: urlString)

NSURLSessionDownloadTask API call clarification on syntax in Swift

I'm learning to do a basic networking call, and following a tutorial. The tutorial goes through concurrency, and downloading the JSON data in the background thread. I was wondering why in the sharedSession.downloadTaskWithURL method the queryURL would be passed as the NSURL object as opposed to the baseURL. I feel like I'm missing something pretty obvious!
func searchRecipeData() {
let baseURL = NSURL(string: "http://api.recipes.com/v1/api/recipes?_app_id=\(apiID)&_app_key=\(apiKey)")
let queryURL = NSURL(string: "&q=onion+soup", relativeToURL: baseURL)!
let sharedSession = NSURLSession.sharedSession()
let downloadData: NSURLSessionDownloadTask = sharedSession.downloadTaskWithURL(queryURL, completionHandler: { (location: NSURL!, response: NSURLResponse!, error: NSError!) -> Void in
if (error == nil) {
let data = NSData(contentsOfURL: baseURL!)
println(data)
}
})
// Resumes it even though it hasn't started yet
downloadData.resume()
}
Take a look at the second parameter where you create queryURL. You are passing the baseURL constant. What happens is that the '&q=onion+soup' query parameter is told to be relative to the baseURL. The queryURL constant is the full URL, and it is then passed to downloadTaskWithURL.

Resources