Вопрос по ios, objective-c – Когда использовать ленивый экземпляр в iOS?

26

Я слышал, что ленивое создание объектов в iOS довольно распространено, однако я не совсем уверен, когда мне следует его использовать? Может ли кто-нибудь дать краткое объяснение того, когда я должен использовать ленивый экземпляр и когда мне просто нужно инициализировать свои свойства в методе init?

Меня беспокоит ленивое создание экземпляров, поскольку для этого требуется много кода (по сравнению с простым написанием всего этого в методе init), особенно если у вас есть несколько свойств для инициализации.

Читайте второй комментарий, все о памяти и производительности ymutlu
Как это требует много кода по сравнению с этим в init? Как правило, это не добавляет гораздо больше, чем просто делать вещи в init Paul.s
@ ymutlu Можете ли вы объяснить, почему это не имеет смысла в маленьких проектах и с новыми устройствами? Paul.s
Это не имеет смысла в маленьких проектах и с новыми устройствами. Если вы беспокоитесь о памяти, вы должны использовать ленивый экземпляр. ymutlu
@ ymutlu Не согласен, все дело в памяти и производительности. Если объект сложен в настройке, и он будет настроен только один раз, я бы предпочел перенести его в геттер, используя ленивую реализацию, чем иметь много кода в init, который просто загромождает поток. Paul.s

Ваш Ответ

4   ответа
18

если у вас есть объект, который нужно настроить только один раз, и в нем есть какая-то конфигурация, которую вы не хотите загромождать своим методом init.

- (UIView *)myRoundedView;
{
    if (!_myRoundedView) {
        _myRoundedView = [[UIView alloc] initWithFrame:<#some frame#>];
        _myRoundedView.layer.cornerRadius = 10.f;
        _myRoundedView.backgroundColor    = [UIColor colorWithWhite:0.f alpha:0.6f];
        _myRoundedView.autoresizingMask   = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    }
    return _myRoundedView;
}

Это довольно надуманный пример, но вы можете начать видеть достоинства. Методы должны быть похожи на классы и делать одну вещь хорошо. Этот метод возвращает округленный вид, который я хочу. Если бы я добавил этот код в метод init, то теперь метод init должен был бы знать мельчайшие подробности того, как создать и настроить это представление и любые другие объекты, которые я добавлю туда.

13

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

Однако ясно, что если все объекты нуждаются в инициализации после или сразу после инициализации объекта-контейнера, ленивая инициализация не имеет никакого смысла, и следует использовать стандартную инициализацию конструктора.

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

11

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

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

3

проверьте это, вот еще один пример:

- (NSArray *)validElements{
    if (!_validElements) {
        _validElements = [[NSArray alloc] initWithObjects:
                          @"mystuff",@"generaldescription",@"title",@"autor",
                          @"version",@"date",@"context",@"operatingsystem",@"kindofdevice",
                          @"deviceversion",@"rule",@"daytime",@"time",@"location",@"deviceheading",
                          @"region",@"language",nil];
    }
    return _validElements;
}

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

Похожие вопросы