array created with optional - ios

I am declaring a array:
var array:[String] = []
assigning values:
array.append(uniqueId as String)
and then pass it to a function:
static var levels_array : [String] = []
class func setLevelsArray(arr:[String])
{
GamePrefrences.levels_array = arr
println(GamePrefrences.levels_array)
}
My problem is that when i print the array i get:
[Optional(88868658), Optional(112051080), Optional(95274974)]
Why is that optional? i only want Strings in the array so why is "optional" added?
I come from Java can someone explain why optional is created and how to remove it

Very likely the actual strings are "Optional(88868658)", etc. You have probably created this strings from an optional accidentally. In the above code, you definitely have an array of strings, not an array of optionals, and when you print an array of strings, they don't include the double-quotes (which can be confusing).
It may is happening here:
array.append(uniqueId as String)
What type is uniqueId? as is not used to convert types. It's just used to cast them if possible (though this should really fail if that's the case; so I'm suspecting you're doing a string interpolation somewhere).

The Strings themselves are not optional -- the uniqueId is. Basically, optionals mean that a stored value may or may not exist.
I'd recommend using an if let statement to unwrap your optional uniqueID before converting it into a String so the program in fact knows that the optional exists before storing it as a String, ex:
if let uniqueId = uniqueId {
array.append(uniqueId as String)
}

Related

How do we append values to dictionary containing 3 elements in swift 2.3?

I am trying to append value to dictionary which I have declared like this.
var setHomIconDict:[(iconImg: UIImage, Operator: String, oprCode: String, oprMerchCode:String)]!
I am not sure its dictionary though. I am learning swift and I found a Intresting code on net. Anyway I am confused on how will I append values to this. I tried
setHomIconDict.append((iconImg:img!, Operator: "Strin", oprCode: "Hello", oprMerchCode: "Huja"))
But i get this error : fatal error: unexpectedly found nil while unwrapping an Optional value . here is the image
Can anyone suggest an appropriate way.
setHomIconDict is not Dictionary it is an Array of tuple and you are getting this crash because you haven't initialized the setHomIconDict object, you have just declared its type. So initialized it with its declaration.
var setHomIconDict:[(iconImg: UIImage, Operator: String, oprCode: String, oprMerchCode:String)] = []
Note: Instead of creating array of tuple better solution is to create one custom model Class with the property that you want to set/access, then create array of that custom Class objects and use it.
You are probably better off creating a struct to hold your values. Then your array would be an array of that struct.
struct homIcon {
var iconImg: UIImage
var Operator: String
var oprCode: String
var oprMerchCode:String
}
var setHomIconArray:[homIcon] = []
let newHomIcon = homIcon(iconImg: img!, Operator: "Strin", oprCode: "Hello", oprMerchCode: "Huja")
setHomIconArray.append(newHomIcon)
As Nirav says, the syntax you are using creates an array of tuples. If you want a dictionary get rid of the parentheses.
You want to define key/value pairs using this syntax:
var aDict = [key:value, key:value, key:value]
Then you can add new key/value pairs using:
aDict[newKey] = newValue
Is your goal to create and use a dictionary, or is it your goal to user and understand the structure that you found on the net?

Why print() is printing my String as an optional?

I have a dictionary and I want to use some of its values as a key for another dictionary:
let key: String = String(dictionary["anotherKey"])
here, dictionary["anotherKey"] is 42 but when I print key in the debugger I see the following:
(lldb) expression print(key)
Optional(42)
How is that possible? To my understanding, the String() constructor does not return an optional (and the compiler does not complain when I write let key: String instead of let key: String?). Can someone explain what's going on here?
As a sidenote, I am currently solving this using the description() method.
This is by design - it is how Swift's Dictionary is implemented:
Swift’s Dictionary type implements its key-value subscripting as a subscript that takes and returns an optional type. [...] The Dictionary type uses an optional subscript type to model the fact that not every key will have a value, and to give a way to delete a value for a key by assigning a nil value for that key. (link to documentation)
You can unwrap the result in an if let construct to get rid of optional, like this:
if let val = dictionary["anotherKey"] {
... // Here, val is not optional
}
If you are certain that the value is there, for example, because you put it into the dictionary a few steps before, you could force unwrapping with the ! operator as well:
let key: String = String(dictionary["anotherKey"]!)
You are misunderstanding the result. The String initializer does not return an optional. It returns the string representation of an optional. It is an non-optional String with value "Optional(42)".
A Swift dictionary always return an Optional.
dictionary["anotherKey"] gives Optional(42), so String(dictionary["anotherKey"]) gives "Optional(42)" exactly as expected (because the Optional type conforms to StringLiteralConvertible, so you get a String representation of the Optional).
You have to unwrap, with if let for example.
if let key = dictionary["anotherKey"] {
// use `key` here
}
This is when the compiler already knows the type of the dictionary value.
If not, for example if the type is AnyObject, you can use as? String:
if let key = dictionary["anotherKey"] as? String {
// use `key` here
}
or as an Int if the AnyObject is actually an Int:
if let key = dictionary["anotherKey"] as? Int {
// use `key` here
}
or use Int() to convert the string number into an integer:
if let stringKey = dictionary["anotherKey"], intKey = Int(stringKey) {
// use `intKey` here
}
You can also avoid force unwrapping by using default for the case that there is no such key in dictionary
var dictionary = ["anotherkey" : 42]
let key: String =
String(dictionary["anotherkey", default: 0])
print(key)

Mismatching types 'Int64' and '_' when trying to assign optional Int64 to a dictionary key

Question regarding Swift 2.1 in Xcode 7.
I have declared an optional variable like this:
var something: Int64?
I would like to later assign it to a dictionary key using a shorthand if, like this:
dictionary['something'] = (something != nil) ? something! : nil
XCode is giving me the following validation error:
Result values in '? :' expression have mismatching types: 'Int64' and
'_'
What is the issue here? Why can't optional Int64 be nil?
There are a number of problems here. First, Int64 isn't an AnyObject. None of the primitive number types are classes. They can be bridged to AnyObject using NSNumber, but you don't get that bridging automatically for Int64 (see MartinR's comment. I originally said this was because it was wrapped in an Optional, but it's actually because it's fixed-width).
Next, this syntax:
(something != nil) ? something! : nil
Is just a very complicated way to say something.
The tool you want is map so that you can take your optional and convert it to a NSNumber if it exists.
dictionary["something"] = something.map(NSNumber.init)
Of course, if at all possible, get rid of the AnyObject. That type is a huge pain and causes a lot of problems. If this were a [String: Int64] you could just:
dictionary["something"] = something
You can't add a Int64 to a dictionary of type [String : AnyObject], you need to wrap in in an NSNumber object. You can only store objects that conform to AnyObject in your dictionary.
var something: Int64?
something = 42
if let myVal: Int64 = something { // unwrap to make sure the value is there
let myNum = NSNumber(longLong: myVal) // create an NSNumber from your Int64
dictionary["something"] = myNum // insert it into the dictionary
}
As Anton Bronnikov said below, if your dictionary was type [String : Int64], you would be able to add your Int64 to it no problem.
It seems that others have already pointed out the issues with the types in your dictionary. I want to add that you can also use the nil coalescing operator '??' as even more concise shorthand for what you are doing in your example. It is most useful when you want to do a check for nil, (and if non-nil) unwrap the value and assign it, otherwise provide a default value.
var maybeSomething: Int?
var dictionary:[String:Int?] = [:]
dictionary["something"] = maybeSomething ?? nil
something! has type Int64. Not optional Int64, but Int64. nil has type nil. You can't have an expression
condition ? Int64 : nil
What would be the type of it?
And the whole thing is pointless. On the right hand side you would have just "something". If that doesn't work then your dictionary doesn't accept optionals.
PS. Noticed that your dictionary wants to store Objective-C objects. In that case, no way it accepts an optional. And it only accepts an Int64 after converting to NSNumber.

Optional Type 'String??' Not Unwrapped

"Value of optional type 'String??' not unwrapped; did you mean to use '!' or '?'?" -
I got this weird compiler error today, which was entirely confusing due to the two question marks after String.
I have a dictionary s, of type [String : String?], and a function which accepts all arguments as String?s. Specifically (from 5813's method of copying user-selected information into a dictionary), I have an elaborated version of the following:
func combine(firstname: String?, lastname: String?) {...}
var text = combine(s["kABPersonFirstNameProperty"], lastname: s["kABPersonLastNameProperty"])
I'm getting the error on the second line, and I'm wondering why it's so. If the values in s are of type String?, shouldn't that be accepted by combine(), since it's arguments are supposed to be of the same type? Why, then, would I get this error and how can I fix it?
Dictionary<T1, T2>[key] returns T2?. This is to return nil in case key doesn't exist.
So if T2 is String?, s[key] returns String??
You cannot pass String?? as String?
You can call like this to unwrap and prepare for non-existing key as well
var text = combine(s["kABPersonFirstNameProperty"] ?? nil, lastname: s["kABPersonLastNameProperty"] ?? nil)
By the way, code below will not set value to nil but remove the entire entry from the dictionary
s[key] = nil
If you want the value to be nil instead of removing entry, you will have to do this
s[key] = nil as String?
It is once optional because your dictionary value is optional. And it is optional again, because dictionary[key] returns optional. So you need to unwrap it twice.
Try this in a playground to understand the problem (and see possible solution):
let oos: String?? = "Hello"
print(oos)
if let os = oos { // Make String?
print(os)
if let s = os { // Make ordinary String
print(s)
}
}
Prints:
Optional(Optional("Hello"))
Optional("Hello")
Hello
But you could use other ways than if let to unwrap, too. For example:
print(oos! ?? "n/a")
Will force unwrap it once and then print either the inner String or n/a in case of nil...
Maybe the easiest solution would be to make the dictionary hold String instead of String?. Then you don't have the unwrapping problems which are described in other solutions.
Or do you really have to store String? types?
Do you want to differentiate between 'key exists but holds nil' and 'key does not exist'?

Swift: difference as String? vs. as? String [duplicate]

This question already has answers here:
Downcasting in Swift with as and as?
(3 answers)
Closed 8 years ago.
Is there a difference between as? String vs. as String? in Swift? If so, what's the difference and when should I use one vs. another?
There's a subtle but important difference:
variable as? String: variable can be any type, such as an array, an integer, etc. Cast to string if it's a string, set to nil otherwise.
variable as String?: variable is a String?, but stored in an opaque type, such as AnyObject?, or it's a non optional string. If it's something different, a runtime exception is generated.
Some examples:
var x: AnyObject? = "Test"
x as String? // OK, the result is an optional string
x as? String // OK, evaluates to an optional string
"string" as String? // OK, evaluates to optional string
x as? Int // OK, evaluates to nil, it's not an Int
x as Int? // Runtime exception, it's not castable to optional Int
So:
as? Type means: cast to this type, if possible, otherwise evaluate to nil
as Type? means: cast to an optional Type, because I know it's an optional Type. I understand that if it's not that, a runtime exception is generated
However, the real difference is between as? and as: the former is an attempt to cast, the latter is a forced cast, resulting in runtime error if not possible.
Update Dec 14, 2015 Since Swift 1.2, there are 3 variations of the as operator:
as? is an attempt to cast, evaluating to nil if cast fails
as! is a forced cast, resulting to an runtime exception if cast fails (this is what as previously did)
as is now a special type of cast to be used when casting to equivalent types, usually bridged types, such as Swift's String and NSString.
From The Swift Programming Language book,
as is a type cast operator which we use to downcast to the subclass and as? is used for an optional form, when we are not sure if the downcast will succeed. Consider the following example
for item in library {
if let movie = item as? Movie {
println("Movie: '(movie.name)', dir. (movie.director)")
} else if let song = item as? Song {
println("Song: '(song.name)', by (song.artist)")
}
}
The example starts by trying to downcast the current item as a Movie. Because item is a MediaItem instance, it’s possible that it might be a Movie; equally, it’s also possible that it might be a Song, or even just a base MediaItem.
String? An optional value either contains a value or contains nil to indicate that the value is missing.
From this,
as? String means when you don't know what you're downcasting, you are assuming that as a String, but it might me Integer or Float or Array or Dictionary
as String? means it's an Optional Value, it may either contain a String or Nil value.
Yes there is a difference.
In the first case, you are doing an optional cast to the type String. This will return a value if the object you are attempting to cast is indeed a String or nil if it is not.
In the second case, you are doing a forced cast to the type String?. If the value you are casting is not a string, it will crash your program.
YES, there is diffrence.
variable as String? downcast to optional String.If variable is not String? it will cause run-time exception.
while variable as? String will return nil if your variable is not String type or return downcast variable to String. This is conditional downcasting, if you not sure about down-casting you need to use this .

Resources