AnyObject not working in Xcode8 beta6?
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.
Xcode 8 beta 6: AnyObject replaced by Any: where is classForCoder?
Using type(of:)
You can use type(of:)
to find out what type of variable is in a variable of type Any
.
let a: Any = "hello"
print(type(of: a)) // String
let b: Any = 3.14
print(type(of: b)) // Double
import Foundation
let c: Any = "hello" as NSString
print(type(of: c)) // __NSCFString
let d: Any = ["one": 1, "two": "two"]
print(type(of: d)) // Dictionary
struct Person { var name = "Bill" }
let e: Any = Person()
print(type(of: e)) // Person
Using classForCoder
classForCoder
is still there, and you can cast a value of type Any
to AnyObject
, but if the value is a Swift value type, you'll get a converted result and not the original type:
import Foundation // or import UIKit or import Cocoa
let f: Any = "bye"
print((f as AnyObject).classForCoder) // NSString
print(type(of: f)) // String
let g: Any = 2
print((g as AnyObject).classForCoder) // NSNumber
print(type(of: g)) // Int
let h: Any = [1: "one", 2: 2.0]
print((h as AnyObject).classForCoder) // NSDictionary
print(type(of: h)) // Dictionary
struct Dog { var name = "Orion" }
let i: Any = Dog()
print((i as AnyObject).classForCoder) // _SwiftValue
print(type(of: i)) // Dog
// For an object, the result is the same
let j: Any = UIButton()
print((j as AnyObject).classForCoder) // UIButton
print(type(of: j)) // UIButton
Xcode 8 beta 6 AnyObject Swift 3 changes
According to the beta 6 release notes you have to (bridge) cast to AnyObject
cell.name.text = (maindata["name"] as AnyObject) as? String
or force cast
cell.name.text = maindata["name"] as! String
That's one more reason to prefer custom classes / structs with distinct property types over common dictionaries.
I updated to Xcode 8 beta 6 and I am getting very weird errors
The method signature has changed in Xcode 8 now it is the following:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Code here
}
How to test whether generic variable is of type AnyObject
In Swift 3, everything is bridgeable to AnyObject
due to the introduction of _SwiftValue
(see this Q&A for more info), that can wrap anything that isn't directly bridgeable to Objective-C in an opaque Objective-C compatible box.
Therefore is AnyObject
will always be true, as anything can be represented as an AnyObject
via wrapping in a _SwiftValue
.
One way to check whether a value is a reference type (as shown in this Q&A) is to type-check the type of the value against the metatype of AnyObject
, AnyClass
(aka AnyObject.Type
).
For generics, if you want to check whether the static type of T
is a reference type, you can do:
isObject = T.self is AnyClass
If you want to check whether the dynamic type of a value typed as T
is a reference type (such as val
in your example), you can use the type(of:)
function on the unwrapped value, as the aforementioned Q&A suggests:
if let val = val {
isObject = type(of: val) is AnyClass
// ...
}
The difference between these two approaches is that when T
is of type Any
(or a non AnyObject
abstract type), T.self is AnyClass
will return false
(which could be useful if you want a box where the value could be a reference or value type) – type(of: val) is AnyClass
however, will return whether val
itself is a reference type.
Check if `Any` value is object
UPDATE
The code I have shown below is reported as not working in release build.
(Please see Paul Cantrell's comment below.)
Apologies for my "as far as I tested" was too limited.
I'll update this answer when I find some further info about this.
I'm not sure we can see this behaviour in the next beta (or GM or Released version...), but this works as you expect in Xcode 8 beta 6.
let foo: Any = 4
if type(of: foo) is AnyClass {
print("It's an object.")
let object = foo as AnyObject
//do something with `object` that requires reference semantics
} else {
print("It's not an object.") //->It's not an object.
}
class MyClass {}
let bar: Any = MyClass()
if type(of: bar) is AnyClass {
print("It's an object.") //->It's an object.
let object = foo as AnyObject
//do something with `object` that requires reference semantics
} else {
print("It's not an object.")
}
let baz: Any = Array()
if type(of: baz) is AnyClass {
print("It's an object.")
let object = foo as AnyObject
//do something with `object` that requires reference semantics
} else {
print("It's not an object.") //->It's not an object.
}
I cannot check all possible cases, so there may be some edge cases where this does not work. But as far as I tested, this seems to work as expected.
Cannot assign value of type 'String' to type 'AnyObject?', Swift 3, Xcode 8 beta 6
In b6, String no longer magically bridges to NSString. String is not a class; it's a struct. You need to do the bridging by hand:
dict["key"] = "value" as AnyObject
The fact that is
still seems to be bridging is likely a bug and should be reported.
It goes without saying that [String: AnyObject]
and [String: Any]
should be used as little as possible in your code.
(Make sure to follow the link Hamish provides in the comments below.)
Unable to compile AWS CustomIdentityProvider on xcode 8 beta 6
Cast to NSDictionary instead of a Swift Dictionary:
return AWSTask(result: tokens! as NSDictionary)
Array storing Any objects is also of AnyObject type
First, the Swift Programming Language Guide is a not a language specification in the way that ISO 9899 defines C. (And even given an ISO standard, not every compiler implements C identically, or even in 100% accordance with the standard.) If you find a disagreement between the compiler and the documentation, it is just as likely to be a documentation bug as a compiler bug.
That said, I believe you've glossed over an important part of the spec you reference:
AnyObject can also be used as the concrete type for an instance of a type that bridges to an Objective-C class. Many value types in Swift bridge to Objective-C counterparts, like String and Int.
() -> Void
is equivalent to dispatch_block_t
, which bridges to ObjC as a dispatch_object
(see dispatch/object.h
and os/object.h
):
/*
* By default, dispatch objects are declared as Objective-C types when building
* with an Objective-C compiler. This allows them to participate in ARC, in RR
* management by the Blocks runtime and in leaks checking by the static
* analyzer, and enables them to be added to Cocoa collections.
* See for details.
*/
OS_OBJECT_DECL_CLASS(dispatch_object);
So there is no surprise here that () -> Void
can be coerced into AnyObject
.
In practice, pretty much anything can now bridge into AnyObject
(again, from a language specification point of view, anything that can be an NSValue
can be an AnyObject
, even though that's not exactly how it's implemented).
AnyObject
is different than Any
, however. Any
behaves like a protocol (despite not being a protocol). AnyObject
behaves like the superclass of every class (despite actually being a protocol).
let b = true // true
let bany = true as Any // true
let banyobj = true as AnyObject // 1 <=== (because it's NSNumber)
MemoryLayout.size(ofValue: b) // 1 (size of a bool)
MemoryLayout.size(ofValue: bany) // 32 (size of a protocol box)
MemoryLayout.size(ofValue: banyobj) // 8 (size of a reference pointer)
type(of: b) // Bool.Type
type(of: bany) // Bool.Type
type(of: banyobj) // __NSCFBoolean.Type
(Try the same thing for {}
to see how closures are handled.)
It is reasonable to open a defect against the AnyObject
docs to include a more explicit explanation that any type can be converted into a reference type using as AnyObject
, but this is just an omission, not a contradiction of what's already there. (And if it were a contradiction, or you find it confusing, then again, the correct answer is to open a defect to improve the docs to match Swift, not Swift to match the docs.)
Ambiguous error in Xcode 8 beta 6
cgRectValue
is a property on the NSValue
class. What you get out of the userInfo
dictionary isn't known to be an NSValue
, so you can't access NSValue
properties on it.
For the compiler to let you use those properties, you need to let it know that you expect that value to be an NSValue
:
if let beginKeyBoardFrame = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.origin.y {
(This didn't result in compiler errors before because dictionaries in imported Cocoa APIs bridged with a value type of AnyObject
. AnyObject
has some magic like the ObjC id
type, in that the compiler will let you call any method/property on it—with the result wrapped in an Optional
because it may not exist. Now that dictionaries have Any
as their value type, you need to explicitly say what you expect the value type to be.)
Related Topics
How to Tell Swiftui Views to Bind to Nested Observableobjects
Making Text Bold Using Attributed String in Swift
How to Create Launch Images For Iphone 6/6 Plus Landscape Only Apps
Customize Uitableview Header Section
Uiviewcontroller Viewdidload Vs. Viewwillappear: What Is the Proper Division of Labor
Sqlite File Location Core Data
Change Color of Certain Pixels in a Uiimage
Uiscrollview Scroll to Bottom Programmatically
How to Ignore Touch Events and Pass Them to Another Subview'S Uicontrol Objects
In Swift, How to Declare a Variable of a Specific Type That Conforms to One or More Protocols
In Ios13 the Status Bar Background Colour Is Different from the Navigation Bar in Large Text Mode
Download and Install an Ipa from Self Hosted Url on Ios
How to Create a Swift Date Object
iOS (Iphone, iPad, Ipodtouch) View Real-Time Console Log Terminal