Почему бы не создать подкласс UIApplication? Зачем использовать делегат?

Вместо использования делегата приложения, чтобы синглтон UIApplication мог вызывать методы делегата в заранее определенное время, каковы преимущества и недостатки простого создания подкласса UIApplication? (обновление: почему в архитектуре iOS используется делегат приложения вместо того, чтобы позволить людям писать приложение путем создания подкласса UIApplication и переопределения его различных методов?)

Это потому, что когда мы создаем новый элемент управления UIView, мы создаем подкласс UIView (update: или мы также создаем подкласс UIViewController). Так почему же в случае приложения мы не создаем подкласс UIApplication, а вместо этого используем делегирование?


person Jeremy L    schedule 26.05.2012    source источник
comment
Небольшой FYI, вы можете создать подкласс UIApplication и использовать этот подкласс в своем приложении, передав его имя правильному параметру в основной функции.   -  person EmilioPelaez    schedule 26.05.2012


Ответы (6)


Опять же, из документации:

Примечания о подклассах

Вы можете создать подкласс UIApplication, чтобы переопределить sendEvent: или sendAction:to:from:forEvent: для реализации пользовательской диспетчеризации событий и действий. Однако необходимость в расширении этого класса возникает редко; делегат приложения (в большинстве случаев достаточно UIApplicationDelegate. Если вы делаете подкласс UIApplication, будьте очень уверены в том, чего вы пытаетесь достичь с помощью подкласса.

person Kaan Dedeoglu    schedule 26.05.2012

Из справочника по классу UIApplication:

Класс UIApplication обеспечивает централизованный контроль и координацию приложений, работающих на iOS.

Каждое приложение должно иметь ровно один экземпляр UIApplication (или подкласс UIApplication). При запуске приложения вызывается функция UIApplicationMain; помимо других задач, эта функция создает одноэлементный объект UIApplication. После этого вы можете получить доступ к этому объекту, вызвав метод класса sharedApplication.

Итак, что вы подразумеваете под «почему бы нам не создать подкласс UIApplication? Apple даже предоставляет примечания о том, что нужно реализовать в подклассах.

Что касается вашего вопроса о делегировании и использовании singleton вместо стандартных классов, ответ прост: приложение должно предоставлять один общий способ получения и отправки событий (как внешних, так и связанных с системой), обрабатывать многозадачность и свободно взаимодействовать с системой (это почему main.m включает ссылку на делегат вашего приложения).

person CodaFi    schedule 26.05.2012
comment
почему бы нам не создать подкласс UIApplication и не переопределить различные методы для выполнения этих задач? Есть ли преимущества/недостатки? - person Jeremy L; 26.05.2012
comment
Наоборот, яблоко даже рекомендует создать подкласс, хотя немногие делают это, потому что, как сказал @borrrden: для этого нет причин. Для чего вы могли бы создать подкласс? - person CodaFi; 26.05.2012
comment
может быть, я не ясно дал понять... мне было интересно, почему архитектура iOS не создает шаблон, который просто подкласс UIApplication и переопределяет различные методы, а вместо этого использует отдельный делегат приложения... - person Jeremy L; 26.05.2012
comment
Делегат приложения раньше был подклассом UIApplication (до Xcode 4.x), но теперь это подкласс UIResponder, что имеет больше смысла, поскольку UIResponder полностью посвящен событиям. Так что это скорее историческая вещь, чем реальное прикрытие. - person CodaFi; 26.05.2012
comment
@CodaFi По умолчанию AppDelegate раньше был подклассом NSObject, а не подклассом UIApplication. Также у него был протокол UIApplicationDelegate. - person Yoon Lee; 16.03.2017

Причина, по которой разработчики обычно этого не делают, заключается в том, что в этом нет необходимости. UIApplication работает так, как нужно для большинства случаев. Ему просто нужны некоторые подсказки о том, что делать в определенных предопределенных случаях (именно поэтому у него есть делегат). UIView, с другой стороны, очень общий, и я не думаю, что он когда-либо использовался как есть. Это, вероятно, самый настраиваемый класс во всем мире iOS.

person borrrden    schedule 26.05.2012

Делегирование — это основной шаблон проектирования. Это позволяет разделить обязанности между частями вашей программы. Идея состоит в том, что та часть вашей программы, которая, например, рисует на экране, вероятно, не должна общаться с вашей базой данных. На это есть несколько причин:

Производительность: если тот же объект, который рисует на экране, обращается к вашему хранилищу данных, вы столкнетесь с проблемами производительности. Период. Полная остановка.

Сопровождение кода: легче концептуализировать правильно модульный код. (Для меня, во всяком случае)

Гибкость: Если вы создаете подклассы в своем коде, это прекрасно, пока вы не начнете сталкиваться с монолитными классами, которые имеют все виды нежелательного поведения. Вы достигнете точки, когда вам придется перегружать поведение, чтобы отключить вещи, и ваше пространство имен свойств может стать загрязненным. Попробуйте категории, делегирование и блоки для альтернатив.

Тем не менее, я действительно столкнулся с ситуацией, когда подклассы были уместны. У меня есть киоск-приложение, в котором я хотел автоматически закрыть определенное меню настроек, если с ним не взаимодействовали в течение определенного периода времени. Для этого мне нужно было иметь доступ к сенсорным событиям во всем приложении. Я создал подкласс UIApplication и переопределил sendEvent:. Тогда это было уместно, хотя это крайний случай. Как сказал царь Соломон в Екклесиасте, перефразируя: «Всему свое время и место под солнцем».

Чтобы упростить написание, чтение, повторение и поддержку вашей программы, настоятельно рекомендуется следовать определенным правилам. Вы можете создавать подклассы многих классов, и Apple не отклонит ваше приложение из-за плохого кода при условии, что оно работает так, как рекламируется. Тем не менее, если вы не соблюдаете проверенные и проверенные методы, вы копаете себе могилу. Подклассы по своей сути не плохи, но категории, протоколы и блоки настолько увлекательны, что я бы предпочел их в любом случае.

person Moshe    schedule 07.05.2013
comment
Ваш ответ длиннее многих других на StackOverflow и содержит ценную информацию, но я думаю, что в некоторых отношениях он неверен. Например, я не считаю, что в настоящее время производительность является причиной разделения кода пользовательского интерфейса и кода доступа к базе данных. Как вы сказали, разделение и модульность — гораздо лучшая и более рациональная причина. Кроме того, я не думаю, что переопределение метода UIApplications sendEvent:, как вы это сделали, было действительно необходимо. Поскольку это единственный элемент управления, на котором вы сосредоточены, вы могли бы просто создать подкласс этого единственного класса и переопределить «touchesBegan: withEvent:» и т. д. - person return true; 15.07.2016

Есть много специализированных вещей, которые могут потребоваться подклассу UIView. Подумайте об UIScrollView, UIImageView, UIWebView и т. д. и о том, насколько сильно должна отличаться их внутренняя работа. Но, тем не менее, они должны участвовать в иерархии представлений, поэтому создание подклассов имеет смысл.

UIApplication, с другой стороны, является центральным узлом для событий всего приложения, уведомлений, открытия URL-адресов, доступа к окнам и других общих вещей. При нормальных обстоятельствах приложение должно просто знать то, что протокол UIApplicationDelegate предоставит.

Примечание из обзора приложения UIA объясняет одну причину, по которой вы можете создать подкласс UIApplication:

Вы можете создать подкласс UIApplication, чтобы переопределить sendEvent: или sendAction:to:from:forEvent: для реализации пользовательской диспетчеризации событий и действий. Однако необходимость в расширении этого класса возникает редко; делегат приложения (в большинстве случаев достаточно UIApplicationDelegate. Если вы делаете подкласс UIApplication, будьте очень уверены в том, чего вы пытаетесь достичь с помощью подкласса.

Но это должно быть необходимо только в очень особых случаях.

person boxel    schedule 26.05.2012
comment
так что я думаю, вы имеете в виду, что если это довольно пустой класс, такой как UIView, то его подклассы имеют смысл. Но если это очень полностью реализованный класс, такой как UIApplication, все, что нам нужно, это делегат для выполнения определенных действий в заранее определенное время... то есть, если это небольшая неизвестная часть, то использование делегата работает хорошо. - person Jeremy L; 26.05.2012
comment
Я также только что прочитал в книге Cocoa Design Patterns, что может быть лучшая инкапсуляция в UIApplication, если мы используем делегирование, потому что, если мы создадим его подкласс, есть более высокая вероятность того, что мы можем загрязнить UIApplication - person Jeremy L; 26.05.2012

Я добавлю то, что еще никто не упомянул: делегирование устраняет необходимость вызывать super при переопределении/дополнении/добавлении поведения с помощью реализации метода делегата, а не подкласса с переопределенным методом. Я видел, как многие разработчики отвечали на свой собственный вопрос о Stackoverflow, просто забыв называть super (после того, как некоторые даже опубликовали возможные ответы). Более новый декоратор метода NS_REQUIRES_SUPER немного помогает в этом, предупреждая разработчика предупреждением (надеюсь, они его не игнорируют!), однако это не помогает, когда порядок вызова super имеет значение. Я думаю, что Apple решила, что разработчики вместо этого реализуют объект-делегат менее подвержены ошибкам, у которого нет супертребований к вызову, и они даже проделали тяжелую работу по перенаправлению методов UIResponder из UIApplication в объект-делегат.

person malhal    schedule 27.11.2019