Can not satisfy generic constraint with subclass? - swift

I have following compiler error:
Cannot convert value of type ‘PostTagViewModel<CreatePostMediaViewModel>’ to expected argument type ‘PostTagViewModel<PostMediaViewModel>’
CreatePostMediaViewModel is subclass of PostMediaViewModel, so on the first glance it seemed like this should work out of the box, but sadly it does not?
EDIT:
Some addtional info, swift array is generic and I can pass [Subclass] where parameter is declared [Baseclass]

Related

Cannot convert type value of type Observable<Store> to expected argument type Observable<Store?>

I'm getting an error which says the following:
Cannot convert value of type 'Observable<Store>' to expected argument type 'Observable<Store?>
So the method I'm calling StoreMock(state: stateSubject, store: storeSubject) seems to expect an optional for the observable storeSubject. But I'm not sure why it should matter if I pass in a non-optional. Shouldn't it be fine as it will always be there.
Any ideas?
You have to wrap the object into an Optional:
StoreMock(state: stateSubject, store: storeSubject.map(Optional.some))
Just one call will fix this.

what's the difference between typing String() and String.self in swift?

I'm kind of stuck trying to understand .self in swift, always I register a custom cell in an collectionView or an tableView I have to register like customCollectionViewCell.self but why not for example customCollectionViewCell() ?
I've tried in the playground to type String.self in a var to see what happens and it give me no errors but when I try to give it a value it give me the following error
Cannot assign value of type 'String' to type String.Type
what does it mean?
Type() is shorthand notation for Type.init(), so String() calls String.init() and hence initialises a String.
On the other hand, String.self returns the meta type of String, which is a type that represents the String type itself rather than any instance of that type. For more information on meta types, see the Metatype Type section of the official Swift language reference.
In your specific example, you need to register a UITableViewCell subclass type rather than an instance of a specific type, hence you need to use YourCellType.self.

Dynamic casting using result of NSClassFromString("MyUIViewController")

I'm finding that the following code does not work, but I don't exactly understand why.
Say I have a class name saved in a string. I want to cast a view controller as the class that this string refers to.
let controller = self.navigationController as! NSClassFromString("MyUIViewController")
Swift doesn't seem to understand this - I get this error:
Undeclared use of NSClassFromString.
Or the error:
Consecutive statements must be separated by `,`
Can anyone explain why this is the case? I can't cast (using as?) a type based on some variable?
Thanks
No, you cannot cast to a runtime type object. You must cast to a compile-time type. This is why we write x as Int, not x as Int.self: Int is a type, and Int.self is an object that represents that type at runtime.
What would it mean to cast to NSClassFromString("MyUIViewController")? Now you have a variable, controller, whose value is some type that the compiler knows nothing about, so the compiler cannot let you do anything with controller. You can't call methods or access properties on it, because the compiler doesn't know what methods or properties it has. You can't pass it as an argument to a function, because the compiler doesn't know whether it is the right type for that argument.
If you edit your question to explain what you want to do with controller (what methods you want to call on it or what properties you want to access or what functions you want to pass it to), then I will revise my answer to address your goal.

Learning about type methods/type properties

I'm reading through the Swift documentation about type methods and type properties, and I cannot for the life of me figure out why it says this particular thing (in bold):
Within the body of a type method, the implicit self property refers to
the type itself, rather than an instance of that type. For
structures and enumerations, this means that you can use self to
disambiguate between type properties and type method parameters, just
as you do for instance properties and instance method parameters.
More generally, any unqualified method and property names that you use
within the body of a type method will refer to other type-level
methods and properties. A type method can call another type method
with the other method’s name, without needing to prefix it with the
type name. Similarly, type methods on structures and enumerations
can access type properties by using the type property’s name without a
type name prefix.
So, why is this pointing out structures and enumerations being able to do these things when, as far as I know, you can do these things with any kind of type methods/parameters (i.e. classes as well)? It makes me think I'm missing something.
The page in the documentation I'm looking at is here: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Methods.html
Apparently I wasn't the only one with this question. I'm not sure how I didn't see this post before: https://softwareengineering.stackexchange.com/questions/276962/static-properties-and-implicit-self-property-in-structures-and-enumerations-vs

Cast to a Metatype Type in Swift?

Can you cast to a Metatype Type in Swift? It really seems like you should be able to (after all you can instantiate objects from Metatypes).
The following doesn't work:
class Super {}
class A : Super {}
let superA:Super = A()
let subType = superA.dynamicType
let afterCast = superA as subType
//Compiler error: "use of undeclared type 'subType'"
Does anyone know the right way to do this?
Edit:
As newacct pointed out, the result of .dynamicType is obviously not known until runtime, so a compile-time cast to the result of .dynamicType would not make sense.
So the answer is: "You can't" (and there is no good reason to try).
First of all, as takes a type, not an expression, on the right-hand side. So what you have is a syntax error.
What you seem to be trying to do is "cast" to a type that is computed at runtime. What would that even mean? Let's first consider what is a "cast".
Usually, when we have a cast expression x as T, it has two components:
At compile-time: The entire cast expression x as T has compile-time type T?, which allows you to do stuff with the resulting expression that you maybe cannot do on x directly. In other words, it allows you to change the compile-time type.
At runtime: It checks whether the runtime type of x is a subtype of T, and if it is, it evaluates to the optional containing that value, otherwise, it evaluates to nil.
If the type T is not known at compile-time, then obviously you cannot do the compile-time part of it. (The compile-time type of the resulting expression cannot, obviously, depend on something which is not known at compile-time.)
The other part, the runtime component, could that be done with a type computed at runtime? Sure. For example,
import Foundation
let afterCast : Super? =
(superA as AnyObject).isKindOfClass(subType) ? superA : nil
It's not clear if that is what you want.