Какие рекомендации вы используете при написании Objective-C и Cocoa?[закрыто]

StackOverflow https://stackoverflow.com/questions/155964

Вопрос

Я знаю о Привет (что довольно удобно!), Но какие методы программирования вы используете при написании Objective-C, и, более конкретно, при использовании Cocoa (или CocoaTouch).

Это было полезно?

Решение

Есть несколько вещей, которые я начал делать и которые, на мой взгляд, не являются стандартными:

1) С появлением свойств я больше не использую "_" для префикса "частных" переменных класса.В конце концов, если к переменной могут получить доступ другие классы, разве для нее не должно быть свойства?Мне всегда не нравился префикс "_" за то, что он делал код уродливее, и теперь я могу его опустить.

2) Говоря о частных вещах, я предпочитаю размещать определения частных методов внутри файла .m в расширении класса следующим образом:

#import "MyClass.h"

@interface MyClass ()
- (void) someMethod;
- (void) someOtherMethod;
@end

@implementation MyClass

Зачем загромождать файл .h вещами, которые не должны волновать посторонних?Функция empty () работает для закрытых категорий в файле .m и выдает предупреждения о компиляции, если вы не реализуете объявленные методы.

3) Я решил поместить dealloc в начало файла .m, чуть ниже директив @synthesize .Разве то, что вы освобождаете, не должно быть в верхней части списка вещей, о которых вы хотите подумать на занятии?Это особенно верно в такой среде, как iPhone.

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

3.6) При использовании NSURLConnection, как правило, вы вполне можете захотеть реализовать метод делегирования:

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
                  willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
      return nil;
}

Я нахожу, что большинство веб-вызовов очень необычны, и это скорее исключение, чем правило, по которому вы хотите кэшировать ответы, особенно для вызовов веб-служб.Реализация метода, как показано, отключает кэширование ответов.

Также представляют интерес несколько полезных советов, касающихся iPhone, от Джозефа Маттиелло (получено в списке рассылки iPhone).Есть и другие, но они были наиболее полезными, на мой взгляд (обратите внимание, что несколько фрагментов были слегка отредактированы по сравнению с оригиналом, чтобы включить детали, предложенные в ответах):

4) Используйте двойную точность только в случае необходимости, например, при работе с CoreLocation.Убедитесь, что вы заканчиваете свои константы на "f", чтобы gcc сохранял их как значения с плавающей точкой.

float val = someFloat * 2.2f;

Это особенно важно, когда someFloat на самом деле может быть double, вам не нужна математика смешанного режима, так как вы теряете точность в 'val' при хранении.Хотя числа с плавающей запятой поддерживаются аппаратно на iPhone, выполнение арифметики двойной точности все равно может занять больше времени, в отличие от одинарной точности.Ссылки:

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

5) Установите ваши свойства следующим образом nonatomic.Они atomic по умолчанию и после синтеза будет создан семафорный код для предотвращения проблем с многопоточностью.99% из вас, вероятно, не нужно беспокоиться об этом, и код намного менее раздут и более эффективен при использовании памяти, когда установлено значение nonatomic.

6) SQLite может быть очень, очень быстрым способом кэширования больших наборов данных.Например, картографическое приложение может кэшировать свои фрагменты в файлах SQLite.Самая дорогая часть - это дисковый ввод-вывод.Избегайте большого количества небольших записей, отправляя BEGIN; и COMMIT; между большими блоками.Например, мы используем 2-секундный таймер, который сбрасывается при каждой новой отправке.Когда срок его действия истекает, мы отправляем КОММИТ;, что приводит к тому, что все ваши записи собираются в один большой фрагмент.SQLite сохраняет данные транзакции на диске, и выполнение этого переноса начала / окончания позволяет избежать создания множества файлов транзакций, группируя все транзакции в один файл.

Кроме того, SQL заблокирует ваш графический интерфейс, если он находится в вашем основном потоке.Если у вас очень длинный запрос, рекомендуется хранить ваши запросы как статические объекты и запускать ваш SQL в отдельном потоке.Обязательно перенесите все, что изменяет базу данных для строк запроса, в @synchronize() {} блоки.Для коротких запросов просто оставляйте данные в основном потоке для большего удобства.

Дополнительные советы по оптимизации SQLite приведены здесь, хотя документ выглядит устаревшим, многие пункты, вероятно, все еще хороши;

http://web.utk.edu /~jplyon/sqlite/SQLite_optimization_FAQ.html

Другие советы

Не используйте неизвестные строки в качестве строк формата

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

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

    NSString *aString = // get a string from somewhere;
    NSLog(aString);

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

    NSLog(@"%@", aString);

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

Примеры того, что делать и чего не делать:

  • Не объявляйте id m_something; в интерфейсе объекта и назовите его переменная-член или поле;использование something или _something за его название и назовите его переменная экземпляра.
  • Не называйте имя добытчика -getSomething;правильное название какао - это просто -something.
  • Не называйте сеттера по имени -something:;это должно быть -setSomething:
  • Имя метода перемежается с аргументами и содержит двоеточия;это -[NSObject performSelector:withObject:], не NSObject::performSelector.
  • Используйте заглавные буквы (camelCase) в именах методов, параметрах, переменных, именах классов и т.д.вместо нижних строк (подчеркиваний).
  • Имена классов начинаются с заглавной буквы, имена переменных и методов - со строчной.

Что бы ты еще ни делал, не надо используйте венгерскую нотацию в стиле Win16 / Win32.Даже Microsoft отказалась от этого с переходом на платформу .NET.

Бутлеты

Исторически сложилось так, что управление памятью торговых точек было плохим.В настоящее время наилучшей практикой является объявление торговых точек как свойств:

@interface MyClass :NSObject {
    NSTextField *textField;
}
@property (nonatomic, retain) IBOutlet NSTextField *textField;
@end

Использование свойств проясняет семантику управления памятью;это также обеспечивает согласованный шаблон, если вы используете синтез переменных экземпляра.

Используйте статический анализатор LLVM /Clang

ПРИМЕЧАНИЕ:В Xcode 4 это теперь встроено в IDE.

Вы используете Статический анализатор Лязга чтобы - что неудивительно - проанализировать ваш код на C и Objective-C (пока без C ++) в Mac OS X 10.5.Его легко установить и использовать:

  1. Загрузите последнюю версию с сайта эта страница.
  2. Из командной строки, cd в каталог вашего проекта.
  3. Выполнить scan-build -k -V xcodebuild.

(Существуют некоторые дополнительные ограничения и т.д., в частности, вы должны проанализировать проект в его конфигурации "Debug" - см. http://clang.llvm.org/StaticAnalysisUsage.html для деталей - но это более или менее то, к чему все сводится.)

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

Это тонкий, но удобный способ.Если вы передаете себя в качестве делегата другому объекту, сбросьте делегат этого объекта перед собой dealloc.

- (void)dealloc
{
self.someObject.delegate = NULL;
self.someObject = NULL;
//
[super dealloc];
}

Делая это, вы гарантируете, что больше никакие методы делегирования не будут отправлены.Как ты и собирался dealloc и растворитесь в эфире, который вы хотите использовать, чтобы убедиться, что ничто больше не сможет случайно отправлять вам сообщения.Помните self.SomeObject может быть сохранен другим объектом (это может быть синглтон или пул авторелиза или что-то еще), и пока вы не скажете ему "прекратите отправлять мне сообщения!", он думает, что ваш объект, который вот-вот будет освобожден, является честной игрой.

Выработка этой привычки избавит вас от множества странных сбоев, отлаживать которые очень сложно.

Тот же принцип применим и к наблюдению за значением ключа, а также к NSNotifications.

Редактировать:

Еще больше защищаясь, меняйтесь:

self.someObject.delegate = NULL;

в:

if (self.someObject.delegate == self)
    self.someObject.delegate = NULL;

@кенделл

Вместо того, чтобы:

@interface MyClass (private)
- (void) someMethod
- (void) someOtherMethod
@end

Использование:

@interface MyClass ()
- (void) someMethod
- (void) someOtherMethod
@end

Новое в Objective-C 2.0.

Расширения классов описаны в справочнике Apple Objective-C 2.0.

"Расширения класса позволяют вам объявлять дополнительный требуемый API для класса в местах, отличных от основного блока class @interface"

Таким образом, они являются частью фактического класса, а Не (частной) категорией в дополнение к классу.Тонкое, но важное различие.

Избегайте авторелиза

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

Таким образом, вместо того, чтобы:

aVariable = [AClass convenienceMethod];

там, где это возможно, вам следует вместо этого использовать:

aVariable = [[AClass alloc] init];
// do things with aVariable
[aVariable release];

Когда вы пишете свои собственные методы, возвращающие вновь созданный объект, вы можете воспользоваться преимуществами Соглашение об именовании Cocoa указать получателю, что он должен быть освобожден, добавив перед именем метода "new".

Таким образом, вместо:

- (MyClass *)convenienceMethod {
    MyClass *instance = [[[self alloc] init] autorelease];
    // configure instance
    return instance;
}

вы могли бы написать:

- (MyClass *)newInstance {
    MyClass *instance = [[self alloc] init];
    // configure instance
    return instance;
}

Поскольку имя метода начинается с "new", потребители вашего API знают, что они несут ответственность за освобождение полученного объекта (см., например, NSObjectController - это newObject способ).

(1) Вы можете взять управление на себя, используя свои собственные локальные пулы авторелиза.Подробнее об этом читайте в разделе Пулы автоматического выпуска.

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

  • Следуйте правилам именования KVO. Даже если вы не используете KVO сейчас, по моему опыту, часто это все равно полезно в будущем.И если вы используете KVO или привязки, вам нужно знать, что все будет работать так, как должно.Это касается не только методов доступа и переменных экземпляра, но и связей "ко многим", проверки, зависимых ключей с автоматическим уведомлением и так далее.
  • Поместите частные методы в категорию. Не только интерфейс, но и реализация.Хорошо иметь некоторую дистанцию концептуально между частными и непубличными методами.Я включаю все в свой файл .m.
  • Поместите методы фонового потока в категорию. То же, что и выше.Я обнаружил, что полезно сохранять четкий концептуальный барьер, когда вы думаете о том, что есть в основном потоке, а что нет.
  • Использование #pragma mark [section]. Обычно я группирую по своим собственным методам, переопределениям каждого подкласса и любой информации или формальным протоколам.Это намного облегчает переход именно к тому, что я ищу.По той же теме сгруппируйте похожие методы (например, методы делегирования в табличном представлении) вместе, а не просто вставляйте их куда попало.
  • Префикс частных методов и ivars с помощью _. Мне нравится, как это выглядит, и я с меньшей вероятностью использую ivar, когда случайно имею в виду свойство.
  • Не используйте методы / свойства мутатора в init & dealloc. У меня никогда не случалось из-за этого ничего плохого, но я вижу логику, если вы измените метод, чтобы сделать что-то, что зависит от состояния вашего объекта.
  • Поместите IBOutlets в свойства. На самом деле я только что прочитал это здесь, но собираюсь начать это делать.Независимо от каких-либо преимуществ для памяти, это кажется лучше стилистически (по крайней мере, мне).
  • Избегайте написания кода, который вам абсолютно не нужен. Это действительно охватывает множество вещей, например, создание ивара, когда #define будет делать, или кэшировать массив вместо того, чтобы сортировать его каждый раз, когда требуются данные.Я многое мог бы сказать по этому поводу, но суть в том, что не пишите код, пока он вам не понадобится или пока профилировщик не скажет вам об этом.Это намного упрощает обслуживание в долгосрочной перспективе.
  • Закончи то, что ты начал. Наличие большого количества незаконченного кода с ошибками - это самый быстрый способ заглушить проект.Если вам нужен метод заглушки, который подойдет, просто укажите его, поставив NSLog( @"stub" ) внутри, или как бы вы ни хотели следить за происходящим.

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

У вас также нет public vs.защищенный противвидимость частного метода мешает писать тесты для ваших внутренних компонентов.

Золотое Правило:Если вы alloc тогда ты release!

Обновить:Если только вы не используете ARC

Не пишите Objective-C так, как если бы это была Java / C # / C ++ / etc.

Однажды я видел, как команда, привыкшая писать веб-приложения на Java EE, пыталась написать настольное приложение Cocoa.Как если бы это было веб-приложение Java EE.Было много AbstractFooFactory, FooFactory, IFoo и Foo, летающих повсюду, когда все, что им действительно было нужно, - это класс Foo и, возможно, Fooable протокол.

Частью гарантии того, что вы этого не сделаете, является истинное понимание различий в языке.Например, вам не нужны абстрактные factory и классы factory выше, потому что методы класса Objective-C отправляются так же динамически, как и методы экземпляра, и могут быть переопределены в подклассах.

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

Например, он расскажет вам, как найти метод, при котором вы сначала выделили память, который позже вызывает сбои (например, при завершении работы приложения).

Сортируйте строки по желанию пользователя

Когда вы сортируете строки для представления пользователю, вы не должны использовать простой compare: способ.Вместо этого вы всегда должны использовать локализованные методы сравнения, такие как localizedCompare: или localizedCaseInsensitiveCompare:.

Для получения более подробной информации см. Поиск, сравнение и сортировка строк.

Старайтесь избегать того, что я теперь решил назвать гоголизмом новой категории.Когда новички в Objective-C обнаруживают категории, они часто сходят с ума, добавляя полезные маленькие категории к каждому существующему классу ("Что?я могу добавить метод преобразования числа в римские цифры в NSNumber rock on!").

Не делай этого.

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

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

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

ОК.Теперь, когда вы получили предупреждение, не обращайте внимания на "не выполняйте эту часть".Но проявляйте крайнюю сдержанность.

Сопротивляйтесь разделению мира на подклассы.В Cocoa многое делается с помощью делегирования и использования базовой среды выполнения, что в других фреймворках делается с помощью подклассов.

Например, в Java вы используете экземпляры anonymous *Listener подклассов много, и в .NET вы используете свой EventArgs подклассов очень много.В Cocoa вы не делаете ни того, ни другого — вместо этого используется целевое действие.

Заявленные свойства

Обычно вам следует использовать функцию объявленных свойств Objective-C 2.0 для всех ваших свойств.Если они не являются общедоступными, добавьте их в расширение класса.Использование объявленных свойств сразу проясняет семантику управления памятью и упрощает проверку вашего метода dealloc - если вы сгруппируете объявления ваших свойств вместе, вы сможете быстро просмотреть их и сравнить с реализацией вашего метода dealloc.

Вам следует хорошенько подумать, прежде чем не помечать свойства как "неатомные".Как Руководство по языку программирования Objective C примечания, свойства по умолчанию являются атомарными и сопряжены со значительными накладными расходами.Более того, простое придание всем вашим свойствам атомарного характера не делает ваше приложение потокобезопасным.Также обратите внимание, конечно, что если вы не укажете "неатомный" и реализуете свои собственные методы доступа (а не синтезируете их), вы должны реализовать их атомарным способом.

Подумайте о нулевых значениях

Как этот вопрос заметки, сообщения для nil действительны в Objective-C.Хотя это часто является преимуществом, приводящим к более чистому и естественному коду, иногда эта функция может приводить к специфическим и трудноотслеживаемым ошибкам, если вы получаете nil цените, когда вы этого не ожидали.

Используйте NSAssert и друзей.Я постоянно использую nil в качестве допустимого объекта ...особенно отправка сообщений в nil совершенно допустима в Obj-C.Однако, если я действительно хочу убедиться в состоянии переменной, я использую NSAssert и NSParameterAssert, которые помогают легко отслеживать проблемы.

Простой, но часто забываемый.В соответствии со спецификацией:

Как правило, методы в разных классах, которые имеют одинаковый селектор (одинаковое имя), также должны совместно использовать одинаковые типы возвращаемых значений и аргументов.Это ограничение накладывается компилятором для обеспечения динамической привязки.

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

@interface FooInt:NSObject{}
-(int) print;
@end

@implementation FooInt
-(int) print{
    return 5;
}
@end

@interface FooFloat:NSObject{}
-(float) print;
@end

@implementation FooFloat
-(float) print{
    return 3.3;
}
@end

int main (int argc, const char * argv[]) {

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];    
    id f1=[[FooFloat alloc]init];
    //prints 0, runtime considers [f1 print] to return int, as f1's type is "id" and FooInt precedes FooBar
    NSLog(@"%f",[f1 print]);

    FooFloat* f2=[[FooFloat alloc]init];
    //prints 3.3 expectedly as the static type is FooFloat
    NSLog(@"%f",[f2 print]);

    [f1 release];
    [f2 release]
    [pool drain];

    return 0;
}   

Если вы используете Leopard (Mac OS X 10.5) или более позднюю версию, вы можете использовать приложение Instruments для поиска и отслеживания утечек памяти.После сборки вашей программы в Xcode выберите Выполнить > Запустить с помощью Performance Tool > Утечки.

Даже если ваше приложение не обнаруживает никаких утечек, возможно, вы храните объекты слишком долго.В инструментах вы можете использовать для этого инструмент ObjectAlloc .Выберите инструмент ObjectAlloc в вашем документе Instruments и отобразите подробную информацию об инструменте (если она еще не отображается), выбрав View > Detail (рядом с ним должна быть галочка).В разделе "Продолжительность выделения" в разделе ObjectAlloc details убедитесь, что вы выбрали переключатель рядом с надписью "Создано и все еще работает".

Теперь всякий раз, когда вы прекращаете запись своего приложения, выбор инструмента ObjectAlloc покажет вам, сколько ссылок имеется на каждый еще существующий объект в вашем приложении в столбце "# Net".Убедитесь, что вы просматриваете не только свои собственные классы, но и классы объектов верхнего уровня ваших файлов NIB.Например, если у вас нет окон на экране, и вы видите ссылки на все еще работающий NSWindow, возможно, вы не выпустили его в своем коде.

Очистите в dealloc.

Это одна из самых простых вещей, которую можно забыть, особенно.при кодировании на скорости 150 миль в час.Всегда, всегда, всегда очищайте свои атрибуты / переменные-члены в dealloc.

Мне нравится использовать атрибуты Objc 2 - с новая точечная нотация - таким образом, это делает очистку безболезненной.Часто так же просто, как:

- (void)dealloc
{
    self.someAttribute = NULL;
    [super dealloc];
}

Это позаботится о выпуске для вас и установит атрибуту значение NULL (что я считаю защитным программированием - на случай, если другой метод, расположенный дальше в dealloc, снова обратится к переменной-члену - редко, но мог бы случиться).

С включенным GC в версии 10.5 это больше не требуется, но вам все равно может понадобиться очистить другие ресурсы, которые вы создаете, вы можете сделать это в методе finalize.

Все эти комментарии замечательны, но я действительно удивлен, что никто не упомянул об этом Руководство по стилю Objective-C от Google это было опубликовано некоторое время назад.Я думаю, что они проделали очень тщательную работу.

Кроме того, частично связанная тема (с возможностью получения дополнительных ответов!):

Какие маленькие советы и хитрости по Xcode вы хотели бы знать около 2 лет назад?.

Не забывайте, что NSWindowController и NSViewController освободят объекты верхнего уровня файлов NIB, которыми они управляют.

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

Один довольно очевидный для новичка в использовании:используйте функцию автоматического отступа Xcode для своего кода.Даже если вы копируете / вставляете из другого источника, после того как вы вставили код, вы можете выбрать весь блок кода, щелкнуть по нему правой кнопкой мыши, а затем выбрать опцию для изменения отступа всего внутри этого блока.

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

Я знаю, что упустил это из виду, когда впервые занялся программированием Cocoa.

Убедитесь, что вы понимаете обязанности по управлению памятью в отношении файлов NIB.Вы несете ответственность за освобождение объектов верхнего уровня в любом загружаемом вами файле NIB.Читать Документация Apple по этому вопросу.

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

Также часто запускайте статический анализ Clang;вы можете включить его для всех сборок с помощью настройки сборки "Запустить статический анализатор".

Пишите модульные тесты и запускайте их при каждой сборке.

Переменные и свойства

1/ Поддержание чистоты ваших заголовков, скрытие реализации
Не включайте переменные экземпляра в свой заголовок.Частные переменные помещаются в продолжение класса как свойства.Общедоступные переменные объявляются как общедоступные свойства в вашем заголовке.Если он должен быть доступен только для чтения, объявите его как доступный только для чтения и перезапишите как readwrite в продолжении класса.По сути, я вообще не использую переменные, только свойства.

2/ Дайте вашим свойствам имя переменной, отличное от значения по умолчанию, например:


@synthesize property = property_;

Причина 1:Вы будете обнаруживать ошибки, вызванные забыванием слова "self". при назначении свойства.Причина 2:Судя по моим экспериментам, анализатор утечек в Instruments испытывает проблемы с обнаружением свойства утечки с именем по умолчанию.

3/ Никогда не используйте "Сохранить" или "освободить" непосредственно для свойств (или только в очень исключительных ситуациях).В вашем dealloc просто присвоите им значение nil.Свойства сохранения предназначены для обработки сохранения / высвобождения сами по себе.Вы никогда не знаете, не добавляет ли установщик, например, или не удаляет наблюдателей.Вы должны использовать переменную непосредственно только внутри ее установщика и получателя.

Число просмотров

1 / Поместите каждое определение вида в xib, если сможете (исключение обычно составляют настройки динамического содержимого и слоя).Это экономит время (это проще, чем писать код), его легко изменять и он сохраняет ваш код чистым.

2 / Не пытайтесь оптимизировать просмотры за счет уменьшения количества просмотров.Не создавайте UIImageView в своем коде вместо xib только потому, что вы хотите добавить в него подвиды.Вместо этого используйте UIImageView в качестве фона.Платформа просмотра может обрабатывать сотни просмотров без проблем.

3 / IBOutlets не обязательно всегда сохранять (или усиливать).Обратите внимание, что большинство ваших IBOutlets являются частью вашей иерархии представлений и, следовательно, неявно сохраняются.

4/ Выпустите все IBOutlets в viewDidUnload

5/ Вызовите viewDidUnload из вашего метода dealloc.Он не вызывается неявно.

Память

1/ Авторелиз объектов при их создании.Многие ошибки возникают из-за перемещения вашего вызова release в одну ветвь if-else или после инструкции return.Release вместо autorelease следует использовать только в исключительных ситуациях - напримеркогда вы ждете цикла выполнения и не хотите, чтобы ваш объект был автоматически выпущен слишком рано.

2 / Даже если вы используете автоматический подсчет ссылок, вы должны прекрасно понимать, как работают методы сохранения-выпуска.Использование retain-release вручную не сложнее, чем ARC, в обоих случаях вам нужно учитывать утечки и циклы сохранения.Рассмотрите возможность использования функции retain-release вручную в больших проектах или сложных иерархиях объектов.

Комментарии

1 / Сделайте ваш код автодокументированным.Каждое имя переменной и метода должно указывать, что оно делает.Если код написан правильно (в этом вам понадобится много практики), вам не понадобятся никакие комментарии к коду (не то же самое, что комментарии к документации).Алгоритмы могут быть сложными, но код всегда должен быть простым.

2 / Иногда вам понадобится комментарий.Обычно для описания неочевидного поведения кода или взлома.Если вы чувствуете, что должны написать комментарий, сначала попробуйте переписать код, чтобы он был проще и без необходимости комментариев.

Отступ

1 / Не увеличивайте отступ слишком сильно.Большая часть кода вашего метода должна иметь отступы на уровне метода.Вложенные блоки (if, for и т.д.) Снижают читабельность.Если у вас есть три вложенных блока, вам следует попробовать поместить внутренние блоки в отдельный метод.Никогда не следует использовать четыре или более вложенных блока.Если большая часть кода вашего метода находится внутри if, отмените условие if, пример:


if (self) {
   //... long initialization code ...
}

return self;


if (!self) {
   return nil;
}

//... long initialization code ...

return self;

Разбираться в коде на языке Си, в основном в структурах на языке Си

Обратите внимание, что Obj-C - это всего лишь легкий слой ООП поверх языка C.Вы должны понимать, как работают базовые структуры кода на C (перечисления, структуры, массивы, указатели и т.д.).Пример:


view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, view.frame.size.height + 20);

это то же самое , что:


CGRect frame = view.frame;
frame.size.height += 20;
view.frame = frame;

И многое другое

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

В настоящее время наши стандарты кодирования содержат около 20 страниц, смесь стандартов кодирования Java, стандартов Google Obj-C / C ++ и наших собственных дополнений.Документируйте свой код, используйте стандартные отступы, пробелы и незаполненные строки в нужных местах и т.д.

Быть более функциональный.

Objective-C является объектно-ориентированным языком, но Cocoa framework поддерживает функциональный стиль и во многих случаях разработан в функциональном стиле.

  1. Существует разделение изменчивости.Использование неизменяемый классы как первичные, а изменяемый объект как вторичный.Например, используйте NSArray в первую очередь и используйте NSMutableArray только тогда, когда вам нужно.

  2. Есть чистые функции.Не так уж много, но многие API фреймворка разработаны как чистые функции.Посмотрите на такие функции, как CGRectMake() или CGAffineTransformMake().Очевидно, что форма указателя выглядит более эффективной.Однако косвенный аргумент с указателями не может обеспечить отсутствие побочных эффектов.Проектируйте структуры настолько чисто, насколько это возможно.Разделите объекты четного состояния.Использование -copy вместо того, чтобы -retain при передаче значения другому объекту.Потому что общее состояние может незаметно влиять на изменение значения в другом объекте.Так что не может быть без побочных эффектов.Если у вас есть значение из внешнего объекта from, скопируйте его.Поэтому также важно спроектировать общее состояние как можно более минимальным.

Однако не бойтесь использовать и нечистые функции.

  1. Существует ленивая оценка.Видите что-то вроде -[UIViewController view] собственность.Представление не будет создано при создании объекта.Он будет создан при чтении вызывающего абонента view собственность в первый раз. UIImage не будет загружен до тех пор, пока он фактически не будет нарисован.Существует множество реализаций, подобных этому дизайну.Такого рода проекты очень полезны для управления ресурсами, но если вы не знакомы с концепцией отложенной оценки, понять их поведение будет непросто.

  2. Это завершение.Используйте C-блоки как можно чаще.Это значительно упростит вашу жизнь.Но прочтите еще раз об управлении блочной памятью, прежде чем использовать его.

  3. Существует полуавтоматический GC.NSAutoreleasePool.Использование -autorelease первичный.Руководство по использованию -retain/-release второстепенный, когда вам действительно нужно.(пример:оптимизация памяти, явное удаление ресурсов)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top