I have an extension to walk up the view controller chain (even through container views, which is very handy)
public extension UIViewController // go up to a certain class
{
public func above<T>(_ : T.Type)->(T)
{
var p:UIResponder = self
repeat { p = p.next! } while !(p is T)
return p as! T
}
}
(Aside, NB, Swift3 needs the "!" on p.next: unfortunately I'm not sure exactly why.)
So, say you have a view controller class "General", you can
self.above(General).clickedHamburgerMenuButton()
and it will find the first "General" above you. All fine but with Swift 3 you get this warning.......
Missing '.self' for reference to metatype of type 'General'
It seems to want this
self.above(General.self).clickedHamburgerMenuButton()
1) It seems ... dangerous ... to change General
to General.self
- in fact is it safe and is the meaning the same as General
in Swift <3 ?
2) in the extension
public func above<T>(_ : T.Type)->(T)
why is that a metatype? Did I "do something wrong" and make it ask for a metatype rather than just a type?
2) What the hell is a "metatype"? (I can't, really, find it explained as such anywhere.) That is to say, what can "general" possibly mean there other than "the class itself". (Not an instance, or a static instance, or anything else...)
Because
.next
returns an Optional, butp
is not optional. This will crash if you run out of responders.I'm surprised that worked in earlier versions of Swift without the
.self
, but yes,.self
is required in order to directly reference a metatype. Referencing metatypes is somewhat rare in Swift, and can lead to surprising behaviors if done unintentionally, so it requires an extra piece of syntax to say "yes, I really mean the type."You did this correctly.
The type of a type. An instance of a metatype is a type. Consider:
To call this, you pass an instance of
Int
. So similarly:To call this, you pass an instance of the metatype
T.Type
, which is a type.Unrelated, but I would probably rethink this code along these lines. First, it is convenient to be able to treat the responder chain as a sequence. Here's one way to do that:
Then getting the next responder that matches a type is cleaner and clearer IMO (and works on any responder chain):