Как привести массив UIViewControllers к массиву типов протоколов
У меня есть UITabBarController
, чьи viewControllers
все реализуют протокол Refreshable
. Почему я не могу развернуть свойство контроллера панели вкладок viewControllers
в массив типа Refreshable
?
if let tabs = self.tabBarController.viewControllers as? [Refreshable] {
// Some code
tabs[0].refresh() // refresh() is a function in Refreshable
}
Ошибок компиляции нет, но код внутри закрытия if let
никогда не выполняется. Как я могу сделать это правильно?
добавить:
Это работает, но мне это не нравится-я чувствую, что должен быть в состоянии выразить это, как описано выше.if let tabs = self.tabBarController.viewControllers as? [UIViewController] {
if tabs[0] is Refreshable {
(tabs[0] as! Refreshable).refresh()
}
}
3 ответа:
Если Ваш массив
Другими словами,[UIViewController]
, он не будет принимать элементы с типомRefreshable
, так как ему могут соответствовать другие произвольные классы, которые не имеют свойствUIViewController
.Refreshable
Сам по себе не является достаточно сильным обещанием для вашего массива, поскольку он не гарантирует экземплярыUIViewController
.Исходное выражение будет работать только с массивом, где тип определяется типом протокола следующим образом:
// Suppose MyClass conforms to Refreshable let myArray: [Refreshable] = [ MyClass(), MyClass(), MyClass(), MyClass(), ] // Now you can use refresh() without problems for item in myArray { item.refresh() }
К сожалению, поскольку вы используете свойство на контроллер панели вкладок, я боюсь, что это не вариант для вас. Возможный способ убедиться, что вы используете только экземпляры, соответствующие
Refreshable
, - это сначала отфильтровать / отобразить Ваш массив следующим образом:Здесь важно отметить, что если вы используете так какlet items = myarray.filter({ $0 is Refreshable }).map({ return $0 as! Refreshable }) // items will be [Refreshable] for item in items { item.refresh() }
items
будет иметь тип[Refreshable]
, вы больше не можете предполагать, что он имеет свойства из своего исходного класса (т. е.MyClass
), только те, которые предоставляет им протокол (т. е.refresh()
в этом случае).
Свойство
viewControllers
в контроллере панели вкладок объявляется как[AnyObject]?
.. так что проверка типаas? [Refreshable]
не проходит. вместо этого пройдите через контроллеры вида и проверьте тип для каждого из них:for viewController in self.tabBarController!.viewControllers! { if let refreshableTab = viewController as? Refreshable { refreshableTab.refresh() } }