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. UseHH
instead+zzzz
is invalid timezone specifier. UseZ
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.latitude),\(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.latitude),\(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
Format Println Output in a Table
Swift: How to Flush Stdout After Println
How to 'Addtarget' to Uilabel in Swift
Command Failed Due to Signal: Segmentation Fault: 11 While Emitting Ir Sil Function
Generic Method Override Not Working in Swift
Generic and (Early) Binding in Swift 1.2
Can a Condition Be Used to Determine the Type of a Generic
Avaudiosinknode with Non-Default, But Still Device-Native Sample Rates
Distributednotificationcenter - How to Pass Data Between Applications
Function Builder Not Working When Only One Value
How to Cancel Firebase Setvalue While Pending for Completion (When Offline)
Suppress Warnings from Dependencies with Swift Package Manager
Swift Change the Tableviewcell Border Color According to Data
How to Detect Text View Begin Editing and End Editing in Swift 3
Fullscreen for Swift Playgrounds on iPad
Swift Combine: What Are Those Multicast Functions for and How to Use Them