Anyobject Not Working in Xcode8 Beta6

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



Leave a reply



Submit