Perché sta succedendo?
Questo perché quando la tua sottoview si trova al di fuori dei limiti della tua superview, gli eventi di tocco che si verificano effettivamente in quella sottoview non verranno consegnati a quella sottoview. Tuttavia, SARA essere consegnato al suo superview.
Indipendentemente dal fatto che le viste secondarie siano o meno ritagliate visivamente, gli eventi di tocco rispettano sempre il rettangolo dei limiti della superview della vista di destinazione. In altre parole, gli eventi di tocco che si verificano in una parte di una vista che si trova al di fuori del rettangolo dei limiti della sua supervista non vengono consegnati a quella vista. Link
Cosa devi fare?
Quando la tua supervista riceve l'evento di tocco menzionato sopra, dovrai dire esplicitamente a UIKit che la mia sottoview dovrebbe essere quella che riceve questo evento di tocco.
E il codice?
Nella tua superview, implementa func hitTest(_ point: CGPoint, with event: UIEvent?)
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if isHidden || alpha == 0 || clipsToBounds { return super.hitTest(point, with: event) }
// convert the point into subview's coordinate system
let subviewPoint = self.convert(point, to: subview)
// if the converted point lies in subview's bound, tell UIKit that subview should be the one that receives this event
if !subview.isHidden && subview.bounds.contains(subviewPoint) { return subview }
return super.hitTest(point, with: event)
}
Affascinante gotchya: devi andare al "superview più alto troppo piccolo"
Devi andare "su" alla vista "più alta" che la vista del problema è all'esterno.
Esempio tipico:
Supponiamo che tu abbia uno schermo S, con una vista contenitore C.La vista del controller della vista contenitore è V. (Ricorda che V si troverà all'interno di C e avrà le stesse dimensioni.) V ha una vista secondaria (forse un pulsante) B. B è il problema vista che è effettivamente al di fuori di V.
Ma nota che B è anche al di fuori di C.
In questo esempio, si deve applicare la soluzione override hitTest
di fatto a C, non V . Se lo applichi a V, non fa nulla.