I am downloading HTML source code of a webpage this way:
let url = NSURL(string: "http://www.example.com")
var error: NSError?
let html = NSString(contentsOfURL: url!, encoding: NSUTF8StringEncoding, error: &error)
if (error != nil) {
println("whoops, something went wrong")
} else {
println(html!)
}
But I would like to get it as String instead of NSString. Is there any way?
Swift's String also accepts the same initializer:
let html = String(contentsOfURL: url!, encoding: NSUTF8StringEncoding, error: &error)
I would suggest to use safe unwrapping with if let for your values:
var error: NSError?
if let url = NSURL(string: "http://www.example.com"), let html = String(contentsOfURL: url, encoding: NSUTF8StringEncoding, error: &error) {
if error != nil {
println(error)
} else {
println(html)
}
}
Last note: no need to use brackets around the condition in Swift.
Update for Swift 2 (Xcode 7)
if let url = NSURL(string: "http://www.example.com"),
let html = try? String(contentsOfURL: url, encoding: NSUTF8StringEncoding) {
print(html)
}
Related
Right now I have this:
let path : String = NSBundle.mainBundle().pathForResource("jsonFile", ofType: "json") as String!
let jsonData = NSData(contentsOfFile: path) as NSData!
let readableJSON = JSON(data :jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil)
But I want to receive the file from a url, and not have it in my app.
You need to read through some of apple docs: NSURLConnection and NSURLSession
Here is a quick solution for how to achieve this though.
func fetchDetailsFromServer() {
let urlPath = "Server URL to Fetch JSON"
let url = NSURL(string: urlPath)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url!, completionHandler: {data, response, error -> Void in
println("Task completed")
if(error != nil) {
// If there is an error in the web request, print it to the console
println(error.localizedDescription)
}
var err: NSError?
if let jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as? NSDictionary {
if(err != nil) {
// If there is an error parsing JSON, print it to the console
println("JSON Error \(err!.localizedDescription)")
}
// Use your jsonResult appropriately here
}
})
// The task is just an object with all these properties set
// In order to actually make the web request, we need to "resume"
task.resume()
}
I am trying to code a login system with jSon. I can receive and parse the results but when i am trying to use values i am receiving fatal errors.
My code:
var request = NSMutableURLRequest(URL: NSURL(string: "http://www.somedomain.com/api/login.php")!)
var session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
var params:NSDictionary = ["e":"\(email)", "p":"\(passwd)"]
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: NSJSONWritingOptions.allZeros, error: &err)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Body: \(strData)")
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSDictionary
if(err != nil) {
println(err!.localizedDescription)
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: '\(jsonStr)'")
}
else {
if let parseJSON = json {
var success = parseJSON["result"] as? Int
var msg = parseJSON["msg"] as? String
println("Succes: \(success!)") // This works fine i can receive the success variable from json
if success! == 1 { // this line throws error as "fatal error: unexpectedly found nil while unwrapping an Optional value"
// Do something...
} else {
// Do something...
}
}
} else {
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: \(jsonStr)")
}
}
})
task.resume()
What's the problem with my code? I can not use the values that i received from jSon in my code. I am really confused with the "Optional" thing...
When i use values in println() everything is fine, but when i use the values in code that crashes... By the way it was working fine until today :S
This is the error:
Body: Optional({"result":1,"id":"2","name":"tt","msg":"Login successfull"})
Succes: 1
fatal error: unexpectedly found nil while unwrapping an Optional value
Thanks...
Below is my login function. It's a JSON POST request and before, when the URL was http, it worked flawlessly. I attached a JSON filled with the username/password of the user. Today we added a SSL Certificate and after switching the URL to https, it produced this error:
NSURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9843)
I'm not really sure what's going on. I typed that error into google and didn't get any where. I appreciate any help, thank you!
func login(params : Dictionary<String, String>, url : String, postCompleted : (succeeded: Bool, msg: String) -> ()) {
var request = NSMutableURLRequest(URL: NSURL(string: url)!)
var session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
if response != nil {
if response.isKindOfClass(NSHTTPURLResponse) {
httpResponse = response as NSHTTPURLResponse
if let authorizationID = httpResponse.allHeaderFields["Authorization"] as String! {
Locksmith.saveData(["id":authorizationID], forUserAccount: currentUser, inService: "setUpAuthorizationId")
}
else {
println("Failed")
}
}
}
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSDictionary
// Did the JSONObjectWithData constructor return an error? If so, log the error to the console
if(err != nil) {
println(err!.localizedDescription)
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: '\(jsonStr!)'")
postCompleted(succeeded: false, msg: "Error")
}
else {
// The JSONObjectWithData constructor didn't return an error. But, we should still
// check and make sure that json has a value using optional binding.
if let parseJSON = json {
// Okay, the parsedJSON is here, let's get the value for 'success' out of it
if let status = parseJSON["status"] as? String {
if let extractData = parseJSON["data"] as? NSDictionary {
let extractUserId:Int = extractData["id"] as Int
userId = extractUserId
}
if status == "success" {
postCompleted(succeeded: true, msg: "Logged in.")
} else {
let failMessage = parseJSON["message"] as? String
postCompleted(succeeded: false, msg: failMessage!)
}
}
return
}
else {
// Woa, okay the json object was nil, something went worng. Maybe the server isn't running?
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: \(jsonStr)")
postCompleted(succeeded: false, msg: "Error")
}
}
})
task.resume()
}
Using This awesome article I was able to fix my problem. All I needed to do was add:
NSObject, NSURLSessionDelegate, NSURLSessionTaskDelegate
after my class name, and then add these two delegates:
func URLSession(session: NSURLSession,
didReceiveChallenge challenge:
NSURLAuthenticationChallenge,
completionHandler:
(NSURLSessionAuthChallengeDisposition,
NSURLCredential!) -> Void) {
completionHandler(
NSURLSessionAuthChallengeDisposition.UseCredential,
NSURLCredential(forTrust:
challenge.protectionSpace.serverTrust))
}
func URLSession(session: NSURLSession, task: NSURLSessionTask, willPerformHTTPRedirection response: NSHTTPURLResponse, newRequest request: NSURLRequest, completionHandler: (NSURLRequest!) -> Void) {
var newRequest : NSURLRequest? = request
println(newRequest?.description);
completionHandler(newRequest)
}
after that in my actual request I just needed to change:
var session = NSURLSession.sharedSession()
to:
var configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
var session = NSURLSession(configuration: configuration, delegate: self, delegateQueue:NSOperationQueue.mainQueue())
hope this helps someone!!
I am trying to parse JSON result obtained from Playframewordk 1.2 into swift.
Playframework result:
public JsonObject getJson() {
JsonObject jsonObject = new JsonObject();
if (codeJson != null) {
for (String field : codeArticleFields) {
if (codeJson.has(field)) {
jsonObject.add(field, codeJson.get(field));
}
}
}
return jsonObject;
}
view playframework
#{extends 'main.html' /}
#{set title:'Test' /}
#{set 'moreScripts' }
#{/set}
${product?.getJson()}
Here is the code of swift:
func connectProductDatabase() {
let urlString = "http://api.autoidlabs.ch/test/" + "4025089060857"
let url: NSURL = NSURL(string: urlString)!
var request : NSMutableURLRequest = NSMutableURLRequest()
request.URL = url
request.HTTPMethod = "GET"
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(), completionHandler: {
(response:NSURLResponse!, data: NSData!, error: NSError!) -> Void in
var error: NSError?
if let result = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &error)
as? NSArray {
let dataArray = result[0] as NSArray
println(dataArray)
} else {
let resultString = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Flawed JSON String: \(resultString)")
}
})
println("not connected")
}
As a result I am getting the entire file with all HTML tag. This is because it is not entering into the if statement. (I also tried with options:NSJSONReadingOptions.MutableContainers)
I tried with lot of result found from stackoverflow, but getting the same problem. If I understand well, the playframework view is not really returning a JSON, JsonObject of java is a formatted String as JSON.
How can I solve this problem?
I was able to solve the problem.
Instead of NSArray I used NSDictionary
if let result = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error)
as? NSDictionary {
and then in playframework I used renderJSON instead of render.
Why am I unable to parse JSON from the HTTP response via the following code?
if let url = NSURL(string: "https://2ch.hk/b/threads.json") {
let task = NSURLSession.sharedSession().dataTaskWithURL(url) {
(data, response, error) in
var jsonError: NSError?
let jsonDict = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &jsonError) as [String: AnyObject]
if jsonError != nil {
return
}
// ...
}
task.resume()
}
Output
fatal error: unexpectedly found nil while unwrapping an Optional value
What am I doing wrong? How can I fix it?
Thanks in advance.
This is a bit late.... but I think you are trying to parse the error as well so add an else part and and the dictionary to be serialized will only be parsed if there is the data ... your code can be modified as follows
if let url = NSURL(string: "https://2ch.hk/b/threads.json") {
let task = NSURLSession.sharedSession().dataTaskWithURL(url) {
(data, response, error) in
if (jsonError != nil) {
return
} else {
var jsonError: NSError?
let jsonDict = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &jsonError) as [String: AnyObject]}
// ...
}
task.resume()
}