In my app, I have a style dictionary that maps a style key to AnyObject? This allows me to store a CGColor as a value for a style key and all is good. When I want to retrieve the color later I index my dictionary with the appropriate key and try a conditional downcast: If let color = style[kStyle_BackgroundColor] as? CGColor { ... } This gets me an error "Conditional downcast to CoreFoundation type 'CGColor' will always succeed. That strikes me as odd. Trying various other mechanisms for downcasts lead to other errors. This "will always succeed" seems to violate the safety of Swift. Is this error message a bug?
Accepted Reply
The behavior is noted in the Xcode 6.1 Release Notes.
Swift Language
Casts can now be performed between CF types (such as
CFString
,
CGImage
, and
SecIdentity
) and
AnyObject
. Such casts will always succeed at run-time. For example:
var cfStr: CFString = ...
var obj: AnyObject = cfStr as AnyObject
var cfStr = obj as CFString
Swift challenges to import CF types as managed object references, but they are originally defined as pointers to private structs in C-language.
So, the original definitions do not contain type hierarchy informations, which are needed for conditional cast in Swift.
In fact, some CF types are actually subtypes of other CF types, but in old Swift, before 1.1, we cannot convert between such two types without using unsafeBitCast or similar unsafe things.
I believe this is a temporary workaround to treat CF types and shoul be improved, but as for now, it's an intended feature, so should not be called as a bug.
Replies
The behavior is noted in the Xcode 6.1 Release Notes.
Swift Language
Casts can now be performed between CF types (such as
CFString
,
CGImage
, and
SecIdentity
) and
AnyObject
. Such casts will always succeed at run-time. For example:
var cfStr: CFString = ...
var obj: AnyObject = cfStr as AnyObject
var cfStr = obj as CFString
Swift challenges to import CF types as managed object references, but they are originally defined as pointers to private structs in C-language.
So, the original definitions do not contain type hierarchy informations, which are needed for conditional cast in Swift.
In fact, some CF types are actually subtypes of other CF types, but in old Swift, before 1.1, we cannot convert between such two types without using unsafeBitCast or similar unsafe things.
I believe this is a temporary workaround to treat CF types and shoul be improved, but as for now, it's an intended feature, so should not be called as a bug.
Thanks. In this case I'll use a belt and suspenders approach then
if let colorValue = topic.style[kTopicStyle_BackgroundColor] {
if(CFGetTypeID(colorValue) == CGColorGetTypeID()) {
newView.layer?.backgroundColor = (colorValue as! CGColor)
}
}