Как удалить все распознаватели жестов из 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)
}
}
632   3  

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, и вы получите ошибку времени выполнения, если это произойдет, и вы принудительно развернете его.

Простейшее решение

yourView.gestureRecognizers?.removeAll()

Более простой способ сделать это -

for subview in self.subviews as [UIView] {
    if subview.isKindOfClass(CustomSubview) {
        subview.gestureRecognizers?.removeAll(keepCapacity: false)
    }
}

Comments

    Ничего не найдено.