Как удалить все распознаватели жестов из UIView в Swift
Я написал Swift-код, который пытается удалить все распознаватели жестов из всех вложенных представлений данного пользовательского типа UIView.
let mySubviews = self.subviews.filter() {
$0.isKindOfClass(CustomSubview)
}
for subview in mySubviews {
for recognizer in subview.gestureRecognizers {
subview.removeGestureRecognizer(recognizer)
}
}
Но строка for recognizer выдает ошибку компилятора:
'[AnyObject]?' does not have a member named 'Generator'
Я пытался изменить цикл for recognizer на for recognizer in enumerate(subview.gestureRecognizers), но это приводит к ошибке компилятора:
Type '[AnyObject]?!' Does not conform to protocol 'SequenceType'
Я вижу, что метод UIView gestureRecognizers возвращает [AnyObject]??, и я думаю, что дважды завернутые возвращаемые значения сбивают меня с толку. Кто-нибудь может мне помочь?
Обновление:
Пересмотрено, компиляция код:
if let recognizers = subview.gestureRecognizers {
for recognizer in recognizers! {
subview.removeGestureRecognizer(recognizer as UIGestureRecognizer)
}
}
3 ответов:
Обновление для iOS 11
Вообще это (и всегда было) плохой идеей удалить все жесты, распознанные из представления, путем циклического перебора его массива
gestureRecognizers. Вы должны удалить только распознаватели жестов, которыеВы добавляете в представление, отслеживая эти распознаватели в вашей собственной переменной экземпляра.Это приобретает новое значение в iOS 11 для представлений, которые участвуют в перетаскивании, потому что UIKit добавляет свои собственные распознаватели жестов к этим представлениям, чтобы распознайте затяжки и падения.
Обновление
Вам больше не нужно приводить к
UIGestureRecognizer, потому чтоUIView.gestureRecognizersбыл изменен на тип[UIGestureRecognizer]?в iOS 9.0.Также, используя оператор nil-coalescing
??, вы можете избежать оператораif.Однако самый короткий способ сделать это таков:for recognizer in subview.gestureRecognizers ?? [] { subview.removeGestureRecognizer(recognizer) }subview.gestureRecognizers?.forEach(subview.removeGestureRecognizer)Мы также можем выполнить фильтрацию подвидов в цикле
forследующим образом:for subview in subviews where subview is CustomSubview { for recognizer in subview.gestureRecognizers ?? [] { subview.removeGestureRecognizer(recognizer) } }Или мы можем обернуть все это в одно выражение (обернутое для ясность):
subviews.lazy.filter { $0 is CustomSubview } .flatMap { $0.gestureRecognizers ?? [] } .forEach { $0.view?.removeGestureRecognizer($0) }Использование
.lazyдолжно предотвратить создание ненужных временных массивов.Оригинал
Это одна из тех раздражающих вещей о Свифте. Ваш цикл for будет работать только в Objective-C, но в Swift вы должны явно развернуть необязательный массив:
if let recognizers = subview.gestureRecognizers { for recognizer in recognizers { subview.removeGestureRecognizer(recognizer as! UIGestureRecognizer) } }Вы можете принудительно развернуть его (
for recognizer in subview.gestureRecognizers!), но я не уверен, чтоgestureRecognizersможет вернутьnil, и вы получите ошибку времени выполнения, если это произойдет, и вы принудительно развернете его.
Более простой способ сделать это -
for subview in self.subviews as [UIView] { if subview.isKindOfClass(CustomSubview) { subview.gestureRecognizers?.removeAll(keepCapacity: false) } }
Comments