#ios #swift #uitabbarcontroller #uitabbaritem #cgrect
#iOS #swift #uitabbarcontroller #uitabbaritem #cgrect
Вопрос:
У меня есть панель вкладок с 5 элементами. Чтобы получить фрейм первого элемента панели вкладок и установить что-то на основе этого фрейма, я использую это, которое работает отлично:
guard let firstTab = tabBarController?.tabBar.items?[0].value(forKey: "view") as? UIView else { return }
guard let window = UIApplication.shared.windows.filter({$0.isKeyWindow}).first else { return }
let windowRect = lastTab.convert(firstTab.frame, to: window)
print(firstTab) // (2.0, 1.0, 79.00000000298023, 48.0)
print(windowRect) // (4.0, 689.0, 79.00000000298023, 48.0)
Но когда я пытаюсь использовать приведенный выше код, чтобы получить фрейм 5-й вкладки, значения неверны. При настройке tabBar.items?[4]
x
координата кадра находится за пределами экрана на 665 в windowRect:
guard let lastTab = tabBarControlle?.tabBar.items?[4].value(forKey: "view") as? UIView else { return }
guard let window = UIApplication.shared.windows.filter({$0.isKeyWindow}).first else { return }
let windowRect = lastTab.convert(lastTab.frame, to: window)
print(lastTab) // (332.99999999701976, 1.0, 79.00000000298023, 48.0)
print(windowRect) // (665.9999999940395, 689.0, 79.0000000029803, 48.0)
Но при настройке tabBar.items?[2]
я получаю правильную координату x в 336 в windowRect:
// setting the 2nd item gives me the correct frame for the 4th item
guard let lastTab = tabBarControlle?.tabBar.items?[2].value(forKey: "view") as? UIView else { return }
guard let window = UIApplication.shared.windows.filter({$0.isKeyWindow}).first else { return }
let windowRect = lastTab.convert(lastTab.frame, to: window)
print(lastTab) // (168.00000000596046, 1.0, 77.99999998807907, 48.0)
print(windowRect) // (336.0000000119209, 689.0, 77.99999998807908, 48.0)
Почему tabBar.items?[2]
возвращается значение for tabBar.items?[4]
в фрейме окна?
Комментарии:
1. не связано с вашим вопросом, но почему бы и нет просто
windows.first(where: .isKeyWindow)
?2. Когда в XCode 12/13 начало появляться предупреждение, я начал использовать
.filter({..})
, потому что это был первый ответ, который, как я обнаружил, сработал, и я просто никогда не переключался. Я видел.
другой ответ, но к тому времени весь мой код использовался.filter
.3.
filter
будет излишне перебирать всю коллекцию. В этом случае это не имеет значения, потому что окон всего несколько. Убедитесь, что всегда используйтеfirst(where:)
, чтобы он обеспечивал ранний выход при выполнении условия.4. ohhhhhhh, я никогда не знал, узнать что-то новое каждый день. Спасибо за совет. Теперь я собираюсь переключить их все 😊. Если я собираюсь добавить предложение the, я мог бы также использовать более короткий синтаксис
5. О, я понимаю, при каждом появлении количество увеличивается, и как только оно достигает максимального значения, вы нарушаете его. Я думал, у тебя есть другой выход. Я уже пользовался этим раньше. Однако я никогда не использовал его с предложением where .
Ответ №1:
Вы пропустили .superview
.
private func convertTabFrame(for index: Int) -> CGRect? {
guard let window = UIApplication.shared.windows.first(where: {$0.isKeyWindow}) else { return nil }
guard let tabView = self.tabBarController?.tabBar.items?[index].value(forKey: "view") as? UIView else { return nil }
return tabView.superview?.convert(tabView.frame, to: window)
}