Understanding `var status = (string: statusVal as NSString)` variable declaration in Swift - ios

I found the following code in a project that compiles and executes successfully. But I am unable to understand how it works. I tried Googling it using a variety of search phrases but couldn't find an explanation.
let statusVal = "Somestring"
var status = (string: statusVal as NSString)
Can someone clarify what is going on in the second line ?
According to what little knowledge I have in Swift , the second line should be something like
var status = NSString(string: statusVal as NSString)
which of course compiles as well.

While,it is just a tuple with one element
var status = (abcdefg:"abc")
The part abcdefg is description, and "abc" is value.
If a tuple has only one element,it used the type of the element.So the type of status is String
More document about tuple
https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html

What is really happening is var status = statusVal as NSString, the string: part is just giving the variable an association, which is ignored when the code is executed. You can put any word you want in place of string: and the code will still compile.

Related

How can I convert a string in a textfield to an Int in Swift?

I tried for a long time to turn the text into an Int but it did not work. I tried it like this:
(AnzahlString is a textfield)
var AnzahlAInt = 0
if let AnzahlAString = AnzahlString.text {
let AnzahlAInt = Int(AnzahlAString)
}
But then I always get the error:
Value of optional type 'Int?' must be unwrapped to a value of type 'Int'
Then I added a ! at the end of Int(AnzahlAString)! so I don't get a error, but now when I press on the button, the app crashes. It was predictable, but how can I change this now to an Int without the !?
At first glance, it looks like you have two things to check for:
is AnzahlString.text present, and
does it represent an Int
The first check is in fact not necessary, since .text will never return nil, even though it's marked as Optional. This means you can safely force-unwrap it.
The second check is easily done by using the ?? operator:
let AnzahlAInt = Int(AnzahlString.text!) ?? 0
PS, just as a stylistic hint: variable names in Swift ususally start with a lowercase letter, names starting with capital letters are used for types.
PPS: your code as written shadows AnzahlAInt - the value of your var is never changed.
The reason why the resulting Int is optional, is that parsing might or might not succeed. For example, if you try to parse the string "Fluffy Bunnies" into an Int, there is no reasonable Int that can be returned, therefore the result of parsing that string will be nil.
Furthermore, if you force the parser by using !, you're telling Swift that you know for sure that the string you pass will always result in a valid Int, and when it doesn't, the app crashes.
You need to handle the situation in which the parse result is nil. For example:
if let AnzahlAIntResult = Int(AnzahlAString) {
// We only get here if the parse was successful and we have an Int.
// AnzahlAIntResult is now an Int, so it can be assigned to AnzahlAInt.
AnzahlAInt = AnzahlAIntResult
}
You did a good job so far but missed out one thing.
This line tries to convert the String into an Int. However this can fail, since your String can be something like this "dfhuse".
let AnzahlAInt = Int(AnzahlAString)
This is why the result of Int(AnzahlAString) is an Optional (Int?). To use it as an real Int, you have to unwrap it.
First solution is the !, however, every time this does fail your app crashes. Not a good Idea to use so.
The best solution would be Optional Binding, as you already used to get the text of your text field.
if let AnzahlAString = AnzahlString.text {
if let safeInt = Int(AnzahlAString) {
// You can use safeInt as a real Int
} else {
print("Converting your String to an Int failed badly!")
}
}
Hope this helps you. Feel free to ask again if something is unclear.
For unwrapping you can also use guard like this
Simple and easy
guard let AnzahlAInt = Int(AnzahlString.text!) else {
return
}
print(AnzahlAInt)

Cannot convert value of type 'Unmanaged<AnyObject>?' to expected argument type 'AnyObject?' working with Keychain, Swift

Trying to insert some data in the Keychain. I have the following code:
func create(attributes: [String: AnyObject]) {
var rawResult: Unmanaged<AnyObject>?
let rawStatus = SecItemAdd(attributes, &rawResult)
let result: AnyObject? = rawResult?.takeRetainedValue()
}
This won't work... shows the error from the question title. Found a possible "solution" on a similar problem an user experienced on StackOverflow. They told him to remove Unmanaged<AnyObject>? and replace it with AnyObject?. The problem is that I need takeRetainedValue() method which is present in the Unmanaged class.

Intricate access to dictionary key

From a server I receive a JSON string, then I try to convert it to an NSDictionary this way:
let JSON = try NSJSONSerialization.JSONObjectWithData(rToData!, options:[])
guard let JSONDictionary:NSDictionary = (JSON as! NSDictionary) else {
print("My grandma is way more NSDictionary than this")
return
}
Once converted, I try to get some data contained in the dictionary: in particular I need an array I can access this way:
let myArray = JSONDictionary["data1"][0]["data2"];
XCode really doesn't like this idea, it puts an arrow under the first bracket and says Value of optional type "AnyObject?" not unwrapped, did you mean to use "!" or "?" ?. I follow its suggestion and I insert a "!", converting my preceding code to this:
let myArray = JSONDictionary["data1"]![0]["data2"];
At this point, the following line (where I count the number of elements in data2) shows an error, stating AnyObject has no member count.
The only thing that seems to work fine is this solution but, apart from being ugly and unreadable, I really don't understand it:
let myArray = (JSONDictionary["data1"]?[0]["data2"])!;
Can you help me understand why this basic access to a key in a dictionary must be so intricate?
I must say I like Swift but I spend a lot of time dealing with optionals and bizarre XCode alerts.
There is no guarantee that your JSON dictionary will contain a value for the key data1 (OK, you know it will, but Swift doesn't) so JSONDictionary["data1"] returns an optional. You need to unwrap the optional with ? or !
Also, since you have an NSDictionary, not a Swift dictionary, Swift doesn't know the type of the values, so they are AnyObject. Now again, you know it is an array, but Swift doesn't so you get an error stating that AnyObject doesn't have a count method.
While it is more verbose, it is cleaer for both the compiler and anyone else looking at your code if you split the line into multiple lines. It also lets you downcast the various objects so that Swift knows what is going on and handle any malformed JSON;
if let array1 = JSONDictionary["data1"] as? NSArray {
if let dictionary1 = array1[0] as? NSDictionary {
if let data2Array = dictionary1["data2"] as? NSArray {
let count=data2Array.count
}
}
}
You could implement appropriate else statements to handle errors
Optionals are one of Swift's most powerful features. They help avoid a whole family of bugs associated with uninitialised variables and special sentinnel values for boundary conditions. It is important that you learn how they can help you and not just throw ? or ! at your code until it compiles.

Cannot subscript a value of type anyobject

I've currently upgraded to the new Xcode 7, and the following code never had any errors with swift 1.2, but now its telling me that :
Cannot subscript a value of type any object
var imageArray : NSArray = []
let url = NSURL(string: (self.imageArray[indexPath.row][0] as? String)!)
I know its about [0] but how do i rewrite it to be accepted ?
OK, so first you are using an NSArray. You can drop that and make everything much easier.
In Swift always use strong typing where possible. Avoid Any and AnyObject when they are not needed. (They are VERY RARELY needed).
The error is happening because you're not telling the code what is actually in the imageArray.
Also, imageArray tells me the array is full of images. Name your variables more descriptively. imageUrlStringArray or arrayOfImageUrlArrays. Something more descriptive anyway.
Declare imageArray like...
var imageArray = [[String]]()
This tells the compiler that imageArray is a 2D array with Strings at the second level.
Now you can create your URL easily...
guard
let urlString = imageArray[indexPath.row].first,
let url = NSURL(string: urlString)
else { // Handle the inability to create a URL }
// Do something with the url

Cannot subscript a value of type [String: AnyObject]? with an index of type String

I know have many the same question but still cannot find the way to fix my error. Please see the image for more detail. I used Xcode 7 and swift 2.0
Edit: fcking the warning of Swift. finnaly (change?[NSKeyValueChangeNewKey]?.boolValue)! fixed the error
change is an optional. Either unwrap the optional
let isCaptureStillImage = change![NSKeyValueChangeNewKey]!.boolValue
or use optional bindings
if let changeNewKey = change?[NSKeyValueChangeNewKey] {
let isCaptureStillImage = changeNewKey.boolValue
...

Resources