Swift returning optional value

I'm currently working on an Xcode app that allows a user to register by sending data to my MySQL database. I just have a couple of questions. The first question I have is on lines 10, 13, 15 i have a warning sent to me saying: "String interpolation produces a debug description for an optional value; did you mean to make this explicit?" Is there anyway I can change my code so that the value isn't optional? Also, the response string that is sent is worded like: "responseString = Optional( This username is available)". I was planning on using the response string to display information to the user. Is there anyway that I can get rid of the parenthesis and well as the word optional? I really appreciate anyone that can help!



@IBAction func TextFieldEditingDidChange(_ sender: Any) {
let request = NSMutableURLRequest(url: NSURL(string: "usernamecheck.php")! as URL)
request.httpMethod = "POST"
rint("Request: \(request)")
let postString = "username=\(usernameTxt.text!)"
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if error != nil {
print("error=\(error)")
return
} // Ends errror If statements
print("response = \(response)")
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("responseString = \(responseString)")
} // Ends let task
task.resume()

}

portion of PHP file:


$a_sql = mysqli_query($con, "SELECT username FROM users WHERE username = '" . mysqli_real_escape_string($_POST['username']) . "' ; ");
if (empty($_POST['username'])) {
$username_error = "Please input username";
} else {
$a_sql;
} if ($a_sql && mysqli_num_rows($a_sql) > 0) {
$username_exists = "Username is already taken.";
echo $username_exists;
} else {
echo "Fail";
}
Accepted Answer

You use many classic `NS-` types where you have no need to use them. In addition, in Swift convention, only type names uses capitalized identifiers.

So, I start with this equivalent code:


    @IBAction func textFieldEditingDidChange(_ sender: Any) {
        var request = URLRequest(url: URL(string: "usernamecheck.php")!)
        request.httpMethod = "POST"
        print("Request: \(request)")
        let postString = "username=\(usernameTxt.text!)"
        request.httpBody = postString.data(using: .utf8)
        let task = URLSession.shared.dataTask(with: request) {
            data, response, error in
            if error != nil {
                print("error=\(error)")
                return
            } // Ends errror If statements
            print("response = \(response)")
            let responseString = String(data: data!, encoding: .utf8)
            print("responseString = \(responseString)")
        } // Ends let task
        task.resume()
    }


The first question

Is there anyway I can change my code so that the value isn't optional?

You have four ways to work with Optionals:


  1. Forced Unwrapping
  2. Optional Chaining
  3. Conditional Binding
  4. Supplying Default Value


#1 Forced Unwrapping

As you are already using in lines 02, 05 and 14. Use postfix `!`. But be careful, this may cause your app crash, when the value actually is nil.


#2 Optional Chaining

This is useful when you want to call some method if and only if the actual value is non-nil. To your code, this may not be easily applied.


#3 Conditional Binding

For example, lines 09-12 in your code:

            if error != nil {
                print("error=\(error)")
                return
            } // Ends errror If statements

These lines can be re-written using Conditional Binding like this:

            if let error = error {
                print("error=\(error)")
                return
            } // Ends errror If statements

This updated code introduces new non-Optional local variable `error` which shadows the outer `error`.


#4 Supplying Default Value

In Swift, there's an operator called nil-coalescing represented by `??`. With this, you can change your line 14 to something like this:

            let responseString = String(data: data!, encoding: .utf8) ?? "Non-UTF8 data received"

With this change, when the result of `String(data: data!, encoding: .utf8)` becomes nil, `responseString` becomes "Non-UTF8 data received" and its type is inferred as non-Optional.


Use the most appropriate one where you need it.


For example, I would replace your line 13 as:

            print("response = \(response ?? "nil")")


And the second question

Is there anyway that I can get rid of the parenthesis and well as the word optional?


The warning message you have referred is suggesting that you may get such String like "Optional(...)".

With the change I have shown above, `print("responseString = \(responseString)")` would not output "Optional(...)".

Well, this answers my question in the other thread — you have the latest version of Swift, because this behavior is something others have been complaining about recently.


The problem arises like this:


— The NSString(data:encoding:) method returns an optional NSString, because it can fail if the data doesn't match the encoding.


— The print function has recently been changed to show a warning if you try to insert (via "\(…)") an optional value into the printed string.


If you click on the warning icon, you'll see that the compiler offers you two "fix-its". One is to remove the optionality via a "String(describing:)" construct. The other is to provide an explicit value when the string is nil. You can use either of these two suggestions, but the real problem is that the nil value only arises if you got invalid data back from the server (not a valid UTF-8 string).


So, your best option is to test for the optional value, so that by the time you print it, you know it's good. That does mean, though, that you'll need a real strategy for handling errors — including the earlier case where the "error" parameter is non-nil. Simply printing an error message isn't good enough, because the user won't see that, and your app will mysteriously fail.

Swift returning optional value
 
 
Q