Reputation: 2488
This code is called when a subview (imageSlideshow
) is tapped:
imageSlideshow.didTap = { [weak self] in
guard UIApplication.shared.sendAction(#selector(ImageCarouselViewResponder.didTapImageCarousel(sender:)), to: nil, from: self, for: nil) else {
assertionFailure("No target for ImageCarouselViewResponder.didTapImageCarousel(sender:)")
return
}
…
This works as expected, as you can see from this debugging output:
(lldb) po UIApplication.shared.sendAction(#selector(ImageCarouselViewResponder.didTapImageCarousel(sender:)), to: nil, from: self, for: nil)
true
However, when I try to ask for the target with the same selector, it's nil
:
(lldb) po UIApplication.shared.target(forAction: #selector(ImageCarouselViewResponder.didTapImageCarousel(sender:)), withSender: self)
nil
Furthermore, I've added an extension to walk the responder tree to find the first responder, and it returns nil
in this situation.
How is sendAction(…)
working if there is no first responder?
Upvotes: 1
Views: 1496
Reputation: 56625
Calling target(forAction:)
will only pass the request up the responder chain from that responder, but the only thing after the application in the responder chain is the application delegate. Unless this method is implemented in either of those two, calling target(forAction:)
on the application instance would return nil
.
Calling sendAction(_:to:from:for:)
with a nil
target works because it sends the message to the first responder which passes it up the responder chain until it is handled.
Upvotes: 2