Parsing JSON Swift 3 with error Code=3840 - xcode

I have this error.
Error Domain=NSCocoaErrorDomain Code=3840 "Garbage at end." UserInfo={NSDebugDescription=Garbage at end.}
Here is my swift code.
let request = NSMutableURLRequest(url: NSURL(string: "http://example.org/file.php")! as URL)
request.httpMethod = "POST"
let task = URLSession.shared.dataTask(with: request as URLRequest) {
old_data, response, error in
//Error Checking
if error != nil {
print("error=\(error)")
return
}
print("response = \(response)")
//Response string built up
let responseString = NSString(data: old_data!, encoding: String.Encoding.utf8.rawValue)
print("responseString = \(responseString)")
//Manipulating the JSON data
var names = [String]()
do {
if let new_data = old_data,
let json = try JSONSerialization.jsonObject(with: new_data) as? [String: Any],
let buildings = json["buildings"] as? [[String: Any]] {
for building in buildings {
if let name = building["BuildingName"] as? String {
names.append(name)
}
}
}
} catch {
print(error)
}
print("Names: \(names)")
}
task.resume()
The error is happening in my 'do' statement where 'let buildings = json["buildings"]'
And below is what I get when I print the response string.
responseString = Optional({"buildings":[{"BuildingID":"2","BuildingName":"School of Informatics and Comp","Info":"School of higher learning.","Latitude":"39.172085","Longitude":"-86.522908"}]}Successfully Retrieved. SELECT * FROM Buildings;)
Any questions or advice is appreciated

Related

Swift 2 How do I isolate resources in a series of NSMutableURLRequests?

Assume I've already logged to two accounts and have obtained unique session cookies for each.
When executing ViewController.run(), which uses nested closures, a series of 80 unique URL requests is made (40 for each of the two accounts) .
Though I'm able to make all 80 unique URL requests, somehow one account will sometimes make a request of a URL that only the other account should be making.
I'm pretty certain the resources between each account as well as each account's request are isolated. Both executions of run() construct their own instances of Visit(_:), URLVisitor(_:) and Request(_:).
Note: assume that neither account's username array contains a username that the other has in it's array.
ViewController.swift
func run(completion: () -> Void) {
// 40 usernames appended to array
var usernames: [String] = ["username1",..., username40]
for username in usernames {
let visit = Visit()
visit.sessionCookie = sessionCookie
visit.visitProfile(username) {
NSThread.sleepForTimeInterval(5.0)
}
}
}
Visit.swift
var contentsOfURL = NSString()
var sessionCookie = String()
func visitprofile(username: String, completion: () -> Void) {
let url = "https://www.someurl.com/profile/\(username)"
let encodedURL = url.stringByAddingPercentEncodingWithAllowedCharacters(
NSCharacterSet.URLFragmentAllowedCharacterSet()),
URL = NSURL(string: encodedURL!)
let vis = URLVisitor(URL: URL!)
vis.sessionCookie = self.sessionCookie
vis.execute {
if vis.containsString(profileName) {
print("\(profileName) visited: OK")
} else {
print("\(profileName) visited: FAIL")
}
completion()
}
}
URLVisitor.swift
var contentsOfURL = NSString()
var sessionCookie = String()
var URL = NSURL()
init(URL: NSURL) {
self.URL = URL
}
func execute(completion: () -> Void) {
let request = Request()
request.sessionCookie = self.sessionCookie
request.accessToken = self.accessToken
request.sessionCookie = self.sessionCookie
request.sendRequest(self.URL, completion: () -> Void) {
self.sessionCookie = request.sessionCookie
self.contentsOfURL = request.contentsOfURL
completion()
}
}
Request.swift: NSObject, NSURLSessionDelegate
var contentsOfURL = NSString()
var responseCookies = String()
var sessionCookie = String()
func sendRequest(URL: NSURL, completion: () -> Void) {
var request = NSMutableURLRequest(URL: URL)
var session = NSURLSession.sharedSession()
var config = NSURLSessionConfiguration.defaultSessionConfiguration()
if sessionCookie != "" {
config.HTTPCookieStorage = nil
config.requestCachePolicy = .ReloadIgnoringLocalAndRemoteCacheData
request.setValue(sessionCookie, forHTTPHeaderField: "Cookie")
session = NSURLSession(configuration: config, delegate: self, delegateQueue: nil)
}
request.HTTPBody = params.dataUsingEncoding(NSUTF8StringEncoding)
request.HTTPMethod = "GET"
let task = session.dataTaskWithRequest(request) { (data, response, error) in
let response = response as! NSHTTPURLResponse
do {
self.contentsOfURL = try NSString(contentsOfURL: URL, encoding: NSUTF8StringEncoding)
} catch{
}
if self.sessionCookie == "" {
self.sessionCookie = // obtained here during login
}
completion()
}
task.resume()
}

Swift 2 OSX How do I implement proxy settings with NSURLSession?

With iOS I was able to get as far as a 407 error requiring authorization. With OSX, no such luck. After the task resumes, it just hangs for a long time then reports that a connection couldn't be made.
If you answer, please also include how to pass proxy username and password.
func sendRequest() {
var proxyHost : CFString = NSString(string: "12.345.67.89") as CFString
var proxyPort : CFString = NSString(string: "1234") as CFString
var proxyEnable : CFNumber = NSNumber(int: 1) as CFNumber
var proxyDict: [NSObject : AnyObject] = [
kCFNetworkProxiesHTTPEnable: proxyEnable,
kCFStreamPropertyHTTPProxyHost: proxyHost,
kCFStreamPropertyHTTPProxyPort: proxyPort,
kCFStreamPropertyHTTPSProxyHost: proxyHost,
kCFStreamPropertyHTTPSProxyPort: proxyPort,
kCFProxyTypeKey: kCFProxyTypeHTTPS
]
let request = NSMutableURLRequest(URL: NSURL(string:https://www.someurl.com/login))
var configuration = NSURLSessionConfiguration.ephemeralSessionConfiguration()
let configuration.connectionProxyDictionary = proxyDict
let session = NSURLSession(configuration: configuration, delegate: self, delegateQueue: NSOperationQueue.mainQueue())
let task = session.dataTaskWithRequest(request) { (data, response, error) in
NSHTTPCookieStorage.sharedHTTPCookieStorage().setCookies([NSHTTPCookie](), forURL: self.URL, mainDocumentURL: nil)
if data != nil {
do {
let responseHeaders = response as! NSHTTPURLResponse
self.statusCode = responseHeaders.statusCode
switch self.statusCode {
case 200:
self.contentsOfURL = try NSString(contentsOfURL: self.URL, encoding: NSUTF8StringEncoding)
self.cookies = NSHTTPCookieStorage.sharedHTTPCookieStorage().cookiesForURL(self.URL)!
for cookie in self.cookies {
if cookie.name == "session" {
self.sessionCookie = cookie.value
}
}
case 400:
print("400: page not found on web")
case 404:
print("404: page not found on server")
case 407:
print("407: failed authenticate proxy credentials")
default:
print("unable to get statusCode")
}
} catch {
}
} else {
print("\(self.statusCode): unable to get response ")
}
dispatch_semaphore_signal(semaphore)
}
task.resume()
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
}

In change of Swift 2 Extra argument ' error' in call

Upgrade to Xcode 7 Swift 2 and SDK for iOS 9. I get the error "extra argument" error "in call" my code is:
let myUrl = NSURL(string: "http://localhost/SwiftAppAndMySQL/scripts/registerUser.php");
let request = NSMutableURLRequest(URL:myUrl!);
request.HTTPMethod = "POST";
let postString = "userEmail=\(userEmail)&userFirstName=\(userFirstName)&userLastName=\(userLastName)&userPassword=\(userPassword)";
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { (data:NSData!, response:NSURLResponse!, error:NSError!) -> Void in
dispatch_async(dispatch_get_main_queue())
{
spinningActivity.hide(true)
if error != nil {
self.displayAlertMessage(error.localizedDescription)
return
}
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: &err) as? NSDictionary
if let parseJSON = json {
var userId = parseJSON["userId"] as? String
if( userId != nil)
{
var myAlert = UIAlertController(title: "Alert", message: "Registration successful", preferredStyle: UIAlertControllerStyle.Alert);
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default){(action) in
self.dismissViewControllerAnimated(true, completion: nil)
}
myAlert.addAction(okAction);
self.presentViewController(myAlert, animated: true, completion: nil)
} else {
let errorMessage = parseJSON["message"] as? String
if(errorMessage != nil)
{
self.displayAlertMessage(errorMessage!)
}
}
}
}
}).resume()
NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler ) asks you for 3 optionals arguments and you're giving 3 forceds unwrapping arguments.
try change
NSURLSession.sharedSession().dataTaskWithRequest(request) { (data:NSData!, response:NSURLResponse!, error:NSError!)
to
NSURLSession.sharedSession().dataTaskWithRequest(request) { (data:NSData?, response:NSURLResponse?, error:NSError?)
Now is working, I replaced the previous code with this::
let myUrl = NSURL(string: "http://dcapp1.testingview.com/DryCleanAppClientes/scripts/registerUser.php");
let request = NSMutableURLRequest(URL:myUrl!);
request.HTTPMethod = "POST";
let postString = "userEmail=\(userEmail)&userFirstName=\(userFirstName)&userLastName=\(userLastName)&userPassword=\(userPassword)";
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
print(postString)
NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in
dispatch_async(dispatch_get_main_queue())
{
spinningActivity.hide(true)
if error != nil {
self.displayAlertMessage(error!.localizedDescription)
return
}
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary
if let parseJSON = json {
let userId = parseJSON["userId"] as? String
if( userId != nil)
{
let myAlert = UIAlertController(title: "Mensaje", message: "¡Registro exitoso!", preferredStyle: UIAlertControllerStyle.Alert);
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default){(action) in
self.dismissViewControllerAnimated(true, completion: nil)
}
myAlert.addAction(okAction);
self.presentViewController(myAlert, animated: true, completion: nil)
} else {
let errorMessage = parseJSON["message"] as? String
if(errorMessage != nil)
{
self.displayAlertMessage(errorMessage!)
}
}
}
} catch _ as NSError {
}
}
}).resume()
}

How can I send apikey for authenticaion using Swift in OSX?

I am building a Mac App using Swift. Here is my code
import Cocoa
import AppKit
import Foundation
class ViewController: NSViewController {
#IBOutlet var Email: NSTextField!
#IBOutlet var Password: NSSecureTextField!
#IBAction func signup(sender: AnyObject) {
let signup_url = NSURL(string: "https://my_own_domain.com")
NSWorkspace.sharedWorkspace().openURL(signup_url!)
}
#IBOutlet var progress: NSProgressIndicator!
#IBAction func Signin(sender: AnyObject) {
self.progress.hidden = false
self.progress.startAnimation(self)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let userPasswordString = "\(Email.stringValue):\(Password.stringValue)"
let userPasswordData = userPasswordString.dataUsingEncoding(NSUTF8StringEncoding)
let base64EncodedCredential = userPasswordData!.base64EncodedStringWithOptions(nil)
let authString = "Basic \(base64EncodedCredential)"
println("\(authString)")
config.HTTPAdditionalHeaders = ["Authorization" : authString]
let session = NSURLSession(configuration: config)
var running = false
let url = NSURL(string: "https://my_own_domain.com/api/v3/auth/token/")
let task = session.dataTaskWithURL(url!) {
(let data, let response, let error) in
if let httpResponse = response as? NSHTTPURLResponse {
let dataString = NSString(data: data, encoding: NSUTF8StringEncoding)
self.progress.stopAnimation(self)
self.progress.hidden = true
if httpResponse.statusCode == 401 {
self.progress.hidden = true
let alertPopup:NSAlert = NSAlert()
alertPopup.addButtonWithTitle("OK")
alertPopup.informativeText = "Mistakes happen. Go and Enter correctly now :)"
alertPopup.messageText = "Please Enter Valid Credentials"
alertPopup.runModal()
}
running = false
if let dirs = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true) as? [String] {
println("\(dirs[0])")
let path = dirs[0].stringByAppendingPathComponent("user_apikey_details.json")
let path_file = dirs[0].stringByAppendingPathComponent(path)
var jsonData = NSData(contentsOfFile: path_file, options: nil, error: nil)
let folder_path = dirs[0].stringByAppendingPathComponent("/SYNC_FOLDER")
let filemanager: NSFileManager = NSFileManager()
let folder = filemanager.createDirectoryAtPath(folder_path, withIntermediateDirectories: true, attributes: nil, error: nil)
dataString?.writeToFile(path, atomically: true, encoding: NSUTF8StringEncoding, error: nil)
if let file_data = String(contentsOfFile: path, encoding: NSUTF8StringEncoding, error: nil) {
println("\User apikey has been saved to file. file data is: \(file_data)")
var string: String = file_data
var split = string.stringByReplacingOccurrencesOfString("\"", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
var split2 = split.stringByReplacingOccurrencesOfString(",", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
var splitted_data = split2.componentsSeparatedByString(" ")
println("\(splitted_data)")
var savestring : NSUserDefaults = NSUserDefaults.standardUserDefaults()
savestring.setObject(splitted_data[1], forKey: "SavedString")
savestring.synchronize()
}
}
}
running = false
}
running = false
task.resume()
while running {
println("Connecting...")
sleep(1)
}
}
override func viewDidLoad() {
super.viewDidLoad()
progress.hidden = true
// Do any additional setup after loading the view.
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
}
Here in the above code, I am authenticating to my api and getting the json data of apikey and storing it in one file. In splitted_data[1], i get only apikey here.
I have a requirement to get data from other url of the same api. For getting the data, now I need to send the apikey for that api. Previously I have done with the chromeapp and I used to sent as apikey yashwanthbabu.gujarthi#gmail.com:5c9ba3e84ec8ebd1062ddc4e94e5f0c15df8cade.
In this way i used to send the apikey to GET and POST the data. But in swift I used to do the same but it was not authenticating.
In the same way you can send the apikey for the url.
let config1 = NSURLSessionConfiguration.defaultSessionConfiguration()
let apikeystring = "apikey \(self.Email.stringValue):\(splitted_data[1])"
config1.HTTPAdditionalHeaders = ["Authorization" : apikeystring]
let session1 = NSURLSession(configuration: config1)
let url1 = NSURL(string: "https://my_own_domain.com/api/v3/some_thing")
let task1 = session1.dataTaskWithURL(url1!) {
(let data1, let response1, let error1) in
if let httpResponse1 = response1 as? NSHTTPURLResponse {
let dataStr = NSString(data: data1, encoding: NSUTF8StringEncoding)
let mem_path = dirs[0].stringByAppendingPathComponent("mems.json")
let mem_file = dirs[0].stringByAppendingPathComponent(mem_path)
dataStr?.writeToFile(mem_path, atomically: true, encoding: NSUTF8StringEncoding, error: nil)
if let mem_data = String(contentsOfFile: mem_path, encoding: NSUTF8StringEncoding, error: nil) {
println("FILE_DATA\(mem_data)")
}
}
Hope this will definitely work for you.

NSURLSessionDataTask: func receives but returns no data

I've tried to create a simple function which receives URL and simply returns the HTML of the webpage. the NSURLSessionDataTask itself seems to work, I can see the whole html when I println(data). But the func only returns the initial value "#!?". I suspect that the DataTask works asynchronous? How can I handle this?
func loadHTML(targetURL: String) -> String {
var theTargetURL = NSURL(string:targetURL)
var theResult = "#!?"
var request: NSURLRequest = NSURLRequest(URL:theTargetURL)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config)
let task : NSURLSessionDataTask = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
println(NSString(data: data, encoding: NSASCIIStringEncoding))
if error != nil {
println(error.localizedDescription)
theResult = "error"
}
if data != nil {
theResult = NSString(data: data, encoding: NSASCIIStringEncoding)
println("RECEIVED\t\t\(countElements(theResult)) CHARS")
}
});
task.resume()
return theResult
}
Here is an example how you would do it using a completion handler.
typealias CompletionBlock = (NSData!, NSURLResponse!, NSError!) -> Void
func loadHtml(targetUrlString: String, completion: CompletionBlock){
let targetUrl = NSURL(string: targetUrlString)
let request = NSURLRequest(URL: targetUrl)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request, completionHandler: completion)
task.resume()
}
Then, call it from your method where it is needed,
func viewDidLoad(){
super.viewDidLoad()
loadHtml("http://google.com", completion: { (responseData: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
if responseData != nil{
let resultString = NSString(data: responseData, encoding: NSASCIIStringEncoding)
println(resultString)
/*
do some task or update on the main thread
dispatch_async(dispatch_get_main_queue){
myActivityIndicator.stopAnimating()
}
*/
}else if error != nil{
println("Error occurred: \(error.localizedDescription)")
}
})

Resources