Ответы:
Я начал делать несколько вещей, которые я не считаю стандартными:
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
Когда методы или функции принимают аргумент строки формата, вы должны убедиться, что у вас есть контроль над содержимым строки формата.
Например, при регистрации строк заманчиво передать строковую переменную в качестве единственного аргумента NSLog
:
NSString *aString = // get a string from somewhere;
NSLog(aString);
Проблема в том, что строка может содержать символы, которые интерпретируются как строки формата. Это может привести к ошибочному выводу данных, сбоям и проблемам безопасности. Вместо этого вы должны подставить строковую переменную в строку формата:
NSLog(@"%@", aString);
Используйте стандартные соглашения и терминологию именования и форматирования Какао, а не то, к чему вы привыкли из другой среды. Там являются много разработчиков какао там, и когда другой один из них начинает работать с вашим кодом, это будет гораздо более доступным , если она выглядит и чувствует себя похож на другой код какао.
Примеры того, что нужно делать, а что нет:
id m_something;
в интерфейсе объекта и не называйте его переменной или полем члена ; используйте something
или _something
для его имени и назовите его переменной экземпляра .-getSomething
; правильное имя Какао просто -something
.-something:
; так должно быть-setSomething:
-[NSObject performSelector:withObject:]
не NSObject::performSelector
.Что бы вы ни делали, не используйте венгерские обозначения в стиле Win16 / Win32. Даже Microsoft отказалась от этого, перейдя на платформу .NET.
Исторически сложилось, что управление памятью торговых точек было плохим. В настоящее время рекомендуется объявлять торговые точки как свойства:
@interface MyClass :NSObject {
NSTextField *textField;
}
@property (nonatomic, retain) IBOutlet NSTextField *textField;
@end
Использование свойств делает семантику управления памятью понятной; это также обеспечивает непротиворечивый образец, если вы используете синтез переменных экземпляра.
ПРИМЕЧАНИЕ. В Xcode 4 это теперь встроено в IDE.
Вы используете Clang Static Analyzer, что неудивительно, для анализа кода C и Objective-C (пока нет C ++) в Mac OS X 10.5. Установить и использовать тривиально:
cd
в каталог вашего проекта.scan-build -k -V xcodebuild
.(Существуют некоторые дополнительные ограничения и т. Д., В частности, вам следует проанализировать проект в его конфигурации «Отладка» - подробности см. 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;
Memory Management Programming Guide for Cocoa
: Additional cases of weak references in Cocoa include, but are not restricted to, table data sources, outline view items, notification observers, and miscellaneous targets and delegates. In most cases, the weak-referenced object is aware of the other object’s weak reference to it, as is the case for circular references, and is responsible for notifying the other object when it deallocates.
nil == NULL
. Они точно такие же, за исключением того, что nil
есть id
и NULL
есть void *
. Ваше утверждение не соответствует действительности.
@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 class»
Таким образом, они являются частью реального класса - и НЕ (частной) категории в дополнение к классу. Тонкое, но важное отличие.
()
Вместо (Private)
(или какого-либо другого имени категории) есть довольно важное преимущество : вы можете повторно объявить свойства как readwrite, в то время как для публики они доступны только для чтения. :)
Поскольку вы обычно (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 знают, что они ответственны за освобождение полученного объекта (см., Например, метод NSObjectControllernewObject
).
(1) Вы можете получить контроль, используя свои собственные локальные пулы автоматического выпуска. Для получения дополнительной информации об этом см. Автозапуск пулов .
NSAutoreleasePool
. Но только после того, как вы подтвердили, что это действительно проблема. Преждевременная оптимизация и все такое ...
Некоторые из них уже упоминались, но вот что я могу придумать:
#pragma mark [section]
. Обычно я группирую свои собственные методы, переопределения каждого подкласса и любую информацию или формальные протоколы. Это значительно облегчает переход к тому, что я ищу. По той же теме, сгруппируйте сходные методы (например, методы делегатов табличного представления) вместе, а не просто их где-то склеивайте.#define
желанию или кэширование массива вместо сортировки каждый раз, когда нужны данные. Я могу многое сказать по этому поводу, но суть в том, что не пишите код, пока он вам не понадобится, или профилировщик не скажет вам об этом. Это делает вещи намного легче поддерживать в долгосрочной перспективе.NSLog( @"stub" )
внутрь, или как хотите, чтобы отслеживать вещи.Finish what you start
вы также можете использовать // TODO:
для маркировки кода для завершения, который будет отображаться в раскрывающемся списке.
Напишите юнит-тесты. Вы можете протестировать много вещей в Какао, которые могут быть сложнее в других средах. Например, с помощью кода пользовательского интерфейса вы можете в общем убедиться, что все подключено так, как должно быть, и поверить, что они будут работать при использовании. И вы можете легко настроить состояние и вызывать методы делегатов для их тестирования.
У вас также нет видимости открытых и защищенных и закрытых методов, мешающих написанию тестов для ваших внутренних объектов.
Золотое правило: если ты, alloc
то ты release
!
ОБНОВЛЕНИЕ: если вы не используете ARC
copy
, mutableCopy
, new
или retain
.
Не пишите Objective-C, как если бы это был Java / C # / C ++ / и т. Д.
Однажды я видел, как команда разработчиков веб-приложений на Java EE пыталась написать настольное приложение Cocoa. Как будто это было веб-приложение Java EE. Было много AbstractFooFactory и FooFactory, а также IFoo и Foo, которые летали, когда все, что им действительно нужно, это класс Foo и, возможно, протокол Fooable.
Частью обеспечения того, что вы этого не делаете, является истинное понимание различий в языке. Например, вам не нужны абстрактные фабрика и фабричные классы, описанные выше, потому что методы класса Objective C отправляются так же динамически, как методы экземпляра, и могут быть переопределены в подклассах.
Убедитесь, что вы добавили в закладки страницу « Отладка магии» . Это должно быть вашей первой остановкой, когда вы будете биться головой о стену, пытаясь найти источник ошибки Какао.
Например, он расскажет вам, как найти метод, в котором вы сначала выделили память, которая позже вызывает сбои (например, во время завершения приложения).
Старайтесь избегать того, что я сейчас решил назвать Newbiecategoryaholism. Когда новички в Objective-C обнаруживают категории, они часто становятся дикими, добавляя полезные маленькие категории к каждому существующему классу ( «Что? Я могу добавить метод для преобразования числа в римские цифры в NSNumber»! ).
Не делай этого.
Ваш код будет более переносимым и легким для понимания без использования десятков небольших методов категорий, разбросанных поверх двух десятков базовых классов.
Большую часть времени, когда вы действительно думаете, что вам нужен метод категории, чтобы помочь упростить некоторый код, вы обнаружите, что вы никогда не будете использовать метод повторно.
Есть и другие опасности, если только вы не используете пространство имен для методов вашей категории (и кто, кроме совершенно безумного ддрибина?), Есть вероятность, что Apple, или плагин, или что-то еще, работающее в вашем адресном пространстве, также определит ту же категорию. метод с тем же именем с немного другим побочным эффектом ....
ХОРОШО. Теперь, когда вы были предупреждены, игнорируйте «не делайте эту часть». Но проявляйте крайнюю сдержанность.
Сопротивляйтесь подклассификации мира. В Какао многое делается с помощью делегирования и использования базовой среды выполнения, которая в других средах выполняется с помощью подклассов.
Например, в Java вы часто используете экземпляры анонимных *Listener
подклассов, а в .NET вы часто используете ваши EventArgs
подклассы. В Какао вы тоже этого не делаете - вместо этого используется цель-действие.
Когда вы сортируете строки для представления пользователю, вы не должны использовать простой compare:
метод. Вместо этого вы всегда должны использовать локализованные методы сравнения, такие как localizedCompare:
илиlocalizedCaseInsensitiveCompare:
.
Для получения дополнительной информации см. Поиск, сравнение и сортировка строк .
Обычно вы должны использовать функцию объявленных свойств 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 в документе «Инструменты» и откройте сведения об инструменте (если он еще не отображается), выбрав «Вид»> «Детали» (рядом с ним должна стоять галочка). В разделе «Срок действия выделения» в подробностях ObjectAlloc убедитесь, что вы выбрали переключатель рядом с «Создан и еще жив».
Теперь, когда вы прекратите запись своего приложения, выбор инструмента ObjectAlloc покажет вам, сколько ссылок есть на каждый еще живущий объект в вашем приложении в столбце "# Net". Убедитесь, что вы смотрите не только на свои собственные классы, но и на классы объектов верхнего уровня ваших файлов NIB. Например, если у вас нет окон на экране, и вы видите ссылки на еще живое NSWindow, возможно, вы не выпустили его в своем коде.
Убирайся в деилок.
Это одна из самых простых вещей, которую нужно забыть - особенно. при кодировании на 150 миль в час. Всегда, всегда, всегда очищайте ваши атрибуты / переменные-члены в dealloc.
Мне нравится использовать атрибуты Objc 2 - с новой нотацией точек - так что это делает очистку безболезненной. Часто так просто, как:
- (void)dealloc
{
self.someAttribute = NULL;
[super dealloc];
}
Это позаботится о выпуске и установит для атрибута значение NULL (что я считаю защитным программированием - в случае, если другой метод, расположенный ниже в dealloc, снова обращается к переменной-члену - редко, но может случиться).
С включенным в 10.5 GC это больше не нужно, но вам все равно может понадобиться очистить другие ресурсы, которые вы создаете, вы можете сделать это в методе finalize.
-init
и -dealloc
методы, можно найти здесь: mikeash.com/?page=pyblog/…
Все эти комментарии великолепны, но я действительно удивлен, что никто не упомянул руководство по стилю Google Objective-C, которое было опубликовано некоторое время назад. Я думаю, что они проделали очень тщательную работу.
Также, полу-связанная тема (с местом для большего количества ответов!):
Что это за маленькие советы и хитрости Xcode, о которых вы хотели бы знать около 2 лет назад? ,
Один довольно очевидный для новичка: использовать функцию авто-отступа Xcode для вашего кода. Даже если вы копируете / вставляете из другого источника, после того, как вы вставили код, вы можете выбрать весь блок кода, щелкнуть по нему правой кнопкой мыши, а затем выбрать вариант для повторного отступа всего в этом блоке.
Xcode на самом деле проанализирует этот раздел и сделает отступ с помощью скобок, циклов и т. Д. Это намного эффективнее, чем нажатие клавиши пробела или клавиши табуляции для каждой строки.
Я знаю, что упустил это из виду, когда впервые попал в программирование Какао.
Убедитесь, что вы понимаете обязанности по управлению памятью относительно файлов NIB. Вы несете ответственность за освобождение объектов верхнего уровня в любом загружаемом вами файле NIB. Прочитайте документацию Apple по этому вопросу.
Включите все предупреждения GCC, а затем отключите те, которые регулярно вызываются заголовками Apple, для уменьшения шума.
Также часто запускайте статический анализ Clang; Вы можете включить его для всех сборок с помощью параметра сборки «Запустить статический анализатор».
Напишите модульные тесты и запускайте их с каждой сборкой.
Переменные и свойства
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 - это только легкий слой ООП над языком 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 и во многих случаях разработан функциональный стиль.
Существует разделение изменчивости. Используйте неизменяемые классы в качестве основного и изменяемый объект в качестве дополнительного. Например, используйте в первую очередь NSArray, и используйте NSMutableArray только тогда, когда вам нужно.
Есть чистые функции. Не так много, покупайте многие из API-интерфейсов, разработанных как чистая функция. Посмотрите на такие функции, как CGRectMake()
или CGAffineTransformMake()
. Очевидно, форма указателя выглядит более эффективно. Однако косвенный аргумент с указателями не может предложить без побочных эффектов. Проектирование конструкций чисто как можно больше. Отделяйте даже государственные объекты. Используйте -copy
вместо -retain
передачи значения другому объекту. Потому что разделяемое состояние может молча влиять на изменение значения в другом объекте. Так что не может быть без побочных эффектов. Если у вас есть значение из внешнего объекта, скопируйте его. Поэтому также важно, чтобы общее состояние было минимальным.
Однако не бойтесь использовать нечистые функции тоже.
Есть ленивая оценка. Смотрите что-то вроде -[UIViewController view]
собственности. Представление не будет создано при создании объекта. Он будет создан при чтении view
свойства вызывающего абонента в первый раз. UIImage
не будет загружен, пока не будет нарисован. Есть много реализаций, подобных этой конструкции. Подобные конструкции очень полезны для управления ресурсами, но если вы не знаете концепцию отложенной оценки, понять их поведение непросто.
Есть закрытие. Используйте C-блоки как можно больше. Это значительно упростит вашу жизнь. Но прочитайте еще раз о блок-памяти управления, прежде чем использовать его.
Есть полуавтоматический GC. NSAutoreleasePool. Используйте -autorelease
первичный. Используйте ручное -retain/-release
среднее, когда вам действительно нужно. (например: оптимизация памяти, явное удаление ресурса)
autorelease
что в общем случае память будет дольше, а ручное управление retain/release
может уменьшить потребление памяти в этом случае. Однако это должно быть руководство для оптимизации в особом случае (даже если вы чувствуете себя всегда!), Не может быть причиной для обобщения преждевременной оптимизации как практики . И на самом деле ваше предложение не противоположно мне. Я упомянул это как случай действительно нуждающийся :)