Pull to refresh

UIAppearance оказался не так прост

Development for iOSObjective CSwift

Протокол UIAppearance появился в iOS 5 в 2011 году, в те далёкие времена, когда у Instagram не было приложения под Android, а сериальному Неду Старку ещё не отрубили голову.


Насчёт Эддарда

Мейстеры мне прислали ворона с новостью, что на момент выхода iOS 5 — уже отрубили. Но чтобы не спойлерить красную свадьбу или что-то ещё, пожалуй, оставлю всё как есть.


Информации, туториалов, статей на эту тему достаточно, каждый начинающий iOS разработчик знает как и зачем его применять, так что эта статья не об этом. Я бы хотел поразмышлять на тему, что с ним, на мой взгляд, не так, и почему Apple на это не обращает внимания.


В качестве небольшой вводной — выдержки из документации, которая всегда была, есть и должна быть основным доверенным источником информации.


You can customize the appearance of instances of a class by sending appearance modification messages to the class’s appearance proxy.

To support appearance customization, a class must conform to the UIAppearanceContainer protocol and relevant accessor methods must be marked with UI_APPEARANCE_SELECTOR

Для себя я понимаю это так: если хочешь изменить внешний вид по умолчанию для всех объектов класса, реализующего UIAppearance, проверь, помечено ли свойство с помощью UI_APPEARANCE_SELECTOR, и вперёд. Соответственно, если свойство не является UI_APPEARANCE_SELECTOR, то это сделать не получится.


Но "не получится" не значит "нельзя попытаться", поэтому я предлагаю всем любопытным провести простой эксперимент: откройте первый попавшийся проект и добавьте в метод application:didFinishLaunchingWithOptions: следующую строчку:


UIView.appearance().isHidden = true

Прикиньте, что произойдёт, и запустите.


Я, как зануда, ожидал бы возможные варианты:


  • ничего не происходит;
  • ничего не происходит, но в консоль вываливается лог типа "isHidden is not UI_APPEARANCE_SELECTOR, stupid";
  • приложение ловит критическую ошибку или ассерт с подобным сообщением.

Но нет, всё, включая основное окно приложения, становится скрытым. С одной стороны, это даже логично — что написано, то и сделано. Но с другой стороны это выглядит как недокументированное поведение и, как мне кажется, немаленькая такая дыра.


Я ещё мог бы смириться с тем, если бы такие фокусы можно было проворачивать только с теми свойствами, которые влияют на внешний вид, но это можно делать со всеми свойствами!


Например, добавив в код, который используют другие проекты в качестве сторонней библиотеки, вот такую строчку, которая иногда вызывается в рандомный момент времени:


UITableView.appearance().delegate = nil

можно обнулить все делегаты у всех таблиц, которые появятся на экране после выполнения этого кода.


Разработчики получат много удовольствия, пытаться понять, что случилось! Наверняка, можно придумать и что-то ещё более забавное!


Я очень надеюсь, что подобные вещи всё-таки не остались без внимания Apple (информации на эту тему, правда, я не нашёл), и подобные фокусы вскрываются где-нибудь на этапе автоматической проверки сборки в AppstoreConnect. Но проверять, если честно, не хочется.


Такие дела, ребята. Буду рад дискуссии, если тема кому-то тоже интересна.


P. S. Верните мне мой 2011!

Tags:iosuiappearanceuikitswiftobjective-c
Hubs: Development for iOS Objective C Swift
Total votes 10: ↑10 and ↓0+10
Views3.5K
Comments Comments 5

Popular right now