I have a complicated view class,
class Snap:UIViewController, UIScrollViewDelegate
{
}
and the end result is the user can, let's say, pick a color...
protocol SnapProtocol:class
{
func colorPicked(i:Int)
}
class Snap:UIViewController, UIScrollViewDelegate
{
someDelegate.colorPicked(blah)
}
So who's going to handle it.
Let's say that you know for sure there is something up the responder chain, even walking through container views, which is a SnapProtocol. If so you can use this lovely code to call it
var r : UIResponder = self
repeat { r = r.nextResponder()! } while !(r is SnapProtocol)
(r as! SnapProtocol).colorPicked(x)
If you prefer, you can use this superlative extension
public extension UIResponder // walk up responder chain
{
public func next<T>() -> T?
{
guard let responder = self.nextResponder()
else { return nil }
return (responder as? T) ?? responder.next()
}
}
courtesy these guys and safely find any SnapProtocol above you,
(next() as SnapProtocol?)?.colorPicked(x)
That's great.
But. What if the object that wants to get the colorPicked is a knight-move away from you, down some complicated side chain, and/or you don't even know which object wants it.
My current solution is this, I have a singleton "game manager" -like class,
public class .. a singleton
{
// anyone who wants a SnapProtocol:
var useSnap:SnapProtocol! = nil
}
Some freaky class, anywhere, wants to eat SnapProtocol ...
class Dinosaur:NSObject, SnapProtocol
{
....
func colorPicked(index: Int)
{...}
... so, to set that as the desired delegate, use the singleton
thatSingleton.useSnap = dinosaur
Obviously enough, this works fine.
Note too that I could easily write a little system in the singleton, so that any number of users of the protocol could dynamically register/deregister there and get the calls.
But it has obvious problems, it's not very "pattern" and seem violently non-idiomatic.
So. Am I really, doing this the right way in the Swift milieu?
Have I indeed confused myself, and there is some entirely different pattern I should be using in today's iOS, to send out such "messages to anyone who wants them?" ... maybe I shouldn't even be using a protocol?