How to prevent iOS app from crashing due to empty textfields? - ios

I need to figure out a solution to prevent the app from crashing when a value is not entered in a textfield. The idea is if the textfield is empty (nil), the value of that textfield will then equal zero. Below I have copied my code:
let taxPercentDou:Double = Double(taxnosign2!)!
Anyone has any suggestions?

You need to stop force unwrapping optionals with the exclamation ! sign:
let b:Double = Double(rent.text!)!// Rent
If rent.text is nil or contains non-numeric text, your app will crash.
You can check for nil and replace it with "0" using the null coalescing operator:
rent.text ?? "0"
You can pass that into the Double initializer like this:
Double(rent.text ?? "0")
However, this will return nil if rent.text contains non-numeric text. You can use the null coalescing operator again to handle this:
let b: Double = Double(rent.text ?? "0") ?? 0.0
You could take this one step farther and write a simple utility method to make it easier to use for all your fields:
func convertToDouble(text: String?) -> Double {
return Double(text ?? "0") ?? 0.0
}
And call it like this:
let b = convertToDouble(rent.text)

Please find the below code. It Might Help you.
static func isNull(aString: AnyObject?) -> Bool
{
//Check for null
if(aString is NSNull){
return true
}
if(aString == nil){
return true
}
let x: AnyObject? = aString
//if string is nsnumber , convert it into string and check
if(aString is NSNumber){
var aString1 : String? = ""
aString1 = String(describing: aString)
return self.isStringEmpty(aString: aString1!)
}
if let aString1 = x as? String
{
return self.isStringEmpty(aString: aString1)
}
else
{
return true
}
}

Related

Using an if condition for a variable? in Swift 5

I am not sure how to call this scenario. Say i have this variable
let text: String?
How can it be coded such that my if condition would be something like this:
if (text == nil || Float(text) > 0) {
print("i am in")
}
I keep getting No exact matches in call to initializer
You have two issues here:
text is a String? and therefore it needs to be unwrapped to pass it to Float()
Float() returns an optional, this also should be unwrapped to be used with the > operator.
I would avoid force unwrapping, you can do something like:
let text: String? = nil
if let textString = text, let number = Float(textString) {
if number > 0 {
print("I am in")
}
else {
print("I am out")
}
}
else {
print("I am in")
}
First of all, looks like you want to check if text != nil then if text is number check if text > 0
Because in here you have optional String so you should have a specific to check if string text not nil. Then check if it is number.
Code will be like this
extension String {
var isNumber: Bool {
return Double(self) != nil
}
}
Then combine to your condition
if text == nil || (text!.isNumber && Float(text!)! > 0) {
print("i am in")
}
The result will be like this
let text: String? = "2.0" // i am in
let text: String? = nil // i am in
let text: String? = "-1.0" // nothing print
text is an optional
if (text == nil) || Float(text ?? "") ?? 0 > 0 {
print("i am in")
}
Two additional things must be done:
After your check if text is nil you must still unwrap the optional text to use it with the Float() constructor. Here I’ve used a forced unwrap ! which in general is dangerous, but we know at this point text cannot be nil due to the first test. If text is nil, the || uses short-circuit evaluation to return true without executing the right side.
Next, Float(text!) returns a Float? because that text might not convert to a valid Float. In order to unwrap that I’ve used the nil-coalescing operator ?? to unwrap the Float value or use 0 if the value is nil.
if text == nil || Float(text!) ?? 0 > 0 {
print("i am in")
}

value?.min != nil ? value!.min : nil not force unwrapping writing Optional(some number)

func myFunc(array:[Int]) -> (min: Int, max: Int)?
{
if array.isEmpty {return nil}
var minNumber = array[0]
var maxNumber = array[0]
for number in array {
if number < minNumber {
minNumber = number
}
else if number > maxNumber{
maxNumber = number
}
}
return (minNumber, maxNumber)
}
let tempArray:[Int] = [1,2,3,4,5,6,7]
let value = myFunc(array: tempArray)
print("The minima is: \(value?.min != nil ? value!.min : nil) the maxima is \(value?.max != nil ? value!.max : nil)")
In the given code I just wanted to make if for example, the code contains some value it will force unwrap but if it is not contained it will just print "nil". But in my code, if it contains number it will print Optional(some number).
value?.min != nil ? value!.min : nil
is a (conditional) expression and evaluates to some value which has a type.
The first expression value!.min has the type Int, but the second expression nil is an optional and has the type Int?. Therefore the type of the conditional expression becomes Int? and that is printed as "Optional(1)".
What you want is the string "nil", or the non-nil value as a string:
print("The minimum is: \(value?.min != nil ? "\(value!.min)" : "nil")")
(and similarly for the maximum). Now both expression in the conditional expression
value?.min != nil ? "\(value!.min)" : "nil")
are strings, and the result is a string as well. This can be abbreviated to
print("The minimum is: \(value.map {"\($0.min)"} ?? "nil")")
If you need this frequently then you can define an extension method on the optional type
extension Optional {
var descriptionOrNil: String {
switch self {
case .some(let wrapped): return "\(wrapped)"
case .none: return "nil"
}
}
}
and use it as
print("The minimum is: \((value?.min).descriptionOrNil)")
So if i don't understand the question wrong. You can do:
extension Optional where Wrapped == Int {
var valueOrEmpty: String {
guard let unwrapped = self else {
return "nil"
}
return "\(unwrapped)"
}
}
print("The minima is: \(value?.min.valueOrEmpty) the maxima is \(value?.max.valueOrEmpty)")
Right?

Unwrapping Optional String To Int & Making it non-optional

It has been a long time since I have coded in iOS and I am upgrading the old app to swift 3. I am really struggling with one issue of using optional variables.
I have a textfield which is optional. I want it unwrapped into a non-optional Int so that I can use it in the other functions for calculation.
#IBOutlet weak var txtRuns: UITextField!
func sendScore()
{
let runs = txtRuns.text!
let overs = txtOvers.text!
let balls = txtBalls.text!
let wkts = txtWkts.text!
let target = txtTarget.text!
let totalOvers = txtTotalOvers.text!
let strData = "S|R\(runs)" + getOptionalScoreData(
runs: Int(runs),
wkts: Int(wkts),
overs: Int(overs),
balls: Int(balls),
target: Int(target),
totalOvers: Int(totalOvers)
)
}
func getOptionalScoreData(runs: Int, wkts: Int, overs: Int, balls: Int, target: Int, totalOvers: Int) -> String
{
if ( runs == 0 ) {
return getCurrentRunRate(runs: runs)
}
return "";
}
As you can see, I have so many functions to call and I want this textfield to turn into non-optional INT.
Now I have tried several options that I read over here but the error messages only change. The problem didn't solve.
Current ERROR is
The value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'?
Please help.
Thanks
.................
Please note that I don't think nested check is a nice idea here because all these variables are independent of each other. One can be nil but other can be still passed and used.
If I nest checks like this, it means that no other value will be passed if runs are nil.
if let runs = txtRuns.text, let runsInInt = Int(runs) {
if let overs = txtOvers.text, let oversInInt = Int(overs) {
if let wkts = txtWkts.text, let wktsInInt = Int(wkts) {
strData = "S|R\(runs)\(overs)\(wkts)" + getOptionalScoreData( runs: runsInInt, overs: oversInInt, wkts: wktsInInt)
}
If you are frequently getting value from UITextField as Int, you can add an extension as follows:
extension UITextField {
var intValue: Int {
get {
if let text = self.text {
return Int(text) ?? 0
}
return 0
}
set {
self.text = String(newValue)
}
}
}
You can add the above as private extension in your viewcontroller too. Now you can rewrite your code as:
func sendScore() {
let strData = "S|R\(txtRuns.intValue)\(overs.intValue)\(wkts.intValue)" + getOptionalScoreData(
runs: txtRuns.intValue,
wkts: wkts.intValue,
overs: overs.intValue,
balls: balls.intValue,
target: target.intValue,
totalOvers: totalOvers.intValue)
)
}
Int(runs) call constructor of Int following:
public init?(_ text: String, radix: Int = default)
Because String to Int might failed due to the String might not a valid integer.
How would you deal with it?
You can reference Sallu's comment.
user ! to guarantee the String in UITextField is absolute a valid integer, or app crash.
runs: Int(runs)!
user ?? to give a default value if the String in UITextField is not a valid integer.
runs: Int(runs) ?? 0
In the case the default value is 0

Closure argument becomes nil

I have a weird issue trying to validate user input. I'm using a wrapper for a form framework and I want it to be able to validate user input.
The trouble is, when I call the closure with the userValue argument, it ends up being nil and all checks return false:
class FormRowWrap {
var tag: String
var row: AnyObject
var verification: (value: Any?) -> Bool
init(tag: String, row:AnyObject, verification:(Any?) -> Bool) {
self.tag = tag
self.row = row
self.verification = verification
}
}
class InsertViewController: FormViewController {
let rows = [
{
let tag = "Fuel Name"
let row = FormRowWrap(tag: tag,
row:TextRow(tag) {
$0.title = tag
// $0.value = last known user default
},
verification:({(value: Any?) -> Bool in
if let thing = value as? String {
//^----- the value in a **breakpoint here is nil**
//
if !thing.isEmpty {
return true
}
}
return false
}))
return row
}() as FormRowWrap,
{
let tag = "Price"
let row = FormRowWrap(tag: tag,
...
func formValuesAreValid(values: [String: Any?]) -> Bool {
var result = false
for rowWrap in self.rows {
let userValue = values[rowWrap.tag]
print("userValue \(userValue) forTag: \(values[rowWrap.tag])")
// ^---- this prints userValue **Optional(Optional("Ghh")) forTag: Optional(Optional("Ghh"))**
let entryIsValid = rowWrap.verification(value: userValue)
if (!entryIsValid) {
result = false
return result
}
}
result = true
return result
}
If I run rowWrap.verification(value:"test") it returns true, so I think it's an issue about properly unwrapping values.
Your function needs an Optional but userValue is an Optional inside another Optional:
Optional(Optional("Ghh"))
So when you force unwrap it with
let entryIsValid = rowWrap.verification(value: userValue!)
what happens actually is that you unwrap the first layer and get back an Optional:
Optional("Ghh")
which is what your function signature
(value: Any?) -> Bool
needs.
About why it's wrapped twice:
with
formValuesAreValid(values: [String: Any?])
the values in the values dictionary are Optionals, and then when you access the dictionary:
let userValue = values[rowWrap.tag]
you get yet another Optional - because accessing a dictionary always returns an Optional, so in this case values[rowWrap.tag] returns an "Optional Optional".
Then somewhere else you unwrap once thinking you'll get the value if let thing = value as? String but you get the inner Optional instead and your next check fails.
Found a way to make it work by force unwrapping the "userValue":
let entryIsValid = rowWrap.verification(value: userValue!)
I still don't understand why this works and why it doesn't work with the argument as wrapped optional.

How to extend the Swift Dictionary type to return a non-empty String or nil

I'm writing an extension to Dictionary so that when I give it a String key, it'll return me a String only if the value associated with the key is non-nil and not empty.
extension Dictionary {
subscript(key: String) -> String? {
if let string = super.subscript(key) {
if string.isEmpty == false {
return string
}
}
return nil
}
}
However, at the if let string = super.subscript(key) { line, I get the following compile error and I don't know what it means--neither is there a Google result that explains it:
Expected -> for subscript element type
I am doing this because I'm working with an API that returns a JSON where a key's value may be an empty string--which is an invalid value to the app by our requirements, and hence, as good as nil.
Of course the longer way works, but I'm looking for a way to make this shorter.
if let value = dict["key"] as? String {
if value.isEmpty == false {
// The value is non-nil and non-empty.
}
}
You're going to think this is very silly, but my suggestion would be: do more or less exactly what you're doing, but encapsulate it as a separate function rather than trying to deal with the implications of defining a new subscript:
extension Dictionary {
func nes(key:Key) -> String? {
var result : String? = nil
if let s = self[key] as? String {
if !s.isEmpty {
result = s
}
}
return result
}
}
(nes stands for "non-empty string".)
Now call it like d.nes("foo").

Resources