In my iPhone application (develops in SWIFT) I've got to communicate with a https service (with parameters) and needs to analyse the response.
All works ok but in some cases noticed it does NOT getting the expected result... Further analysing I found it's the problem about converting server respone data to string (NSData -> NSString)...
1). When I use UTF8 Encoding I am getting nil as converted String (responseString )
let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
2). But with ASCII encoding it's fine (Gets the correct response server provides)
let responseString = NSString(data: data, encoding: NSASCIIStringEncoding)
Following is a full sample code I am trying...
let myUrl = NSURL(string: "https://myurl.com/myservice.asp")
let request = NSMutableURLRequest(URL: myUrl!)
request.HTTPMethod = "POST"
request.timeoutInterval = 55.0
let postString = "paramone=\(para1)¶mtwo=\(para2)¶mthree=\(para3)"
// NOTE: Works ok with ASCII AND UTF8 both encoding types at this point...
// request.HTTPBody = postString.dataUsingEncoding(NSASCIIStringEncoding)
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
if (error != nil)
{
println("Error: \(error)")
println("Description: \(error.description)")
println("Domain : \(error.domain)")
println("Error code : \(error.code)")
}
else
{
//???? => ENCODING PROBLEM
// let responseString = NSString(data: data, encoding: NSASCIIStringEncoding)
let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Response: \(responseString)")
}
}
task.resume()
I came across with few other POSTS explaining the same issue... But NOT sure if it's good to go with ASCII rather than UTF8...
Also I can't understand the response contains '£' sign and works ok with ASCII encoding (eventhough '£' is NOT in ASCII character Set), BUT NOT with UTF8.
Like to hear if I am missing anything or what the best way to go with this... Thanks.
To convert an Int value to a String value in Swift, use String(). String() accepts integer as argument and returns a String value created using the given integer value.
Overview. The NSURLSession class and related classes provide an API for downloading data from and uploading data to endpoints indicated by URLs. Your app can also use this API to perform background downloads when your app isn't running or, in iOS, while your app is suspended.
Data in Swift 3 is a struct that conforms to collection protocol. It is a collection of bytes ( [UInt8] array of unsigned integer 8 bits 0-255). – Leo Dabus.
NSASCIIStringEncoding
is documented as a strict 7-bit encoding
for the ASCII values 0 .. 127. However, experiments show that when
decoding NSData
to (NS)String
, it accepts arbitrary data and
interprets the bytes 0 .. 255 as the Unicode characters U+0000 .. U+00FF.
So when decoding, NSASCIIStringEncoding
behaves identically to
NSISOLatin1StringEncoding
:
let bytes = (0 ..< 256).map { UInt8($0) }
let data = NSData(bytes: bytes, length: bytes.count)
let s1 = String(data: data, encoding: NSASCIIStringEncoding)!
let s2 = String(data: data, encoding: NSISOLatin1StringEncoding)!
print(s1 == s2) // true
This can explain why a character like "£" is decoded correctly even if it is not in the ASCII character set.
But note that this behavior is (as far as I know) not documented, so you should not rely on it. Also this does not work when encoding
(NS)String
to NSData
:
let d1 = s1.dataUsingEncoding(NSASCIIStringEncoding) // nil
If the server sends a HTTP response header with a Content-Type = charset=...
field then you can detect the encoding automatically,
see https://stackoverflow.com/a/32051684/1187415.
If the server does not send the response encoding in the HTTP response header then you can only try different encodings. Frequently used encodings are
NSUTF8StringEncoding
for the UTF-8 encoding,NSWindowsCP1252StringEncoding
for the Windows-1252 encoding,NSISOLatin1StringEncoding
for the ISO-8859-1 encoding.There is also a NSString
method which can detect the used
encoding, however this requires that you write the data to a file first,
see Convert TXT File of Unknown Encoding to String.
@JibW this code will helps you to analyse response and easy to understand...do some additional changes as per your requirements.!
let URL = NSURL(string: "Paste your url here")!
var request = NSMutableURLRequest(URL: URL)
var session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
request.timeInterval = 55.0
var error: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(parameters, options: nil, error: &error)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
var data: NSData!
var response: NSURLResponse!
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
var httpResponse = response as! NSHTTPURLResponse
println("\(httpResponse.statusCode)")
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
{
// 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
var success = parseJSON["success"] as? Int
println("Succes: \(success)")
}
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)")
}
}
})
task.resume()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With