What is an optional variable? - ios

I have the following code to work out if a number is prime;
#IBAction func isPrimeBtn(sender: AnyObject) {
if(isPrimeTxt.text.isEmpty){
isPrimeResultLbl.text = "Please Enter A Value";
}else{
var value = isPrimeTxt.text.toInt();
println(value);
if(value == 0){
println("value was 0");
isPrimeResultLbl.text = "Its Not";
}else{
for(var i = 3; i * i < value; i += 2){
println("value was 0");
if(value! % i == 0){
isPrimeResultLbl.text = "Its Not";
}
}
isPrimeResultLbl.text = "Its Prime!!";
}
}
}
When i print the value using println(value) I get Optional 22, if I check the variable is 0 it is true.
What am I doing incorrectly?
Thanks

There's a few problems here. Firstly, you correctly use value! in your modulus test, but in the first test and in the for loop you use value. I suggest you use an if let block instead, so value is not an optional ever:
if let value = isPrimeTxt.text.toInt() {
// now you know it's an integer
// ... do your test
} else {
// some error message
}
However, even if you do this, your logic is wrong on three counts:
1) isPrimeResultLbl.text = "Its Prime!!" is always executed after your for loop
2) it's incorrect for everything less than 10 because your for (var i = 3; i * i < value; i += 2) { will never execute if 3 * 3 >= value.
3) you need to start checking divisors at 2, not 3. 16 will appear prime using your algorithm (though 4 & 8 won't, as they're under 9!)

What happens if prime.text is "abc"? What happens is that the conversion toInt() will fail. Because it can fail, toInt() doesn't return an integer, it returns an optional integer. The result is either an integer or nothing. When you call println, you don't print an integer, you print an optional integer. And that's what println prints - it says "optional 22". It might have said something like "empty".
If you print value! instead of value, you tell Swift that you are 100% sure that the optional integer value is actually there. If it isn't, the expression value! will crash. If it is there, println will print 22. So the exclamation mark turns an optional either into a proper value, or into a crash.

Related

Passing substring value of gridview to textbox

Please suggest me any idea to pass sub string value of grid view in text box.
frm.txtcustcode.text = dg.cells["custcode"].value.ToString().Trim();
I need to pass (0000001234) "01234" to txtcustcode.Text;
Below code might work fine:
frm.txtcustcode.Text= dg.Cells["CustomerCode"].Value.ToString().Trim().Substring(5,5);
I hope I understand your question correctly.
The code :
dg.cells["custcode"].value.ToString().Trim();
is a value in a grid and the value you get by using the code is : 0000001234
You would like to display this value in a textbox on the form as a value : 01234
If this is the case you could do the following:
//If the value of custcode always starts with 0's but wont contain 0's in the number.
String sCustCode = "0000001234";
sCustCode = sCustCode.Replace("0", "");
sCustCode = "0" + sCustCode;
MessageBox.Show(sCustCode); //Displays 01234
//Or if your CustCode can contain a 0 and always starts with 0's.
sCustCode = "0000001234";
int num = Int32.Parse(sCustCode); //Depending on the number format use the correct cast.
sCustCode = "0" + num.ToString();
MessageBox.Show(sCustCode); //Displays 01234
//Or you dont want to use a Cast to get your code in the fear of dataloss for some reason.
sCustCode = "0000001234";
int index = 0;
int position = 0;
foreach(char myChar in sCustCode)
{
if (myChar != '0')
{
position = index;
break;
}
index++;
}
if (position == 0)
{
//No starting 0 found
}
else
{
sCustCode = sCustCode.Substring(position - 1, sCustCode.Length - position +1);
}
MessageBox.Show(sCustCode); //Displays 01234
I am sure there are better ways of doing this, it depends on the purpose.
Hope this can help you in the correct direction.

Swift: Combine condition and if-let with logical or

I am trying to do something that would logically look like this:
if text == "" || let i = Int(text) where i < 2 {
// do something; don't care about the value of i
}
Of course this isn't a valid condition -- what would the value of i be if text == "" is the part that holds? But, since I'm only interested in the value of i inside the where clause, I was hoping there is a nice way of achieving the same effect, namely executing the same closure if either condition holds. My current solution is to extract the closure and call it from two separate if blocks, but that's pretty hairy-looking.
The equivalent to your code example would be:
if text == "" || Int(text) ?? 2 < 2 {
print("valid")
// do your previous "something
} else {
print("invalid")
}
which yields
"" -> valid
"1" -> valid
"2" -> invalid
"abc" -> invalid
If you're doing this kind of comparison regularly, you could create your own operator in order to compare an optional with a given closure representing your condition for success. If the unwrapped value meets the condition, it'll return true – else false.
For example:
infix operator ?& {precedence 130 }
func ?&<T>(lhs: T?, #noescape rhs:(T)->Bool) -> Bool {
return lhs != nil ? rhs(lhs!) : false
}
...
if text == "" || Int(text) ?& {$0 < 2} {
print("valid")
} else {
print("invalid")
}
You could also overload the existing < operator to do this, but this may impact already existing code that relies on nil being less than a non-optional value.
func <<T:Comparable>(lhs: T?, rhs:T) -> Bool {
return lhs != nil ? (lhs! < rhs) : false
}
...
if text == "" || Int(text) < 2 {
print("valid")
} else {
print("invalid")
}
Perhaps a more "Swifty" way to handle optional values is with map. Essentially, mapping an optional value gives you an unwrapped value in your closure, which you can then modify to return what you need. Outside the closure, you will receive either the modified value, or nil if the original optional was nil.
let optInt: Int? = 1 // or nil
let incremented: Int? = optInt.map { $0 + 1 }
// If optInt isn't nil, its incremented value is returned by map.
// If it is nil, map just returns nil.
So to solve my problem, I could do:
if text == "" || Int(text).map({$0 < 2}) ?? false {
// If text has an Int value, the map closure will return
// whether that value is less than 2.
// Else, map will return nil, which we coalesce to false.
}

Multidimensional Array Unwrapping an Optional

so I'm having this problem where I can't unwrap an optional for outputting it into the label, I've even tried just printing it in the console and it still gives me an optional
The code and array are in different files.
Code It's in a VC:
for var i = 0; i < stateName.count; i++ {
if tax.state == stateName[i][0] {
stateName[i][1] = Double(taxNumb.text!)!
print(stateName[i][1])
output.text = String(stateName[i][1])
}
}
Array Code I made this in an empty swift file:
var tax : Taxes? = nil
var stateName = [
["AK - Alaska", tax?.alaska!],
["AL - Alabama", tax?.alabama!],
["AR - Arkansas", tax?.arkansas!],
["AZ - Arizona", tax?.arizona!],
["CA - California", tax?.california!]
]
As I wrote in my comment to your previous question use the "Nil Coalescing" ?? operator:
output.text = String(stateName[i][1] ?? "not set")
Or using the alternate swift String magic
output.text = "\(stateName[i][1] ?? "not set")"
The operator returns the first value if it not nil, otherwise it returns the second value.

Unwrapping Optional Int in Swift

The API response I am working with returns a total amount. It supports multiple different currencies, so sometimes the currency symbol will be at the front (ex. $20.00) or at the end (ex. 20.00€). I am doing a check to see if the first char of the value is an int. In this specific case, the value "20.00€" is being returned. firstChar is "2" :
DOES NOT WORK:
let firstNumOpt: Int? = String(firstChar).toInt()
if let num = firstNumOpt { //20.00€
NSLog("Total: \(total)")
}
WORKS:
if let num = String(firstChar).toInt() { //20.00€
NSLog("Total: \(total)")
}
Can someone explain why the first code block does not work? Both ways seem identical to me.
Some debug info:
(lldb) po firstNumOpt
2
{
value = 2
}
(lldb) po num
411432864
Note: This isn't really an answer, but I needed to post code to describe what was working.
I'm not sure that your error is in the code that you've posted. Here is some code that I just ran in an empty playground:
func test(str: String) {
let firstNumOpt: Int? = String(str[str.startIndex]).toInt()
if let anum = firstNumOpt {
print("First worked on \(str)")
}
if let bnum = String(str[str.startIndex]).toInt() {
print("Second worked on \(str)")
}
}
test("20.00€") // prints "First worked on 20.00€" and "Second worked on 20.00€"
test("$20.00") // doesn't print anything

Swift calculate value of UITextFields and return value

Using swift and Xcode 6, I'm trying to return a value calculated based on content of few UITextFields.
I have declared variables
var Number1 = Field1.text.toInt()
var Number2 = Field2.text.toInt()
var Duration = Number1*Number2
Mylabel.text = String ("\(Duration)")
The idea is to capture duration from few UI Fields and based on calculation of those values assign that to a variable as well as display it on a label.
In line: var Duration = Number1*Number2
Challenge is that I have is that when performing multiplication Xcode highlight error: Value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'?
The toInt() method returns an optional value because the string it is trying to convert may not contain a proper value. For instance, these strings will be converted to nil: "house", "3.7","" (empty string).
Because the values may be nil, toInt() returns an optional Int which is the type Int?. You can't use that value without unwrapping it first. That is why you are getting the error message. Here are two safe ways to handle this:
You need to decide what you want to do when a value can't be converted. If you just want to use 0 in that case, then use the nil coalescing operator (??) like so:
let number1 = field1.text.toInt() ?? 0
// number1 now has the unwrapped Int from field1 or 0 if it couldn't be converted
let number2 = field2.text.toInt() ?? 0
// number2 now has the unwrapped Int from field2 or 0 if it couldn't be converted
let duration = number1 * number2
mylabel.text = "\(duration)"
If you want your program to do nothing unless both fields have valid values:
if let number1 = field1.text.toInt() {
// if we get here, number1 contains the valid unwrapped Int from field1
if let number2 = field2.text.toInt() {
// if we get here, number2 contains the valid unwrapped Int from field2
let duration = number1 * number2
mylabel.text = "\(duration)"
}
}
So, what did the error message mean when it said did you mean to use a !. You can unwrap an optional value by adding a ! to the end, but you must be absolutely sure the value is not nil first or your app will crash. So you could also do it this way:
if number1 != nil && number2 != nil {
let duration = number1! * number2!
mylabel.text = "\(duration)"
}
Get the value of textFields in var, multiply them, and then set the value of label. Try this:
var Number1 = Field1.text.toInt()
var Number2 = Field2.text.toInt()
var Duration = Number1 * Number2
Mylabel.text = NSString(format:"%d",Duration!)as String;
Hope this helps.. :)

Resources