Multidimensional Array Unwrapping an Optional - ios

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.

Related

How can I get String from Any in swift3

Such as I get a dic from fetchData:
(lldb) po dic
▿ 3 elements
▿ 0 : 2 elements
- .0 : "total"
- .1 : 0.00
▿ 1 : 2 elements
- .0 : "year"
- .1 : 2016
▿ 2 : 2 elements
- .0 : "month"
- .1 : 12
(lldb) po dic["year"]
▿ Optional<Any>
(lldb) po dic["year"]!
2016
Is there a function to get String form Any?
The function's usage is like below:
let total = UtilSwift.getStrFromAny(dic["total"] as Any )
In objective-c, I written a method:
+ (NSString*)getStringWithoutNull:(id)value
{
NSString *strValue = #"";
if(value != nil){
strValue = [NSString stringWithFormat:#"%#", value];
}
if([strValue isEqualToString:#"null"])
{
return #"";
}
if ([strValue isEqual:[NSNull null]]) {
return #"";
}
return strValue;
}
Is in swift could write a method like this to get String form Any?
The Any maybe Int, String, "", Double, or other type.
EDIT - 1
After the tried in Playground. :
import UIKit
let dict:[String:Any] = ["aa": 123, "year":1994, "month":"12"]
let string = String(describing:dict["year"]) ?? "" // Try to turn result into a String, o
print(string) // If I print(string!), and there will report error.
The warning:
EDIT 2
I know the edit -2 maybe paint the lily, but if when use the func below, when I deliver a Opitional value to the func, the return String will be Opitinal too, how to avoid that?
This below is my test in Playground, dic["b"] as Any convert the parameter to Opitional:
let dic:[String:Any] = [ // ["b": 12, "A": "A"]
"A":"A",
"b":12
]
func stringFromAny(_ value:Any?) -> String {
if let nonNil = value, !(nonNil is NSNull) {
return String(describing: nonNil) // "Optional(12)"
}
return ""
}
let str = stringFromAny(dic["b"] as Any) // "Optional(12)"
Try this one:
func stringFromAny(_ value:Any?) -> String {
if let nonNil = value, !(nonNil is NSNull) {
return String(describing: nonNil)
}
return ""
}
Update:
If the calling code invokes the above function with an Any? parameter that is explicitly cast to Any (a strange scenario which the Swift 3 compiler allows), then it will consider the final type of the parameter to be a non-optional optional, i.e. an Any value where the type Any represents is Any?. Or, in other terms, the value would be considered to be Optional<Any>.some(value:Any?).
In this case, the if let to unwrap the "some" case returns an optional value as the result in the function implementation. Which means that the final string description will include the "Optional" designation.
Because of the various oddities around the fact that the Swift 3 compiler will happily cast between Any and Any? and consider a value of type Any to be a value of type Any? and vice versa, it's actually pretty complicated to detect if an Any really contains an `Any?' or not, and to unwrap accordingly.
A version of this same function, along with some necessary additional extensions is provided below. This version will recursively flatten an Any value containing any number of nested Any? cases inside to retrieve the innermost non-optional value.
While this is what you seem to be looking for, I am of the opinion that it's a lot of hassle to work around something a programmer should not be doing anyway, namely miscasting a known Any? value to be Any because the compiler has a weird exception for that, even when it is not actually true.
Here's the "developer-proof" version of the code:
protocol OptionalType {
var unsafelyUnwrapped: Any { get }
var unsafelyFlattened: Any { get }
}
extension Optional: OptionalType {
var unsafelyUnwrapped: Any { return self.unsafelyUnwrapped }
var unsafelyFlattened: Any { return (self.unsafelyUnwrapped as? OptionalType)?.unsafelyFlattened ?? self.unsafelyUnwrapped }
}
func stringFromAny(_ value:Any?) -> String {
switch value {
case .some(let wrapped):
if let notNil = wrapped as? OptionalType, !(notNil.unsafelyFlattened is NSNull) {
return String(describing: notNil.unsafelyFlattened)
} else if !(wrapped is OptionalType) {
return String(describing: wrapped)
}
return ""
case .none :
return ""
}
}
Use ! if the value is an optional
String(describing: nonNil) // "Optional(12)"
String(describing: nonNil!) // "12"

how to make retrieve button for previous Value

can someone help me
i make button to retrieve previous Values
but i have two TextFiled
i must write in two TextFiled for work retrieve button
i do not want this happens
i want when I write in the first TextFiled, retrieve button work without any problem
but if i write in first TextFiled and second TextFiled at the same time i want retrieve button work without any problem
var previousValues: [String] = [String]();
var previousValues1: [String] = [String]();
previousValues.append(TextFailde.text ?? "error");
previousValues1.append(TextFilde1.text ?? "error");
if self.previousValues.count > 0 {
let previousValue = self.previousValues.removeLast()
let subtracted = (Int(self.lblZeroUs.text!)!) - (Int(previousValue)!)
self.lblZeroUs.text = "\(subtracted)"
}
else if self.previousValues1.count > 0 {
let previousValue = self.previousValues1.removeLast()
let subtracted2 = (Int(self.lblZeroThey.text!)!) - (Int(previousValue)!)
self.lblZeroThey.text = "\(subtracted2)"
}
and here the error
There are many errors, first of all you dont declare your properties with the first letter in uppercase, it's considered a bad practice.
Then, when you involve your properties in mathematical operations what do you need is to assign them a start value, especially if your code try to convert strings.
In Swift, you don’t need to write semicolons at the end of every statement.
I dont know the rest of your code, but your lines crash because you attempt to run mathematical operations using properties have nil as value.
This below it's just an example to avoid the first crashing for nil:
textFailde.text = "0"
textFilde1.text = "0"
previousValues.append(textFailde.text ?? String(0))
previousValues1.append(textFilde1.text ?? String(0))
self.lblZeroUs.text = String(0)
self.lblZeroThey.text = String(0)
if self.previousValues.count > 0 {
let subtracted = (Int(self.lblZeroUs.text!)!) - (Int(self.previousValues.last!))!
self.previousValues.removeLast()
self.lblZeroUs.text = "\(subtracted)"
}
else if self.previousValues1.count > 0 {
let subtracted2 = (Int(self.lblZeroThey.text!)!) - (Int(self.previousValues1.last!))!
self.previousValues1.removeLast()
self.lblZeroThey.text = "\(subtracted2)"
}
previousValues.append(TextFailde.text ?? "error");
previousValues.append(TextFilde1.text ?? "error");
You added to the same array twice, try changing the code to
previousValues.append(TextFailde.text ?? "error");
previousValues1.append(TextFilde1.text ?? "error");

If let condition true when value is missing in optional type, swift

I have parser in Objc, parser returns NSDictionary. I am using this parser in swift class. But when some value is missing on that dictionary, it shows nil value. e.g. ->
wirlessData = {
"anon" = {
};
"channel" = {
"text" = 1;
};
}
I am checking through
if let wepauthValue = wirlessData["wepauth"] {
if let value = wepauthValue["text"] {
print("\(value)") // nil
}
}
I don't how it satisfy the if let condition. Any one faced this types of problem can help me out.
Thanks,
vikash
You don't need any special code to do this, because it is what a dictionary already does. When you fetch dict[key] you know whether the dictionary contains the key, because the Optional that you get back is not nil (and it contains the value).
So, if you just want to answer the question whether the dictionary contains the key, ask:
let keyExists = dict[key] != nil
If you want the value and you know the dictionary contains the key, say:
let val = dict[key]!
But if, as usually happens, you don't know it contains the key - you want to fetch it and use it, but only if it exists - then use something like if let:
if let val = dict[key] {
// now val is not nil and the Optional has been unwrapped, so use it
}
I have tested it and found that value is still optional.Take a look at screenshot below to understand it better.
"anon" would be an empty dictionary. An empty dictionary is not nil, it is a dictionary. Just an empty one. A JSON parser will never, ever give nil values unless you ask for a key that is not in a dictionary. For example wirlessData ["nonexistingkey"] would give you nil.
If you be more type-strong about it with the if..let's then:
if let anonValue = wirlessData["anon"] {
if let value = anonValue["text"] as? String {
// This won't execute if value isn't converted from `anonvalue["text"]` to String specifically. This includes null been a false match too
print("\(value)") // nil
}else{
print("Value did't match string at all")
}
}
or even more specifically in your case:
if let anonValue = wirlessData["anon"] {
if let value = anonValue["text"] as? Int {
// This won't execute if value isn't converted from `anonvalue["text"]` to String specifically. This includes null been a false match too
print("\(value)") // nil
}else{
print("Value did't match int at all")
}
}
The value your parser is returning not nil, its empty so you need to check on count if inner data type is dictionary or array, I have past 1 sample here
Please use below code and correct your logic accordingly to get it work properly
let wirlessData:[String:AnyObject] = [
"anon" : [],
"channel" : [
"text" : 1
]
]
if wirlessData["anon"]?.count > 0 {
if let value = wirlessData["anon"]!["text"] {
print("\(value)") // nil
}
}
Try this below code using type check operator (is) -
if wirlessData["anon"] is [String:AnyObject]
{
let anon = wirlessData["anon"]!
print(anon)
if anon["random"] is String {
let stringValue = anon["random"]!
print("\(stringValue)")
}
else if anon["random"] is Int
{
let intValue = anon["random"]!
print("\(intValue)") // nil
}
else
{
print(" may be value did't match string & Int or nil ")
}
}

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