Swift 3 better way to unwrap an optional - swift

Right now I have some code that looks like the following:
let msg: String? = myStr.removingPercentEncoding ?? nil
print("msg \(msg!)")
I really don't like the use of ! in msg! as that can possibly throw an exception, I believe.
What's the best way to call myStr.removingPercentEncoding if myStr is not nil and then unwrap msg without throwing an exception?

The proper way would be:
if let msg = myStr.removingPercentEncoding {
print("msg \(msg)")
}
Here, msg is only valid inside the if statement and only if myStr.removingPercentEncoding isn't nil.
If you wish to print something if myStr.removingPercentEncoding is nil, then you could and an else:
if let msg = myStr.removingPercentEncoding {
print("msg \(msg)")
} else {
print("msg has no value")
}
Read up on Optional Binding in the The Swift Programming Language book.

This line is completely useless, when myStr.removingPercentEncoding is nil, then nil (right hand side of ??) is assigned to msg:
let msg: String? = myStr.removingPercentEncoding ?? nil
Why don't you make it as:
let msg: String = myStr.removingPercentEncoding ?? ""
print("msg \(msg)")

Related

How to read null values from SQLite database using Swfit [duplicate]

I am reading from a dbtable and get an error at a specific position of the table. My sql is ok, because I could already read from the same table, but at a specific row I get an error and I would like to know howto handle this error. I am not looking for a solution to solve my db-issue, I am just looking for handling the error, so it doesn't crash.
I have the following code :
let unsafepointer=UnsafePointer<CChar>(sqlite3_column_text(statement, 2));
if unsafepointer != nil {
sText=String.fromCString(unsafepointer)! // <<<<<< ERROR
} else {
sText="unsafe text pointer is nil !";
}
I get an error:
"fatal error: unexpectedly found nil while unwrapping an Optional value"
at line marked with <<<<<< ERROR.
The unsafe pointer's value is not nil:
pointerValue : 2068355072
How can I handle this error, so my app is not crashing ?
Another possible solution is this:
let unsafepointer=UnsafePointer<CChar>(sqlite3_column_text(statement, 2));
var sText = "unsafe text pointer is nil !";
if unsafepointer != nil{
if let text = String.fromCString(unsafepointer) as String?{
sText = text;
}
}
let statementValue = sqlite3_column_text(statement, 2)
var sText = withUnsafeMutablePointer(&statementValue) {UnsafeMutablePointer<Void>($0)}
if sqlite3_column_text(statement, 2) != nil {
print("do something")
} else {
YourString = ""
}

How to unwrap optional value in swift?

code correct
print(error!.localizedDescription)
}else{
return
To replace a nil value we need to unwrap optional value this done according to type of value.
i.e. if value is string then we need to add ?? "" or if value is double we need to add ?? 0.0
As in case of the above scenario (EmailTextField.text ?? "") this is the format to replace unwrap optional value .
Auth.auth().createUser(withEmail: (txtEmail.text ?? ""), password: (txtPass.text ?? "")) { (result, error) in
if let _eror = error {
//something bad happning
print(_eror.localizedDescription )
}else{
//user registered successfully
print(result)
}
}
This error clearly indicates that you have forced unwrap the optional somewhere in your code.
Remove force unwrapping (!) by optional binding in your code.
Ways to optional binding...
if let
guard let
nil coalescing i.e ??
Look for exclaimation mark in your code, where you have force
unwrapped and replace it with one of the above way.

Trying to do deal with errors and optionals the right way

I am attempting to use SwiftSoup to scrape some HTML. This example, based on the SwiftSoup github documentation, works fine…
func scrape() throws {
do {
let htmlFromSomeSource = "<html><body><p class="nerp">HerpDerp</p><p class="narf">HoopDoop</p>"
let doc = try! SwiftSoup.parse(htmlFromSomeSource)
let tag = try! doc.select("p").first()!
let tagClass = try! tag.attr("class")
} catch {
print("oh dang")
throw Abort(.notFound)
}
print(tagClass)
}
… Up until I mess with the selector or attribute targets, at which point everything crashes thanks to the implicitly unwrapped optionals (which I assume was just quick-and-dirty code to get smarter people started). That do/catch doesn't seem to help at all.
So what's the Right way? This compiles...
print("is there a doc?")
guard let doc = try? SwiftSoup.parse(response.body.description) else {
print("no doc")
throw Abort(.notFound)
}
print("should halt because there's no img")
guard let tag = try? doc.select("img").first()! else {
print("no paragraph tag")
throw Abort(.notFound)
}
print("should halt because there's no src")
guard let tagClass = try? tag.attr("src") else {
print("no src")
throw Abort(.notFound)
}
... but again if I mess with the selector or attribute it crashes out, "Unexpectedly found nil while unwrapping an Optional value" (after "is there a doc?"). I thought guard would halt the process when it encountered a nil? (If I convert "try?" to "try" the compiler complains that "initializer for conditional binding must have Optional type"…)
If you declare the function as throws you don't need a do - catch block inside the function. Just remove the block and the exclamation marks after try to pass through the errors to the caller function.
func scrape() throws { // add a return type
let htmlFromSomeSource = "<html><body><p class="nerp">HerpDerp</p><p class="narf">HoopDoop</p>"
let doc = try SwiftSoup.parse(htmlFromSomeSource)
guard let tag = try doc.select("p").first() else { throw Abort(.notFound) }
let tagClass = try tag.attr("class")
// return something
}

Should we do nil check for non-optional variables?

I have a function (abc) as follows and I should throw an error when the arguments passed are empty or nil, should I check for nil too or only empty is enough?
public func abc(forURL serviceUrl:String,serviceID:String, error:inout Error? )throws ->[AnyHashable : Any]{
guard serviceUrl != nil, !serviceUrl.isEmpty else {
let argError:Error = MapError.emptyArgumentUrl.error()
error = argError
throw argError
}
guard !serviceID.isEmpty else {
let argError:Error = MapError.emptyArgumentServiceId.error()
error = argError
throw argError
}
serviceID is not an optional.
That means it can't be nil.
So no, there is no need for that check.

unexpectedly found nil while unwrapping an Optional value while reading from DS with fromCString

I am reading from a dbtable and get an error at a specific position of the table. My sql is ok, because I could already read from the same table, but at a specific row I get an error and I would like to know howto handle this error. I am not looking for a solution to solve my db-issue, I am just looking for handling the error, so it doesn't crash.
I have the following code :
let unsafepointer=UnsafePointer<CChar>(sqlite3_column_text(statement, 2));
if unsafepointer != nil {
sText=String.fromCString(unsafepointer)! // <<<<<< ERROR
} else {
sText="unsafe text pointer is nil !";
}
I get an error:
"fatal error: unexpectedly found nil while unwrapping an Optional value"
at line marked with <<<<<< ERROR.
The unsafe pointer's value is not nil:
pointerValue : 2068355072
How can I handle this error, so my app is not crashing ?
Another possible solution is this:
let unsafepointer=UnsafePointer<CChar>(sqlite3_column_text(statement, 2));
var sText = "unsafe text pointer is nil !";
if unsafepointer != nil{
if let text = String.fromCString(unsafepointer) as String?{
sText = text;
}
}
let statementValue = sqlite3_column_text(statement, 2)
var sText = withUnsafeMutablePointer(&statementValue) {UnsafeMutablePointer<Void>($0)}
if sqlite3_column_text(statement, 2) != nil {
print("do something")
} else {
YourString = ""
}