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.)
Related
I'm currently trying to get a value from an alert box in swift 3.
The below code is used to prompt the alert and save the data, however, im having trouble with calling back the data and manipulating it so it's just a basic string.
func presentAlert() {
let alertController = UIAlertController(title: "IP?", message: "Please input your unique key:", preferredStyle: .alert)
let confirmAction = UIAlertAction(title: "Confirm", style: .default) { (_) in
if let field = alertController.textFields?[0] {
// store it
UserDefaults.standard.set(field.text, forKey: "userIP")
UserDefaults.standard.synchronize()
} else {
// user did not fill field
print("no input given")
}
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (_) in }
alertController.addTextField { (textField) in
textField.placeholder = "IP"
}
alertController.addAction(confirmAction)
alertController.addAction(cancelAction)
self.present(alertController, animated: true, completion: nil)
}
This method is called here:
override func viewDidAppear(_ animated: Bool) {
presentAlert()
}
I'm trying to call it and assign it in between a string as:
let url_to_unlock:String = "http://\(UserDefaults.standard.value(forKey: "userIP")):3000/unLock"
However, this gives me the output:
http://Optional():3000/unLock
When I try to print it.
Any nudge in the correct direction would be greatly appreciated.
Class Added:
class ViewController: UIViewController {
func presentAlert() {
let alertController = UIAlertController(title: "IP?", message: "Please input your unique key:", preferredStyle: .alert)
let confirmAction = UIAlertAction(title: "Confirm", style: .default) { (_) in
if let field = alertController.textFields?[0] {
// store your data
//this could be lock unique key name etc in future
UserDefaults.standard.set(field.text, forKey: "userIP")
UserDefaults.standard.synchronize()
} else {
// user did not fill field
print("no input given")
}
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (_) in }
alertController.addTextField { (textField) in
textField.placeholder = "IP"
}
alertController.addAction(confirmAction)
alertController.addAction(cancelAction)
self.present(alertController, animated: true, completion: nil)
}
//view did appear for the alert
override func viewDidAppear(_ animated: Bool) {
presentAlert()
}
//to post to an /unLock it must be put in the URL
// let url_to_unlock:String = "http://\(UserDefaults.standard.value(forKey: "userIP")):3000/unLock"
//let url_to_lock:String = "http://\(textField):3000/Lock"
let url_to_unlock:String = "http://10.73.195.218:3000/unLock"
let url_to_lock:String = "http://10.73.195.218:3000/Lock"
override func viewDidLoad() {
super.viewDidLoad()
}
var Timestamp: String {
return "\(NSDate().timeIntervalSince1970 * 1000)"
}
func un_lock()
{
print(url_to_unlock)
let url:URL = URL(string: url_to_unlock)!
let session = URLSession.shared
let request = NSMutableURLRequest(url: url)
request.httpMethod = "POST"
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
let paramString = "data=unLocking at \(Timestamp)"
request.httpBody = paramString.data(using: String.Encoding.utf8)
let task = session.dataTask(with: request as URLRequest, completionHandler: {
(
data, response, error) in
guard let _:Data = data, let _:URLResponse = response , error == nil else {
print("error")
return
}
//for errors
let dataString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print(dataString! )
})
task.resume()
}
func lock()
{
let url:URL = URL(string: url_to_lock)!
let session = URLSession.shared
let request = NSMutableURLRequest(url: url)
request.httpMethod = "POST"
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
let paramString = "data=Locking at \(Timestamp)"
request.httpBody = paramString.data(using: String.Encoding.utf8)
let task = session.dataTask(with: request as URLRequest, completionHandler: {
(
data, response, error) in
guard let _:Data = data, let _:URLResponse = response , error == nil else {
print("error")
return
}
//for errors
let dataString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print(dataString! )
})
task.resume()
}
#IBAction func lock(_ sender: UIButton) {
lock()
}
#IBAction func unLock(_ sender: Any) {
un_lock()
}
}
Thank you.
The value for this is optional:
// let url_to_unlock:String = "http://\(UserDefaults.standard.value(forKey: "userIP")):3000/unLock"
try:
let url = UserDefaults.standard.value(forKey: "userIP")!
let url_to_unlock:String = "http://\(url):3000/unLock"
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
Kindly help me out for properly start activity indicator when button pressed and stop when process commpleted. My code is given below
startting animation
self.activityIndicator.startAnimating()
self.nextButton.enabled = false
self.activityIndicator.startAnimating()
self.newForMe()
self.finals = self.mids.filter { !self.vmids.contains($0) }
self.RandomNumber = Int(arc4random_uniform(UInt32(self.finals.count)))
let accesstoken = self.defaults.valueForKey("accesstoken")
if self.finals.count != 0
{
//self.activityIndicator.startAnimating()
self.like1Button.enabled = true
self.imgView.hidden = false
self.vview.hidden = true
if self.vc.isConnectedToNetwork() {
let jSon2 = JSON(data: NSData(contentsOfURL: NSURL(string: "https://api.instagram.com/v1/media/\(self.finals[self.RandomNumber])?access_token=\(accesstoken!)")!)!, options: NSJSONReadingOptions.AllowFragments, error: nil)
self.st = jSon2["data"]["images"]["low_resolution"]["url"].stringValue
self.firstCardString = NSURL(string: self.st)!
let con = jSon2["data"]["user_has_liked"].boolValue
if con == true {
self.nextPressed(self)
}
}else {
// print("No Connectivity")
}
// print(con)
let data = NSData(contentsOfURL: self.firstCardString)
if data != nil
{
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.imgView.image = UIImage(data: data!)
dispatch_async(dispatch_get_main_queue(), {
self.activityIndicator.stopAnimating()
})
})
}
self.nextButton.enabled = true
}
stoping animation
I am astoping it here then also it not starting exectly
else {
self.like1Button.enabled = false
self.imgView.image = UIImage(named: "download (1)")
let alert = UIAlertController(title: "No Photo to like", message: "There is no photo to like!!", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: { (UIAlertAction) -> Void in
// self.like1Button.hidden = true
self.imgView.image = nil
self.activityIndicator.stopAnimating()
}))
self.presentViewController(alert, animated: true, completion: nil)
}
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)
}
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 */
})