Swift 3: Converting Data to String Returns a Nil Value

Swift 3: Converting Data to String returns a nil value

This doesn't work because when you interpret the bytes of the Image as a String, the string is invalid. Not every jumble of data is a valid utf8 string. i.e. not every collection of n bits (8, sometimes 16) are a valid utf8 code point. The Swift String api loops through the data object you pass it to validate that it is a valid string. In your case, theres no reason to think that this Data is a valid string, so it doesn't work.

A good read on utf8:
https://www.objc.io/issues/9-strings/unicode/

Why doesn't cast work from NSData to String? Swift

Note: I don't speak Swift. This following code may not compile, but it should give you the main idea/logic behind it.

The issue was because there NSData was incomplete (you receive them piece by piece and the buffer size may not be sufficient to handle the complete response at once), assuming that the bytes are really transformable to NSString according to the encoding used, as @zaph pointed out.
Simple example: Transform a UIImage into NSData using UIImageJPEGRepresentation() for example, and try to transform it into NSString using the wanted encoding, it may not be valid, or do the same with the stream of a video.

An example for our case:

Full valid "Character": "1001", nothing with "10" nor "01".

You receive "10" only. And if you convert it to NSString, it's nil because it's not valid.

Then, you receive "01". And if you convert it to NSString, it's nil because it's not valid.

So you have to read all the NSData before transforming it to NSString.

So at the beginning, you can create a var finalData = NSMutableData.init()
Then, each time you read the buffer, do:

var partialData = NSData.init(bytes: data, length: data.count)
finalData.appendData(partialData)

At the end, just transform finalData to String:

if let str = String(data:finalData, encoding: NSUTF8StringEncoding) {
response = str
}

Swift 3.0 Converting String to Double returning nil?

Most likely there is an additional space in your data, note:

print(Double("-85.1113644443208")) // => Optional(-85.111364444320799)
print(Double("-85.1113644443208 ")) // => nil
print(Double(" -85.1113644443208")) // => nil

Try to trim the spaces first:

let doubleLong = Double(long.trimmingCharacters(in: CharacterSet.whitespaces))

or use a NumberFormatter for parsing:

let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .decimal
numberFormatter.locale = Locale(identifier: "en_US_POSIX")

print(numberFormatter.number(from: "-85.1113644443208") as Double?) // => Optional(-85.111364444320799)
print(numberFormatter.number(from: " -85.1113644443208") as Double?) // => Optional(-85.111364444320799)
print(numberFormatter.number(from: "-85.1113644443208 ") as Double?) // => Optional(-85.111364444320799)

Conversion from string to date in swift returns nil

You set the wrong format specifier for hour and timezone. Use this:

dateFormatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ss Z"
dateFormatter.locale = Locale(identifier: "en_US")
  • hh means 12-hour format so there's no hour 15. Use HH instead
  • +zzzz is invalid timezone specifier. Use Z instead
  • Unless Friday is shortened to Fri in Bulgarian, use an English locale

Why is my variable returning a nil after being converted to an int?

Even simpler, though slightly a trick, you can use integerValue:

temperatureString.integerValue

Unlike toInt, integerValue will stop converting when it finds a non-digit (it also throws away leading spaces.

If temperatureString is a String (rather than an NSString), you'll need to push it over:

(temperatureString as NSString).integerValue

Convert base 64 string into image return nil in swift

The problem is that the string you pass to Data(base64Encoded: is not actually base64encoded, it contains some more plaintext in the front.

You need to remove that and only pass the actual base64 encoded image, like so:

let str = "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQ..."
let dataDecoded : Data = Data(base64Encoded: str)!
let decodedimage = UIImage.init(data: dataDecoded)

Alternatively you can programatically split the original data at the , and take the second part as the actual data input.

At that point you can remove the options: .ignoreUnknownCharacters as well since now there should not be any non-base64 chars left - and if there are you should fix the data instead of the code.

Final note: depending on where you get the data from it might be a good idea to not force-unwrap anything and instead deal with a broken / missing image by e.g. displaying a placeholder image.

Convert Data to String in Swift 3

This is an example using a completion handler:

class func getFilm(filmID: Int, completion: @escaping (String) -> ()) {
let url = URL(string: "https://api.kinopoisk.cf/getFilm?filmID=\(filmID)")!

URLSession.shared.dataTask(with:url) { (data, response, error) in
if error != nil {
print(error!)
completion("")
} else {
if let returnData = String(data: data!, encoding: .utf8) {
completion(returnData)
} else {
completion("")
}
}
}.resume()
}

And you call it

MyClass.getFilm(filmID:12345) { result in
print(result)
}

In case of an error the completion handler returns an empty string.

MyClass is the enclosing class of getFilm method. Most likely the web service will return JSON, so you might need to deserialize the JSON to an array or dictionary.


In a more sophisticated version create an enum with two cases and associated values

enum ConnectionResult {
case success(String), failure(Error)
}

With a little more effort demonstrating the subtle power of Swift you can return either the converted string on success of the error on failure in a single object.

class func getFilm(filmID: Int, completion: @escaping (ConnectionResult) -> ()) {
let url = URL(string: "https://api.kinopoisk.cf/getFilm?filmID=\(filmID)")!

URLSession.shared.dataTask(with:url) { (data, response, error) in
if error != nil {
completion(.failure(error!))
} else {
if let returnData = String(data: data!, encoding: .utf8) {
completion(.success(returnData))
} else {
completion(.failure(NSError(domain: "myDomain", code: 9999, userInfo: [NSLocalizedDescriptionKey : "The data is not converible to 'String'"])))
}
}
}.resume()
}

On the caller side a switch statement separates the cases.

MyClass.getFilm(filmID:12345) { result in
switch result {
case .success(let string) : print(string)
case .failure(let error) : print(error)
}
}

Convert String to NSURL is return nil in swift

As suggested by the Martin R, I see THIS post and I converted that objective-c code to swift and I got this code:

var url : NSString = "https://maps.googleapis.com/maps/api/distancematrix/json?origins=\(self.latitud‌​e),\(self.longitude)&destinations=\(self.stringForDistance)&language=en-US" 
var urlStr : NSString = url.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
var searchURL : NSURL = NSURL(string: urlStr)!
println(searchURL)

and this is working correctly.

For swift 3.0:

let url : NSString = "https://maps.googleapis.com/maps/api/distancematrix/json?origins=\(self.latitud‌​e),\(self.longitude)&destinations=\(self.stringForDistance)&language=en-US"
let urlStr : NSString = url.addingPercentEscapes(using: String.Encoding.utf8.rawValue)! as NSString
let searchURL : NSURL = NSURL(string: urlStr as String)!
print(searchURL)


Related Topics



Leave a reply



Submit