In Xcode8 beta6, the following code will cause a warning: 'is' test is always true. But it won't print pass.
struct TestStruct {
}
//warning: 'is' test is always true
if TestStruct() is AnyObject {
print("pass")
}
And the following code will cause a warning: Conditional cast from 'T' to 'AnyObject' always succeeds
public static func register<T>(_ protocolType: T.Type, observer: T) {
//Warning: Conditional cast from 'T' to 'AnyObject' always succeeds
guard let object = observer as? AnyObject else {
fatalError("expecting reference type but found value type: \(observer)")
}
//...
}
The warning works as intended: the false return of TestStruct() is AnyObject, however, does not
The prior version of this answer perceived the warning,
'is' test is always true
as the bug, and contained some discussion as to why this perceived buggy warning would manifest itself. That TestStruct() is AnyObject evaluated to false at runtime, however, was perceived as expected behaviour.
Given the comments to the bug report filed by the OP (SR-2420), it seems the situation is the reverse: since Xcode 8/beta 6, the is test should always evaluate to true, and the bug the OP:s post is the fact that TestStruct() is AnyObject evaluates to false during runtime.
Joe Groff writes:
This is correct, because everything bridges to AnyObject now.
...
is/as AnyObject always succeed for all types now. It's behaving
as intended.
The new SwiftValue box for conversion from Swift values to Obj-C objects
(for additional details, see discussion in the comments below, thanks #MartinR)
It seems as if Swift values that are not explicitly implemented to be bridgeable to Obj-C objects via e.g. conformance to _ObjectiveCBridgeable (see e.g. the following Q&A for details regarding _ObjectiveCBridgeable), will instead automatically make use of the new SwiftValue box to allow conversion to Obj-C objects.
The initial commit message for swift/stdlib/public/runtime/SwiftValue.mm reads:
Runtime: Implement an opaque 'SwiftValue' ObjC class to hold bridged values
If there's no better mapping for a Swift value into an Objective-C
object for bridging purposes, we can fall back to boxing the value in
a class. This class doesn't have any public interface beyond being
NSObject-conforming in Objective-C, but is recognized by the Swift
runtime so that it can be dynamically cast back to the boxed type.
Long story short.
To check if value has a reference type:
if type(of: value) is AnyClass {
// ...
}
To check if type is a reference type:
if SomeType.self is AnyClass {
// ...
}
More helpful answers:
https://stackoverflow.com/a/39185374/746347
https://stackoverflow.com/a/39546887/746347
Related
I'm learning Swift for iOS 8 / OSX 10.10 by following this tutorial, and the term "unwrapped value" is used several times, as in this paragraph (under Objects and Class):
When working with optional values, you can write ? before operations
like methods, properties, and subscripting. If the value before the ?
is nil, everything after the ? is ignored and the value of the whole
expression is nil. Otherwise, the optional value is unwrapped, and
everything after the ? acts on the unwrapped value. In both cases, the
value of the whole expression is an optional value.
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength
I don't get it, and searched on the web without luck.
What does this means?
Edit
From Cezary's answer, there's a slight difference between the output of the original code and the final solution (tested on playground) :
Original code
Cezary's solution
The superclass' properties are shown in the output in the second case, while there's an empty object in the first case.
Isn't the result supposed to be identical in both case?
Related Q&A : What is an optional value in Swift?
First, you have to understand what an Optional type is. An optional type basically means that the variable can be nil.
Example:
var canBeNil : Int? = 4
canBeNil = nil
The question mark indicates the fact that canBeNil can be nil.
This would not work:
var cantBeNil : Int = 4
cantBeNil = nil // can't do this
To get the value from your variable if it is optional, you have to unwrap it. This just means putting an exclamation point at the end.
var canBeNil : Int? = 4
println(canBeNil!)
Your code should look like this:
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare!.sideLength
A sidenote:
You can also declare optionals to automatically unwrap by using an exclamation mark instead of a question mark.
Example:
var canBeNil : Int! = 4
print(canBeNil) // no unwrapping needed
So an alternative way to fix your code is:
let optionalSquare: Square! = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare.sideLength
EDIT:
The difference that you're seeing is exactly the symptom of the fact that the optional value is wrapped. There is another layer on top of it. The unwrapped version just shows the straight object because it is, well, unwrapped.
A quick playground comparison:
In the first and second cases, the object is not being automatically unwrapped, so you see two "layers" ({{...}}), whereas in the third case, you see only one layer ({...}) because the object is being automatically unwrapped.
The difference between the first case and the second two cases is that the second two cases will give you a runtime error if optionalSquare is set to nil. Using the syntax in the first case, you can do something like this:
if let sideLength = optionalSquare?.sideLength {
println("sideLength is not nil")
} else {
println("sidelength is nil")
}
The existing correct answer is great, but I found that for me to understand this fully, I needed a good analogy, since this is a very abstract and weird concept.
So, let me help those fellow "right-brained" (visual thinking) developers out by giving a different perspective in addition to the correct answer. Here is a good analogy that helped me a lot.
Birthday Present Wrapping Analogy
Think of optionals as being like birthday presents that come in stiff, hard, colored wrapping.
You don't know if there's anything inside the wrapping until you unwrap the present — maybe there is nothing at all inside! If there is something inside, it could be yet another present, which is also wrapped, and which also might contain nothing. You might even unwrap 100 nested presents to finally discover there was nothing but wrapping.
If the value of the optional is not nil, now you have revealed a box containing something. But, especially if the value is not explicitly typed and is a variable and not a predefined constant, then you may still need to open the box before you can know anything specific about what's in the box, like what type it is, or what the actual value is.
What's In The Box?! Analogy
Even after you unwrap the variable, you are still like Brad Pitt in the last scene in SE7EN (warning: spoilers and very R-rated foul language and violence), because even after you have unwrapped the present, you are in the following situation: you now have nil, or a box containing something (but you don't know what).
You might know the type of the something. For example, if you declared the variable as being type, [Int:Any?], then you'd know you had a (potentially empty) Dictionary with integer subscripts that yield wrapped contents of any old type.
That is why dealing with collection types (Dictionaries and Arrays) in Swift can get kind of hairy.
Case in point:
typealias presentType = [Int:Any?]
func wrap(i:Int, gift:Any?) -> presentType? {
if(i != 0) {
let box : presentType = [i:wrap(i-1,gift:gift)]
return box
}
else {
let box = [i:gift]
return box
}
}
func getGift() -> String? {
return "foobar"
}
let f00 = wrap(10,gift:getGift())
//Now we have to unwrap f00, unwrap its entry, then force cast it into the type we hope it is, and then repeat this in nested fashion until we get to the final value.
var b4r = (((((((((((f00![10]! as! [Int:Any?])[9]! as! [Int:Any?])[8]! as! [Int:Any?])[7]! as! [Int:Any?])[6]! as! [Int:Any?])[5]! as! [Int:Any?])[4]! as! [Int:Any?])[3]! as! [Int:Any?])[2]! as! [Int:Any?])[1]! as! [Int:Any?])[0])
//Now we have to DOUBLE UNWRAP the final value (because, remember, getGift returns an optional) AND force cast it to the type we hope it is
let asdf : String = b4r!! as! String
print(asdf)
Swift places a high premium on type safety. The entire Swift language was designed with safety in mind. It is one of the hallmarks of Swift and one that you should welcome with open arms. It will assist in the development of clean, readable code and help keep your application from crashing.
All optionals in Swift are demarcated with the ? symbol. By setting the ? after the name of the type in which you are declaring as optional you are essentially casting this not as the type in which is before the ?, but instead as the optional type.
Note: A variable or type Int is not the same as Int?. They are two different types that can not be operated on each other.
Using Optional
var myString: String?
myString = "foobar"
This does not mean that you are working with a type of String. This means that you are working with a type of String? (String Optional, or Optional String). In fact, whenever you attempt to
print(myString)
at runtime, the debug console will print Optional("foobar"). The "Optional()" part indicates that this variable may or may not have a value at runtime, but just so happens to currently be containing the string "foobar". This "Optional()" indication will remain unless you do what is called "unwrapping" the optional value.
Unwrapping an optional means that you are now casting that type as non-optional. This will generate a new type and assign the value that resided within that optional to the new non-optional type. This way you can perform operations on that variable as it has been guaranteed by the compiler to have a solid value.
Conditionally Unwrapping will check if the value in the optional is nil or not. If it is not nil, there will be a newly created constant variable that will be assigned the value and unwrapped into the non-optional constant. And from there you may safely use the non-optional in the if block.
Note: You can give your conditionally unwrapped constant the same name as the optional variable you are unwrapping.
if let myString = myString {
print(myString)
// will print "foobar"
}
Conditionally unwrapping optionals is the cleanest way to access an optional's value because if it contains a nil value then everything within the if let block will not execute. Of course, like any if statement, you may include an else block
if let myString = myString {
print(myString)
// will print "foobar"
}
else {
print("No value")
}
Forcibly Unwrapping is done by employing what is known as the ! ("bang") operator. This is less safe but still allows your code to compile. However whenever you use the bang operator you must be 1000% certain that your variable does in fact contain a solid value before forcibly unwrapping.
var myString: String?
myString = "foobar"
print(myString!)
This above is entirely valid Swift code. It prints out the value of myString that was set as "foobar". The user would see foobar printed in the console and that's about it. But let's assume the value was never set:
var myString: String?
print(myString!)
Now we have a different situation on our hands. Unlike Objective-C, whenever an attempt is made to forcibly unwrap an optional, and the optional has not been set and is nil, when you try to unwrap the optional to see what's inside your application will crash.
Unwrapping w/ Type Casting. As we said earlier that while you are unwrapping the optional you are actually casting to a non-optional type, you can also cast the non-optional to a different type. For example:
var something: Any?
Somewhere in our code the variable something will get set with some value. Maybe we are using generics or maybe there is some other logic that is going on that will cause this to change. So later in our code we want to use something but still be able to treat it differently if it is a different type. In this case you will want to use the as keyword to determine this:
Note: The as operator is how you type cast in Swift.
// Conditionally
if let thing = something as? Int {
print(thing) // 0
}
// Optionally
let thing = something as? Int
print(thing) // Optional(0)
// Forcibly
let thing = something as! Int
print(thing) // 0, if no exception is raised
Notice the difference between the two as keywords. Like before when we forcibly unwrapped an optional we used the ! bang operator to do so. Here you will do the same thing but instead of casting as just a non-optional you are casting it also as Int. And it must be able to be downcast as Int, otherwise, like using the bang operator when the value is nil your application will crash.
And in order to use these variables at all in some sort or mathematical operation they must be unwrapped in order to do so.
For instance, in Swift only valid number data types of the same kind may be operated on each other. When you cast a type with the as! you are forcing the downcast of that variable as though you are certain it is of that type, therefore safe to operate on and not crash your application. This is ok as long as the variable indeed is of the type you are casting it to, otherwise you'll have a mess on your hands.
Nonetheless casting with as! will allow your code to compile. By casting with an as? is a different story. In fact, as? declares your Int as a completely different data type all together.
Now it is Optional(0)
And if you ever tried to do your homework writing something like
1 + Optional(1) = 2
Your math teacher would have likely given you an "F". Same with Swift. Except Swift would rather not compile at all rather than give you a grade. Because at the end of the day the optional may in fact be nil.
Safety First Kids.
'?' means optional chaining expression
the'!'means is force-value
There are 7 ways to unwrapping optional value in Swift.
Optional Binding - Safe
Optional Chaining - Safe
Optional Pattern - Safe
Nil Coalescing - Safe
Guard Statement - Safe
Force Unwrapping - Unsafe
Implicit Unwrapping - Unsafe
I no longer see Xcode complaining that certain things need optionals (the "?"). Now it is always forced unwrapped (the bang "!"). Is there any reason to use optionals anymore when we now have forced unwrap?
I don't really know what you mean when you write that you no longer see Xcode complaining that "certain things need optionals. Now it is always forced unwrapped". These two sentences contradict eachother:
You may have non-optional variables as much as you wish, but optional can really nice once you get to know all the benefits of using them.
If you have a property that is not an optional, then it won't need, by definition, any unwrapping.
Perhaps what you ment was that Xcode seemingly complains less often when you actually do force unwrap optionals, or, as a bad habit of Xcode, prompts you to force unwrap things to avoid compile time errors. This is generally because Xcode cannot know at compile time that you just wrote code that will break your app at runtime.
Xcode may seemingly at times have only one single purpose with its "smart hints": namely to absolve compile time errors. If you try to assign the value of a String? type (optional String) to String type, Xcode will prompt you with a compiler error and ask if you ment to add the forced unwrapping operator !. Smart Xcode, you say? Meh, Xcode is good for many things, but deciding how you unwrap your optionals is, not yet anyway, one of them. So even with Xcode prompting you for all kinds of things: if you can use optional chaining, do.
There might be exception, of course. For the controller part of the MVC design pardigm, you usually use the as! operator to do "forced conversion" (casting), with Xcode sometimes telling you to explicitly to use as! instead of as, e.g. "Did you mean as! ... ?". In these situations, Xcode can sometimes actually know what its doing and infer that you are trying to cast, as an example, a custom UIViewController class instance to type UIViewController, i.e., to it's parent class. I'd say that this is perhaps one of the few times I use the "forced" marker ! without go-arounds; forced conversion to types I know with 100% certainty to be castable.
The as! operator
But let's leave the subject of type conversion/casting and move on to optional types, wrapping, and optional chaining, in general.
Generally, you should avoid force unwrapping unless you explicitly knows that the entity you unwrap will be non-nil. For general class properties, variables and so on, given that you state this question the way you do, I'll give your the following advice:
If you can use conditional unwrapping (if-let, guard-let, nil
coalescing operator ??), then don't use forced unwrapping (!).
Below follows an example of the dangers of forced unwrapping. You can treat the first if clause (if arc4random...) as any smaller or larger segment of some program you've written with imperative programming techniques: we don't really know in detail just how 'name' will turn out until runtime, and our compiler can't really help us out here.
var name : String?
/* 'name' might or might not have a non-nil
value after this if clause */
if arc4random_uniform(2) < 1 {
name = "David"
}
/* Well-defined: us an if-let clause to try to unwrap your optional */
if let a = name {
print("Hello world "+a)
/* Very well-behaved, we did a safe
unwrap of 'name', if not nil, to constant a */
print("Hello world "+name!)
/* Well... In this scope, we know that name is,
for a fact, not nil. So here, a force unwrap
is ok (but not needed). */
}
let reallyGiveMeThatNameDammit = name!
/* NOT well-defined. We won't spot this at compile time, but
if 'name' is nil at runtime, we'll encounte a runtime error */
I recommend you to read up on optional chaining, a key subject in Swift.
Swift Language Guide - Optional Chaining
do you mean that cocoa stuff? do you mean implicitly unwrapped?
protocol AnyObject { ... }
The protocol to which all classes implicitly conform.
When used as a concrete type, all known #objc methods and properties are available, as implicitly-unwrapped-optional methods and properties respectively, on each instance of AnyObject. For example:
class C {
#objc func getCValue() -> Int { return 42 }
}
// If x has a method #objc getValue()->Int, call it and
// return the result. Otherwise, return nil.
func getCValue1(x: AnyObject) -> Int? {
if let f: ()->Int = x.getCValue { // <===
return f()
}
return nil
}
// A more idiomatic implementation using "optional chaining"
func getCValue2(x: AnyObject) -> Int? {
return x.getCValue?() // <===
}
// An implementation that assumes the required method is present
func getCValue3(x: AnyObject) -> Int { // <===
return x.getCValue() // x.getCValue is implicitly unwrapped. // <===
}
I understand, this particular error was already posted here and there and the code is somewhat basic, but I myself still unable to figure this one out & I need advice.
The thing is when I add the first two lines of code provided on parse.com for saving objects
var gameScore = PFObject(className:"GameScore")
gameScore["score"] = 1337
I get the following error for the second line:
'PFObject' does not have a member named 'subscript'
I'm on Xcode 6.3 beta 2.
All required libraries are linked with binary, <Parse/Parse.h> imported via BridgeHeader.
What syntax should I use?
This is happening due to the 1.6.4 version of the parse sdk which added Objective-C Nullability Annotations to the framework. In particular the file Parse/PFObject.h defines:
- (PF_NULLABLE_S id)objectForKeyedSubscript:(NSString *)key;
which is causing the Swift compile error. Removing the PF_NULLABLE_S fixes the problem.
On the other hand it seems correct that an object for a keyed subscript might be nil, so I suspect this is a Swift bug...
The problem seems to be the changed method signature, as kashif suggested. Swift doesn't seem to be able to bridge to the Objective-C method because the signature no longer matches the subscript method names.
Workaround 1
You can work around this without modifying the framework by calling the subscript method directly, instead of using the [] operator:
Instead of using the instruction below for getting the value of a particular key:
let str = user["key-name"] as? Bool
Please use the following instruction:
let str = user.objectForKey("key-name") as? Bool
and
Instead of using the instruction below for setting the value of a particular key:
user["key-name"] = "Bla bla"
Please use the following instruction:
user.setObject("Bla bla", forKey: "key-name")
Workaround 2
Another solution is to add an extension on PFObject that implements the subscript member and calls setValue:forKey::
extension PFObject {
subscript(index: String) -> AnyObject? {
get {
return self.valueForKey(index)
}
set(newValue) {
if let newValue: AnyObject = newValue {
self.setValue(newValue, forKey: index)
}
}
}
}
Note that this second workaround isn't entirely safe, since I'm not sure how Parse actually implements the subscript methods (maybe they do more than just calling setValue:forKey - it has worked in my simple test cases, so it seems like a valid workaround until this is fixed in Parse/Swift.
I've successfully run your exact code.
First, make sure you are indeed saving the object in the background, after you set the new value:
gameScore.save()
I would double check for misspellings in the class name and subclass; if they are incorrect, it will not work.
If that's not the problem, verify in Parse that the "score" subclass is set to be a number. If you accidentally set it to be a string, setting it as an integer will not work.
If these suggestions have not hit the solution, then I'm not sure what the problem is. Hope I helped.
I encountered a similar error with Parse 1.6.4 and 1.6.5 in the PFConstants.h header file with method parameters.
Xcode 6.3 beta 4 has a note in the "New in..." section regarding nullability operators.
Moving the nullability operator between the pointer operator and the variable name seems to comply/compile.
Changing:
PF_NULLABLE_S NSError *error
to:
NSError * PF_NULLABLE_S error
(i.e., NSError* __nullable error)
... resolved the compiler error.
This also worked for block parameters defined with id. So...
PF_NULLABLE_S id object
becomes:
id PF_NULLABLE_S object
In the above case, perhaps:
- (id PF_NULLABLE_S)objectForKeyedSubscript:(NSString *)key;
I.e., the nullability operator is after the pointer type.
I know its been a while but I encountered a similar problem when I was starting my first Parse application with SDK version 1.9.1.
The Quickstart guide had the code below as an example as to how to save values:
let testObject = PFObject(className: "TestObject")
testObject["foo"] = "bar"
testObject.saveInBackgroundWithBlock { (success: Bool, error: NSError?) -> Void in
println("Object has been saved.")
}
But, the line testObject["foo"] = "bar" returned the error 'PFObject' does not have a member named 'subscript'. I was able to work around the problem by changing the line to testObject.setValue("bar", forKey: "foo"). (As suggested by a tutorial video on YouTube: https://www.youtube.com/watch?v=Q6kTw_cK3zY)
Apple has the following method in the SKPhysicsBody class.
/* Returns an array of all SKPhysicsBodies currently in contact with this one */
func allContactedBodies() -> [AnyObject]!
I noticed it returns an array of AnyObject. So I read about how to deal with down casting AnyObject Here
I want to loop through the allContactedBodies array of my physics body. The problem is, no matter what I try I just can't get things to work.
I tried this first:
for body in self.physicsBody.allContactedBodies() as [SKPhysicsBody] {
}
But I get this error.
fatal error: array cannot be downcast to array of derived
I also tried this:
for object in self.physicsBody.allContactedBodies() {
let body = object as SKPhysicsBody
}
But this also crashes with the following:
And similarly I tried this:
for object in self.physicsBody.allContactedBodies() {
let body = object as? SKPhysicsBody
}
There is no crash, but "body" becomes nil.
And if I don't cast at all, I don't get a crash. For example:
for object in self.physicsBody.allContactedBodies() {
}
But obviously I need to cast if I want to use the actual type.
So then as a test I just tried this:
let object: AnyObject = SKPhysicsBody()
let body = object as SKPhysicsBody
And this also results in the same crash that is in the picture.
But other types won't crash. For example, this won't crash.
let object: AnyObject = SKNode()
let node = object as SKNode
So my question is, how can I correctly loop through the allContactedBodies array?
Edit: I am running Xcode 6 beta 4 on iOS 8 beta 4 device.
Edit 2: More Information
Ok so I just did some more testing. I tried this:
let bodies = self.physicsBody.allContactedBodies() as? [SKPhysicsBody]
If "allContactedBodies" is empty, then the cast is successful. But if "allContactedBodies" contains objects, then the cast fails and "bodies" will become nil, so I can't loop through it. It seems that currently it is just NOT POSSIBLE to cast AnyObject to SKPhysicsBody, making it impossible to loop through the "allContactedBodies" array, unless someone can provide a workaround.
Edit 3: Bug still in Xcode 6 beta 5. Workaround posted below still works
Edit 4: Bug still in Xcode 6 beta 6. Workaround posted below still works
Edit 5: Disappointed. Bug still in Xcode 6 GM. Workaround posted below still works
EDIT 6: I have received the following message from Apple:
Engineering has provided the following information:
We believe this issue has been addressed in the latest Xcode 6.1 beta.
BUT IT IS NOT, the bug is still in Xcode 6.1.1!!! Workaround still works.
Edit 7: Xcode 6.3, still not fixed, workaround still works.
After much trial and error, I have found a workaround to my problem. It turns out that you don't need to downcast at all to access the properties of the SKPhysicsBody, when the type is AnyObject.
for object in self.physicsBody.allContactedBodies() {
if object.node??.name == "surface" {
isOnSurface = true
}
}
Update: This was a bug, and it's fixed in iOS 9 / OS X 10.11. Code like the following should just work now:
for body in self.physicsBody.allContactedBodies() {
// inferred type body: SKPhysicsBody
print(body.node) // call an API defined on SKPhysicsBody
}
Leaving original answer text for posterity / folks using older SDKs / etc.
I noticed this in the related questions sidebar while answering this one, and it turns out to be the same underlying issue. So, while Epic Byte has a workable workaround, here's the root of the problem, why the workaround works, and some more workarounds...
It's not that you can't cast AnyObject to SKPhysicsBody in general — it's that the thing(s) hiding behind these particular AnyObject references can't be cast to SKPhysicsBody.
The array returned by allContactedBodies() actually contains PKPhysicsBody objects, not SKPhysicsBody objects. PKPhysicsBody isn't public API — presumably, it's supposed to be an implementation detail that you don't see. In ObjC, it's totally cool to cast a PKPhysicsBody * to SKPhysicsBody *... it'll "just work" as long as you call only methods that the two classes happen to share. But in Swift, you can cast with as/as?/as! only up or down the type hierarchy, and PKPhysicsBody and SKPhysicsBody are not a parent class and subclass.
You get an error casting let obj: AnyObject = SKPhysicsBody(); obj as SKPhysicsBody because even the SKPhysicsBody initializer is returning a PKPhysicsBody. Most of the time you don't need to go through this dance (and have it fail), because you get a single SKPhysicsBody back from an initializer or method that claims to return an SKPhysicsBody — all the hand-wavy casting between SKPhysicsBody and PKPhysicsBody is happening on the ObjC side, and Swift trusts the imported ObjC API (and calls back to the original API through the ObjC runtime, so it works just as it would in ObjC despite the type mismatch).
But when you cast an entire array, a runtime typecast needs to happen on the Swift side, so Swift's stricter type-checking rules come into play... casting a PKPhysicsBody instance to SKPhysicsBody fails those rules, so you crash. You can cast an empty array to [SKPhysicsBody] without error because there aren't any objects of conflicting type in the array (there aren't any objects in the array).
Epic Byte's workaround works because Swift's AnyObject works like ObjC's id type: the compiler lets you call methods of any class on it, and you just hope that at runtime you're dealing with an object that actually implements those methods.
You can get back a little bit of compile-time type safety by explicitly forcing a side cast:
for object in self.physicsBody.allContactedBodies() {
let body = unsafeBitCast(object, SKPhysicsBody.self)
}
After this, body is an SKPhysicsBody, so the compiler will let you call only SKPhysicsBody methods on it... this behaves like ObjC casting, so you're still left hoping that the methods you call are actually implemented by the object you're talking to. But at least the compiler can help keep you honest. (You can't unsafeBitCast an array type, so you have to do it to the element, inside the loop.)
This should probably be considered a bug, so please let Apple know if it's affecting you.
When I wrote this:
// json is of type AnyObject
var status : String? = json.valueForKeyPath("status") as String?
Xcode seems to blocked in an infinite loop during the compilation:
Is there something wrong in my code?
I've done some tests and when I wrote:
var status : String? = json.valueForKeyPath("status") as? String
Xcode is able to compile but what will be the behavior when valueForKeyPath will return nil.
As the documentation says:
Because downcasting can fail, the type cast operator comes in two different forms. The optional form, as?, returns an optional value of the type you are trying to downcast to.
Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/au/jEUH0.l
This means that when you write as? String, the return value is automatically wrapped in an optional for you, so the actual type produced by this is String?, which is the behaviour that you want, so your second option is correct.
In your first example, you are trying to cast the value returned by valueForKeyPath, which is of type AnyObject! (! means implicitly unwrapped), to String?, which is explicitly wrapped, and this the value is not automatically wrapped in an optional for you, so, since these types are not identical, casting between them probably won't work.
TL;DR: your first option is actually incorrect (although it shouldn't crash the compiler, that's a bug), and your second option is correct and does what you want.
Your second version is correct. An optional value is supposed to be assigned to a statement that can return nil. This is the flow of that line:
valueForKeyPath returns an implicitly unwrapped optional of AnyObject (AnyObject!). This means that it can be nil or it can have a value.
An attempt is made to convert it to a String
If it is not possible to convert it to a String, return nil making status nil. If it is indeed a non-nil String return that making status whatever string is returned