it-swarm.com.ru

Каковы лучшие практики, которые вы используете при написании Objective-C и какао?

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

346
pixel

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

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.

float val = someFloat * 2.2f;

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

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

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

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

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

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

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

399
Kendall Helmstetter Gelner

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

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

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

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

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

    NSLog(@"%@", aString);
110
mmalc

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

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

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

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

108
Chris Hanson

IBOutlets

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

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

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

107
mmalc

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

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

Вы используете Clang Static Analyzer , что неудивительно - для анализа кода C и Objective-C (пока нет C++) в Mac OS X 10.5. Тривиально установить и использовать:

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

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

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

98
mmalc

Это тонкий, но удобный. Если вы передаете себя в качестве делегата другому объекту, сбросьте делегат этого объекта перед собой 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;
95
schwa

@kendell

Вместо:

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

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

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

Новое в Objective-C 2.0.

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

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

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

87
schwa

Избегайте автоматического выпуска

Поскольку вы обычно (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 знают, что они ответственны за освобождение полученного объекта (см., Например, метод newObject в NSObjectController ).

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

75
mmalc

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

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

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

У вас также нет видимости открытых и защищенных и закрытых методов, мешающих написанию тестов для ваших внутренних объектов.

56
Chris Hanson

Золотое правило: если вы alloc, то вы release!

ОБНОВЛЕНИЕ: если вы не используете ARC

55
JamesSugrue

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

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

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

55
Chris Hanson

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

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

50
mj1531

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

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

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

38
mmalc

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

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

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

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

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

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

38
schwa

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

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

37
Chris Hanson

Объявленные свойства

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

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

31
mmalc

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

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

26
mmalc

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

26
NikWest

Простой, но часто забытый. Согласно спецификации:

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

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

@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;
}   
23
Özgür

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

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

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

22
mj1531

Убирайся в деиллок.

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

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

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

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

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

21
schwa

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

17
slf

Также, полу-связанная тема (с местом для большего количества ответов!):

Что это за маленькие советы и хитрости Xcode, о которых ты хотел бы знать 2 года назад? .

15
schwa

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

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

13
mj1531

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

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

12
iwasrobbed

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

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

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


@synthesize property = property_;

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

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

Просмотров

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

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

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

4/Освободить все IBOutlets в viewDidUnload

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

Память

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

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

Комментарии

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

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

Отступ

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


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

return self;


if (!self) {
   return nil;
}

//... long initialization code ...

return self;

Понимаю код C, в основном структуры C

Обратите внимание, что Obj-C является лишь легким слоем OOP над языком 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++ и наших собственных дополнений. Документируйте свой код, используйте стандартные стандартные отступы, пробелы и пустые строки в нужных местах и ​​т.д.

10
Sulthan

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

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

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

10
oefe

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

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

10
mj1531

Будь более функциональным.

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

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

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

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

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

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

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

9
Eonil

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

8
bbrown

Выпускать только метод свойство в dealloc. Если вы хотите освободить память, которую содержит свойство, просто установите его как nil:

self.<property> = nil;
4
Tuan Nguyen
#import "MyClass.h"

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

@implementation MyClass
0
Nirmit Pathak