Ответ
Технически возможно, но крайне непрактично. CALayer — это низкоуровневый объект отрисовки без обработки событий и управления жизненным циклом.
Ограничения использования только CALayer:
- Нет обработки событий — слои не обрабатывают тапы, свайпы, жесты
- Нет автоматического управления памятью — нужно вручную контролировать retain cycles
- Нет готовых UI-компонентов — кнопки, текстовые поля, таблицы отсутствуют
- Сложная анимация — отсутствуют удобные методы анимации UIView
Базовый пример создания слоя:
class LayerOnlyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Создание и настройка слоя
let customLayer = CALayer()
customLayer.frame = CGRect(x: 50, y: 100, width: 200, height: 150)
customLayer.backgroundColor = UIColor.systemBlue.cgColor
customLayer.cornerRadius = 12
customLayer.borderWidth = 2
customLayer.borderColor = UIColor.white.cgColor
// Добавление на экран
view.layer.addSublayer(customLayer)
// Проблема: нет обработки тапов на этот слой
// Решение: добавляем gesture recognizer на view
let tapRecognizer = UITapGestureRecognizer(target: self,
action: #selector(handleTap))
view.addGestureRecognizer(tapRecognizer)
}
@objc func handleTap(_ recognizer: UITapGestureRecognizer) {
let point = recognizer.location(in: view)
// Вручную проверяем hit test для каждого слоя
if let hitLayer = view.layer.hitTest(point) {
print("Tapped layer: (hitLayer)")
}
}
}
Практическая рекомендация:
Используйте UIView как контейнер для CALayer. UIView предоставляет:
- Автоматическое создание и управление backing layer
- Систему responder chain для обработки событий
- Удобные методы анимации (
UIView.animate) - Автоматическое обновление layout при изменении bounds
Гибридный подход (рекомендуется):
class CustomView: UIView {
override class var layerClass: AnyClass {
return CAShapeLayer.self // Кастомный тип слоя
}
override func layoutSubviews() {
super.layoutSubviews()
// Настройка кастомного слоя
if let shapeLayer = layer as? CAShapeLayer {
shapeLayer.path = UIBezierPath(roundedRect: bounds,
cornerRadius: 10).cgPath
}
}
}