What is difference between Any , Hashable , AnyHashable in Swift 3? - ios

I scratch my head through lots of tutorials to understand the difference between the above 3 terms and find new term type erased container, now it becomes confusing to me. It raises lots of question.
Why does Swift introduce AnyHashable ?
What is the fundamental difference between these 3 terms?
Difference between Any and AnyHashable ?
Difference between Hashable and AnyHashable?
When to use Hashable and when to use AnyHashable ?
Last but most confusing, what is the meaning of type erased term in the context of AnyHashable ?
As a context, I followed Swift Evolution Proposal SE-0131.

It's more important to understand what they are than what are the differences between them.
Any means "anything", ranging from swift enums, tuples, closures, structs, classes, protocols, whatever. Every type can be assigned to a variable of type Any.
Hashable is protocol that says "this object can be hashed i.e. has a hashcode". If your object can be hashed, implement this protocol, because lots of data structures (namely dictionaries and sets) need it.
So what is AnyHashable?
Normally, if you try to do this:
let a: Set<Hashable>?
it does not compile. This is because Hashable inherits from Equatable which contains Self.
Now, let's say you want to port a method from Objective-C to swift. That method takes a parameter of type NSSet. In Swift, this will turn into a Set, but what is its generic parameter? If we just put Any like we do with NSArrays, it does not work because Set's objects must be hashable. But if we put Set<Hashable> it does not work either because Hashable can only be used as a generic constraint. That's why they wrapped Hashable with an AnyHashable that does not use Self and so can be used as a generic parameter.
Regarding what "type erased" means:
Having Self in a protocol is kind of like a protocol with a generic parameter, and the generic parameter is always the conforming class. This causes the protocols to be unable to be used on its own like Set<Hashable> because the "generic parameter" is unknown. AnyHashable solves this problem by not using Self at all so it now becomes a normal struct. It "erases" the generic Self type.

Related

Cannot assign a value of type 'AnyDataSource<NSManagedObjectSubclass>' to a value of type 'AnyDataSource<NSManagedObject>'

I'm stumped.
The title of this question the compiler error.
I am creating an object that basically marries the delegates of NSFetchedResultsController and UITableViewDataSource. The type parameter is used to indicate which NSManagedObject subclass should be used in the fetch requests.
Here is an example where Swift lacks dynamism and we end up writing all sorts of crazy code, (OR, I'm new to Swift and dislike being told what I'm not allowed to do)
So, on a UITableViewController subclass, i'd like to have a property
var dataSource: AnyDataSource<NSManagedObject>?
when I try to create one of these with a subclass of NSManagedObject and assign it to that property, the compiler complains. There seems to be nothing I can do that will succeed without a warning.
You would think that I should be able to use NSManagedObject or any of its subclasses, so I'm a little confused.
Any ideas? I'm using typical "type erasure" patterns that can be found on the internet, like via realm.io.
Ultimately I found that this approach was not possible. I mean, to achieve these with completely protocol-based programming.
I defined a few base protocols with no associated type, implemented an abstract baseclass that implements that protocol, then introduced generic type parameters in subclasses, that implement further protocols that have associated type.
I'll post my generalized solution on github when it's finished.

Meaning of the angle brackets in Objective-C?

Even though the question is quite wide I am actually curious regarding one case I sow recently while using the Realm library. As I previously used the protocols(delegate) on many occasions and also imported classes using <>. And now this is the line the code I don't completely understand or don't understand at all if I am mistaking:
#property (nonatomic, strong) RLMArray <ExerciseLog *><ExerciseLog> * exerciseLogs;
I suppose that the second part of the line <ExerciseLog> * exerciseLogs is used to ensure that exerciseLogs may be an instance of any ExerciseLog that conforms to the ExerciseLog protocol, is my assumption correct?
Or simple said if the user send a different object then the expected one, the app won't crash, and that a default value will be assigned.
And this part I am guessing, the is some sort of safe casting so that the returned object confirms to the ExerciseLog.
A combination of Obj-C protocol conformance and generics. RLMArray is declared as
#interface RLMArray < RLMObjectType : RLMObject * > : NSObject<RLMCollection,NSFastEnumeration>
it has one generic argument. That's the <ExerciseLog *>.
The second part <ExerciseLog> is conformance to protocol of the given type.
By the way, that protocol is declared using RLM_ARRAY_TYPE macro. The code seems to be a bit complicated but it was probably an older way to enforce element type for arrays (RLMArray<protocolX> is not assignable to RLMArray<protocolY>).
Quoting the documentation:
Unlike an NSArray, RLMArrays hold a single type, specified by the objectClassName property. This is referred to in these docs as the “type” of the array.
When declaring an RLMArray property, the type must be marked as conforming to a protocol by the same name as the objects it should contain (see the RLM_ARRAY_TYPE macro). RLMArray properties can also use Objective-C generics if available. For example:
The angle brackets in a class interface definition indicates the protocols that your class is conforming to.
A protocol is almost like an interface in Java or C#, with the addition that methods in an Objective-C protocol can be optional.
Additionaly in Objective-C you can declare a variable, argument or instance variable to conform to several protocols as well. Example
NSObject *myVariable;
In this case the class must be NSObject or a subclass (only NSProxy and its subclasses would fail), and it must also conform to both NSCoding and UITableViewDelegate protocols.
In Java or C# this would only be possible by actually declaring said class.

What is the difference between NSObject and AnyObject? When to use the two?

I'm trying to create an array to store Strings or an array of custom class. Am I better off creating a dictionary?
AnyObject is Swift's representation of Objective-C's id type. It's more general than NSObject (i.e. every NSObject is an AnyObject, but not every AnyObject is a NSObject).
On the other part of the question - depends on how you intend to use the structure. Using a more particular class for the generic structure (Swift's typed array or dictionary) will allow you to enjoy the benefits of the strong typing, whereas using a more generic type will allow you to be more dynamic. Really it depends on what you intend to use the class for.

"Type'Program' does not conform to protocol 'Any Object'"

I updated xcode and now I have error in my project and I dont have idea what to do with it.
struct Program {
let name : String
let url : String
}
self.arrayOfPrograms = [Program(name: "First", url: "http://1.com"), Program(name: "Second", url: "http://2.com"), Program(name: "Third", url: "http://2.com")]
and I'm getting error "Type'Program' does not conform to protocol 'Any Object'"
As reported in the documentation:
AnyObject can represent an instance of any class type.
A struct is not a class, so it cannot be cast to AnyObject
You should either:
turn Program into a class
define your array as Array<Any>
if your array is supposed to hold instances of Program only, declare it as Array<Program>
Needless to say, the last is the best solution, whereas the first is the one I wouldn't recommend because it requires you to make design changes (there's a reason why you declared it as a value type and not a reference type).
Side note: arrays and dictionaries can be cast to AnyObject because they are automatically bridged respectively to NSArray and NSDictionary, which are classes.
check this link you got your answare I recently wrapped my head around
something that I have found very strange in Swift. Swift provides two
high level protocols called Any and AnyObject. Any can be used for
both value types (like structs) and reference types (classes) while
AnyObject can only be used for classes.
enter link description here

What's the point of using 'Any' in Swift? When to use 'Any' and when to use 'AnyObject'?

In Swift documentation, it says the following:
Swift provides two special type aliases for working with non-specific types:
AnyObject can represent an instance of any class type.
Any can represent an instance of any type at all, apart from function types.
NOTE
Use Any and AnyObject only when you explicitly need the behavior and capabilities they provide. It is always better to be specific about the types you expect to work with in your code.
If I understand it correctly, AnyObject should be used when it is compatible with class types, which means it cannot represent Swift's built-in String, Int, Dictionary, Array, etc... since those are all represented as structure, not class, in Swift.
However, when I write the following code, it can be compiled without any errors:
var myInt: Int = 10
var myStr: String = "st"
var myDict:Dictionary<String, AnyObject> = ["k1": "1", "k2": 2, "k3": true]
var myArr:Array<AnyObject> = []
myArr.append(myInt)
myArr.append(myStr)
myArr.append(myDict)
println(myArr)
Because I define myArr as AnyObject[], it should be able to contain only class types, while myInt, myStr, and myDict are all compatible to Any, not AnyObject, and Any is not compatible with `AnyObject.
However, I think the reason it can be compiled is because myInt is convertible to Objective-C's NSInteger internally, which is a subtype of AnyObject. Same is true of String/NSString and Dictionary/NSDictionary. Is my guess correct? Then, here's my question:
Even if you can define Swift's Array as AnyObject and still store Swift's structure like Int or String, what's the point of using Any? Is there any situation that you have to define an Array as Any? How about the Dictionary's value type?
How should I decide when to use Any and when to use AnyObject, especially if I deal with an type which can be convertible to Objective-C's Object, like String, Int, Dictionary, etc?
I think the most methods in Cocoa and Cocoa Touch return AnyObject!, not Any!. So I wonder what is the best case to use Any in Swift's Array and Dictionary's value type.
Well you can use Any[] to store custom structs.
However, when I write the following code, it can be compiled without
any errors:
Not if you don't have import Foundation. Without importing Foundation, there are lots of errors. It only compiles for you due to the bridging that Foundation has for numeric types to NSNumber, String to NSString, etc.

Resources