Irbisa · Шпаргалка
Основы UIKit
UIView, жизненный цикл UIViewController, иерархия view, обработка касаний
Что такое
UIWindow, с чего начинается иерархия вью и чем окно отличается от обычногоUIView?Расскажите о жизненном цикле
UIViewController: какие колбэки вызываются один раз, а какие при каждом появлении, и где начинать загрузку данных?Что такое
loadView, когда его переопределяют и чем он отличается отviewDidLoad?final class ProfileView: UIView { let nameLabel = UILabel() // builds its own subviews and constraints in init} final class ProfileViewController: UIViewController {…Чем отличаются
frameиboundsи когдаbounds.originне равен нулю?let card = UIView(frame: CGRect(x: 20, y: 100, width: 120, height: 60))// card.frame = (20, 100, 120, 60) in the superview's coordinates// card.bounds = (0, 0, 120, 60) in its own coordinates let dot = UIView(frame: CGRect(x: 10, y: 10, width: 20, height: 20))card.addSubview(dot) // (10, 10) inside card…Каковы плюсы и минусы сторибордов, XIB и вёрстки интерфейса в коде?
Чем отличаются
@IBOutletи@IBActionи как target-action связывает контрол с вашим кодом?final class LoginViewController: UIViewController { @IBOutlet private weak var emailField: UITextField! @IBOutlet private weak var loginButton: UIButton! private let retryButton = UIButton(type: .system) @IBAction private func loginTapped(_ sender: UIButton) {…Как работает
UINavigationControllerи чем push отличается от present?// Push: onto the current navigation stacknavigationController?.pushViewController(DetailViewController(id: id), animated: true)navigationController?.popViewController(animated: true) // Present: modally, with its own navigation barlet editor = UINavigationController(rootViewController: EditorViewController())…Как работает
UITableView: что делают data source и delegate и что такое переиспользование ячеек?final class ContactsViewController: UITableViewController { private var names = ["Alice", "Bob", "Carol"] override func viewDidLoad() { super.viewDidLoad() tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")…Как устроен
UIScrollViewи за что в нём отвечают свойстваcontentSize,contentOffsetиcontentInset?final class FeedViewController: UIViewController, UIScrollViewDelegate { private let scrollView = UIScrollView() private let header = UIView() override func viewDidLoad() { super.viewDidLoad()…Чем отличаются
UIImageиUIImageView, а также.scaleAspectFitи.scaleAspectFill?Как скруглить углы вью и добавить тень и почему они конфликтуют?
final class CardView: UIView { let content = UIView() // inner view: clips to the rounded shape override init(frame: CGRect) { super.init(frame: frame) layer.shadowColor = UIColor.black.cgColor…Этот лейбл обновляется из колбэка
URLSession, и приложение потом падает в случайных местах. Что не так и как это исправить?func loadProfile() { URLSession.shared.dataTask(with: profileURL) { data, _, _ in guard let data else { return } let profile = try? JSONDecoder().decode(Profile.self, from: data) self.nameLabel.text = profile?.name self.view.setNeedsLayout() }.resume()}Как поддержать тёмную тему в UIKit и почему цвет рамки слоя не переключается вместе с ней?
final class BadgeView: UIView { override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .secondarySystemBackground // dynamic: updates itself layer.borderWidth = 1 updateBorder()…Как анимировать вью в UIKit и как анимировать изменение констрейнта Auto Layout?
// Expand a panel by changing its height constraintview.layoutIfNeeded() // settle pending layout firstheightConstraint.constant = isExpanded ? 240 : 88UIView.animate(withDuration: 0.3) { self.view.layoutIfNeeded() // the layout pass is animated}…Что такое
viewIsAppearing(_:)и почему для настройки, зависящей от геометрии, он лучше, чемviewWillAppearилиviewDidLayoutSubviews?final class AgendaViewController: UIViewController { private let tableView = UITableView() private var todayIndexPath = IndexPath(row: 0, section: 0) // wrong: scrolling in viewWillAppear, bounds and traits may be stale override func viewWillAppear(_ animated: Bool) {…Найдите баг: после нескольких заходов на экран корзины одно изменение корзины попадает в аналитику несколько раз.
final class CartViewController: UIViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) NotificationCenter.default.addObserver( self, selector: #selector(cartDidChange), name: .cartDidChange, object: nil) reloadBadge() } @objc private func cartDidChange() { reloadBadge() analytics.log("cart_changed") }}Как передать данные вперёд, в следующий view controller, и назад, в предыдущий?
struct Item { var title: String } final class EditViewController: UIViewController { private var item: Item var onSave: ((Item) -> Void)? // back: a callback the parent sets…Что такое containment view controller'ов и какие вызовы нужны, чтобы добавить и убрать дочерний контроллер?
extension UIViewController { func embed(_ child: UIViewController, in container: UIView) { addChild(child) // 1. relationship child.view.translatesAutoresizingMaskIntoConstraints = false container.addSubview(child.view) // 2. view NSLayoutConstraint.activate([…Что такое responder chain и как
hitTest(_:with:)определяет, какая вью получит касание?// Enlarge a small button's tap area without changing its sizefinal class BigTapButton: UIButton { override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { bounds.insetBy(dx: -12, dy: -12).contains(point) }}…Как работают gesture recognizers и как сделать, чтобы одиночный тап ждал двойной, а pan работал вместе со scroll view?
final class CardViewController: UIViewController, UIGestureRecognizerDelegate { private let scrollView = UIScrollView() private let card = UIView() private var dragStart: CGPoint = .zero override func viewDidLoad() { super.viewDidLoad()…Чем отличаются
UIViewиCALayerи когда работают со слоем напрямую?final class GradientView: UIView { // The backing layer itself is a gradient: no frame syncing needed override class var layerClass: AnyClass { CAGradientLayer.self } private var gradient: CAGradientLayer { layer as! CAGradientLayer } override init(frame: CGRect) {…Чем отличаются
setNeedsLayoutиsetNeedsDisplayи когда вызываетсяdraw(_:)?final class ProgressRingView: UIView { var progress: CGFloat = 0 { didSet { setNeedsDisplay() } // content changed: redraw once } override init(frame: CGRect) {…Как работает главный run loop и почему
Timerперестаёт срабатывать, пока пользователь скроллит?// wrong: scheduledTimer registers for .default only, so it pauses while scrolling// Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in ... } // right: register for .common, which includes .tracking// tick() is a method of the owning controllerlet countdown = Timer(timeInterval: 1, repeats: true) { [weak self] _ in…Этот контроллер закрывают через 3 секунды после открытия. Что напечатается, когда и есть ли здесь утечка памяти?
final class DetailViewController: UIViewController { private let statusLabel = UILabel() override func viewDidLoad() { super.viewDidLoad() DispatchQueue.main.asyncAfter(deadline: .now() + 5) { self.statusLabel.text = "Loaded" print("closure ran") } } deinit { print("deinit") }}Найдите баг: при быстром скролле в строках на мгновение появляется аватар другого пользователя, а иногда чужой так и остаётся.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Avatar", for: indexPath) as! AvatarCell let user = users[indexPath.row] cell.nameLabel.text = user.name Task { let image = await imageLoader.image(for: user.avatarURL) cell.avatarView.image = image } return cell}