NSURL problems in Swift - ios

I'm building a weather app and this whole block of code is an error. I've tried almost everything.
This is the code:
func getCurrentWeatherData() -> Void {
let baseURL = NSURL(string: "https://api.forecast.io/forecast/\(apiKey)/")
let forecastURL = NSURL(string: "37.8267,-122.423", relativeToURL: baseURL)
let sharedSession = NSURLSession.sharedSession()
let downloadTask: NSURLSessionDownloadTask = sharedSession.downloadTaskWithURL(forecastURL!, completionHandler: { (location: NSURL!, response: NSURLResponse!, error: NSError!) -> Void in
if (error == nil){
let dataObject = NSData(contentsOfURL: location)
let weatherDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(dataObject, options: nil, error: nil) as NSDictionary
let currentWeather = Weather(weatherDictionary: weatherDictionary)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.currentTemperature.text = "\(currentWeather.temperature)"
self.iconView.image = currentWeather.icon!
let formatter = NSDateFormatter()
formatter.timeStyle = .ShortStyle
self.currentTime.text = formatter.stringFromDate(NSDate())
self.humidity.text = "\(Int(currentWeather.humidity * 100))%"
self.rain.text = "\(Int(currentWeather.precipProbability))%"
self.summary.text = "\(currentWeather.summary)"
self.refreshActivityIndicator.stopAnimating()
self.refreshActivityIndicator.hidden = true
self.refreshButton.hidden = false
})
} else {
let networkIssueController = UIAlertController(title: "Error", message: "Unable to load data. Connectivity error!", preferredStyle: .Alert)
let okButton = UIAlertAction(title: "OK", style: .Default, handler: nil)
networkIssueController.addAction(okButton)
let cancelButton = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
networkIssueController.addAction(cancelButton)
self.presentViewController(networkIssueController, animated: true, completion: nil)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.refreshActivityIndicator.stopAnimating()
self.refreshActivityIndicator.hidden = true
self.refreshButton.hidden = false
})
}
})
}
This is the error:
"/Users/Ethan/Downloads/Weather-master/Weather/ViewController.swift:39:117: '(NSURL!, NSURLResponse!, NSError!) -> Void' is not convertible to '(NSURL?, NSURLResponse?, NSError?) -> Void'"
Edit
Solve error above one...now the
Code is:
let weatherDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(dataObject, options: nil, error: nil) as NSDictionary
error is
/Users/Ethan/Downloads/Weather-master/Weather/ViewController.swift:42:85: Extra argument 'error' in call

change
location: NSURL!, response: NSURLResponse!, error: NSError!
to
location: NSURL?, response: NSURLResponse?, error: NSError?
if you are using swift2
do {
let jsonResult = try NSJSONSerialization.JSONObjectWithData(dataObject, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary
} catch let error as NSError {
print(error)
}

Related

How can I get data from API in Swift?

How can I get location, time, lng, lat, mag and depth data from this API in Swift?
https://api.hknsoft.com/earthquake/v1/last24hours?limit=500
//API
let url = URL(string: "https://api.hknsoft.com/earthquake/v1/last24hours?limit=500")
let session = URLSession.shared
let task = session.dataTask(with: url!) { data, response, error in
if error != nil {
let alert = UIAlertController(title: "Error!", message: error?.localizedDescription, preferredStyle: UIAlertController.Style.alert)
let okButton = UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil)
alert.addAction(okButton)
self.present(alert, animated: true, completion: nil)
} else {
if data != nil {
do {
let jsonResponse = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as! Dictionary<String, Any>
DispatchQueue.main.async {
//print(jsonResponse)
if let result = jsonResponse["earthquakes"] as? [String : Any] {
if let location = result["location"] as? String {
print(location)
}
if let time = result["time"] as? String {
print(time)
}
if let mag = result["mag"] as? Double {
print(mag)
}
if let lat = result["lat"] as? Double {
print(lat)
}
if let lng = result["lng"] as? Double {
print(lng)
}
if let depth = result["depth"] as? Double {
print(depth)
}
}
}
} catch {
print("alert")
let alert = UIAlertController(title: "Error!", message: error.localizedDescription, preferredStyle: UIAlertController.Style.alert)
let okButton = UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil)
alert.addAction(okButton)
self.present(alert, animated: true, completion: nil)
}
}
}
}
task.resume()

S3 stop uploading files iOS

I have 2 application, one in swift and the other in objective-c, I'm using cognito to authenticate with s3 but the last days this feature stop working I down know why, the console of my application say "request timed out" but I don't change anything. the application start uploading but always stops in 39% or 14% and freeze the upload, this is my code:
App delegate:
let credentialsProvider = AWSCognitoCredentialsProvider(regionType:.USEast1,
identityPoolId:poolId)
AWSLogger.defaultLogger().logLevel = .Verbose
let configuration = AWSServiceConfiguration(region:.SAEast1, credentialsProvider:credentialsProvider)
AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = configuration
PhotoViewController
let uploadRequest = AWSS3TransferManagerUploadRequest()
uploadRequest.bucket = "bucket"
uploadRequest.ACL = AWSS3ObjectCannedACL.PublicRead
uploadRequest.key = "\(self.userLogin.customer_subdomain)/photos/\(imageName)"
uploadRequest.contentType = "image/png"
uploadRequest.body = url
uploadRequest.uploadProgress = { (bytesSent:Int64, totalBytesSent:Int64, totalBytesExpectedToSend:Int64) -> Void in
dispatch_sync(dispatch_get_main_queue(), {() -> Void in
self.updateLabel(totalBytesSent,totalBytesExpectedToSend: totalBytesExpectedToSend)
})
}
AWSS3TransferManager.defaultS3TransferManager().upload(uploadRequest).continueWithBlock { (task) -> AnyObject! in
if (task.error != nil) {
//failed
dispatch_async(dispatch_get_main_queue()) {
self.dismissViewControllerAnimated(false, completion: nil)
let refreshAlert = UIAlertController(title: "Error", message: "Error al intentar subir el archivo", preferredStyle: UIAlertControllerStyle.Alert)
refreshAlert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
self.presentViewController(refreshAlert, animated: true, completion: nil)
}
print(task.error!)
} else {
let dic=["file":"\(self.userLogin.customer_subdomain)/photos/\(imageName)"]
let jsonData = try! NSJSONSerialization.dataWithJSONObject(dic, options: [])
let jsonString = NSString(data: jsonData, encoding: NSUTF8StringEncoding)! as String
let con:URLConnection
con=URLConnection.init()
con.delegate=self
let headers=["X-Auth-Token":self.userLogin.api_token]
con.connect(self.userLogin.customer_url+"/rest/activities/\(self.activity.id)/photos",method:"POST",json: jsonString, headers: headers)
self.imgName = "\(self.userLogin.customer_subdomain)/photos/\(imageName)"
}
return nil
}
thank you!
was the datetime of the device, always need to be the correct hour

How to use closures to return a JSON value from a NSURLSession

I am trying to return a result from a JSON object but unable to do so. I am new to Swift so kindly explain me how to do so. In the below code I want to return json_level_number in the return of function fetchNumberOfSections () where i have hard coded as 5 right now return 5. If i declare a variable json_level_number just above the reachability code it sort of solves the problem but then it is returning '0' for the first time. The API returns 2 each time.
Code as below:
func fetchNumberOfSections () -> Int {
if Reachability.isConnectedToNetwork() == true {
// Below code to fetch number of sections
var urlAsString = "http://themostplayed.com/rest/fetch_challenge_sections.php"
urlAsString = urlAsString+"?apiKey="+apiKey
print (urlAsString)
let url = NSURL(string: urlAsString)!
let urlSession = NSURLSession.sharedSession()
let jsonQuery = urlSession.dataTaskWithURL(url, completionHandler: { data, response, error -> Void in
if (error != nil) {
print(error!.localizedDescription)
}
do {
let jsonResult = (try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)) as! NSDictionary
let json_level_number: String! = jsonResult["level_number"] as! String
//
dispatch_async(dispatch_get_main_queue(), {
// self.dateLabel.text = jsonDate
// self.timeLabel.text = jsonTime
print(json_level_number)
// self.activityIndicatorStop()
})
}
catch let errorJSON {
print (errorJSON)
// alert box code below
let alert = UIAlertController(title: "JSON Error!", message:"Error processing JSON.", preferredStyle: .Alert)
let action = UIAlertAction(title: "OK", style: .Default) { _ in
// Put here any code that you would like to execute when
self.dismissViewControllerAnimated(true, completion: {})
}
alert.addAction(action)
self.presentViewController(alert, animated: true, completion: nil)
// alert box code end
}
})
jsonQuery.resume()
// End
}
else {
print("Internet connection FAILED")
self.performSegueWithIdentifier("nointernet", sender: nil)
}
return 5
}

Tab with UITableView takes long to load

I have a tab that contains a UITableView. The UITableView loads JSON from a server. Here are some lines in my viewDidLoad():
// Register the UITableViewCell class with the tableView
self.tableView?.registerClass(UITableViewCell.self, forCellReuseIdentifier: self.cellIdentifier)
var tblView = UIView(frame: CGRectZero)
tableView.tableFooterView = tblView
tableView.backgroundColor = UIColor.clearColor()
startConnection()
Here is my startConnection():
func startConnection() {
let url = NSURL(string: "some correct URL")
var request = NSURLRequest(URL: url!)
var data = NSURLConnection.sendSynchronousRequest(request, returningResponse: nil, error: nil)
if data != nil {
var json = JSON(data: data!)
if let jsonArray = json.arrayValue {
for jsonDict in jsonArray {
var pageName: String? = jsonDict["title"].stringValue
//some code
}
}
activityIndicator.stopAnimating()
} else {
println("No data")
activityIndicator.stopAnimating()
var alert = UIAlertController(title: "No data", message: "No data received", preferredStyle: UIAlertControllerStyle.Alert)
let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel) { (action) in
}
alert.addAction(cancelAction)
let OKAction = UIAlertAction(title: "Retry", style: .Default) { (action) in
self.startConnection()
}
alert.addAction(OKAction)
self.presentViewController(alert, animated: true, completion: nil)
}
}
After the first load, the tab will show upon clicking. I am thinking if it is the NSURLConnection.sendSynchronousRequest causing the lag. Any advice and suggestion? I don't really know how to use sendAsynchronousRequest either =/ Please help. Thank you! =D
Although there are several ways to get data from a website, the important thing is that you execute your UI updates on the main thread using dispatch_async(dispatch_get_main_queue()) {}. This is because URL tasks such as NSURLSession.dataTaskWithURL or NSURLConnection.sendAsynchronousRequest() {} execute on a background thread so if you don't explicitly update UI on the main thread you will often experience a lag. Here's what a simple request looks like:
func fetchJSON(sender: AnyObject?) {
let session = NSURLSession.sharedSession()
let url: NSURL! = NSURL(string: "www.someurl.com")
session.dataTaskWithURL(url) { (data, response, error) in
var rawJSON: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: .allZeros, error: nil)
if let result = rawJSON as? [[String: AnyObject]] {
dispatch_async(dispatch_get_main_queue()) {
// Update your UI here ie. tableView.reloadData()
}
}
}.resume()
}
You can do it like this:
let url:NSURL = NSURL(string:"some url")
let request:NSURLRequest = NSURLRequest(URL:url)
let queue:NSOperationQueue = NSOperationQueue()
NSURLConnection.sendAsynchronousRequest(request, queue: queue, completionHandler:{ (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in
/* Your code */
})

Get Nil When Trying to Reuse NSURL

I'm trying to get the weather of some locations using https://developer.forecast.io/ api.
The format of API call is https://api.forecast.io/forecast/APIKEY/LATITUDE,LONGITUDE
I can get response from one position, but when I tried to change the location and get the weather again use NSURL, the NSURL returns Nil. Why is that and how to handle this?
Can anyone helps me out? Thanks.
func getCurrentWeatherData() -> Void {
let baseURL = NSURL(string: "https://api.forecast.io/forecast/\(apiKey)/")
var forecastURL = NSURL(string: "36.107728,-112.113040", relativeToURL: baseURL)
let sharedSession = NSURLSession.sharedSession()
let downloadTask: NSURLSessionDownloadTask = sharedSession.downloadTaskWithURL(forecastURL!, completionHandler: {
(location: NSURL!, response: NSURLResponse!, error: NSError!) -> Void in
//var urlContents = NSString(contentsOfURL: location, encoding: NSUTF8StringEncoding, error: nil)
if (error == nil) {
let dataObject = NSData(contentsOfURL: location)
let weatherDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(dataObject!, options: nil, error: nil) as NSDictionary
let currentWeather = Current(weatherDictionary: weatherDictionary)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.iconView.image = currentWeather.icon!
self.currentTimeLabel.text = "At \(currentWeather.currentTime!) it is"
self.temperatureLabel.text = "\(Double(currentWeather.temperature-32) * 0.56)"
self.summaryLabel.text = "\(currentWeather.summary)"
self.refreshActivityIndicator.stopAnimating()
self.refreshActivityIndicator.hidden = true
self.refreshButton.hidden = false
})
} else {
let networkIssueController = UIAlertController(title: "Error", message:"Unable to load data. Connectivity error!", preferredStyle: .Alert)
let okButton = UIAlertAction(title: "OK", style: .Default, handler:nil)
networkIssueController.addAction(okButton)
let cancelButton = UIAlertAction(title:"Cancel", style: .Cancel, handler:nil)
networkIssueController.addAction(cancelButton)
self.presentViewController(networkIssueController, animated: true, completion: nil)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.refreshActivityIndicator.stopAnimating()
self.refreshActivityIndicator.hidden = true
self.refreshButton.hidden = false
})
}
})
downloadTask.resume()
var forecastURL2 = NSURL(string: "https://api.forecast.io/forecast/\(apiKey)/36.861941, -111.374420")
let sharedSession2 = NSURLSession.sharedSession()
**//forcastURL2 returns Nil**
let downloadTask2: NSURLSessionDownloadTask = sharedSession2.downloadTaskWithURL(forecastURL2!, completionHandler: {
(location: NSURL!, response: NSURLResponse!, error: NSError!) -> Void in
//var urlContents = NSString(contentsOfURL: location, encoding: NSUTF8StringEncoding, error: nil)
if (error == nil) {
let dataObject = NSData(contentsOfURL: location)
let weatherDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(dataObject!, options: nil, error: nil) as NSDictionary
let currentWeather = Current(weatherDictionary: weatherDictionary)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.iconView2.image = currentWeather.icon!
self.temperatureLabel2.text = "\(Double(currentWeather.temperature-32) * 0.56)"
self.summaryLabel.text = "\(currentWeather.summary)"
self.refreshActivityIndicator.stopAnimating()
self.refreshActivityIndicator.hidden = true
self.refreshButton.hidden = false
})
} else {
let networkIssueController = UIAlertController(title: "Error", message:"Unable to load data. Connectivity error!", preferredStyle: .Alert)
let okButton = UIAlertAction(title: "OK", style: .Default, handler:nil)
networkIssueController.addAction(okButton)
let cancelButton = UIAlertAction(title:"Cancel", style: .Cancel, handler:nil)
networkIssueController.addAction(cancelButton)
self.presentViewController(networkIssueController, animated: true, completion: nil)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.refreshActivityIndicator.stopAnimating()
self.refreshActivityIndicator.hidden = true
self.refreshButton.hidden = false
})
}
})
downloadTask2.resume()
}
The URL that you use ("https://api.forecast.io/forecast/\(apiKey)/36.861941, -111.374420") should be well formatted and, according to Apple, comply with RFC2396. If not NSURL will return nil.
The url that you use is not correct. For example space should be escape using "%20". In your case, I think you can just remove the space.
Delete the space:
var forecastURL2 = NSURL(string: "https://api.forecast.io/forecast/\(apiKey)/36.861941,-111.374420")
Also, for future questions, it would be helpful if you didn't post all of the code in your method, but rather just the code necessary to reproduce the issue (in this case, just this one line was necessary.)

Resources