Відповіді:
Я почав робити кілька речей, які я не вважаю стандартними:
1) З появою властивостей я більше не використовую "_" для приставки "приватних" змінних класу. Зрештою, якщо до змінної можна отримати доступ до інших класів, чи не має бути для неї властивості? Мені завжди не подобався префікс "_", щоб зробити код більш потворним, і тепер я можу його залишити.
2) Якщо говорити про приватні речі, я вважаю за краще розміщувати визначення приватних методів у файлі .m у розширенні класу, як:
#import "MyClass.h"
@interface MyClass ()
- (void) someMethod;
- (void) someOtherMethod;
@end
@implementation MyClass
Чому захаращувати .h-файл із сторонніми речами не варто піклуючись? Порожній () працює для приватних категорій у файлі .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
насправді це може бути подвійне, вам не потрібна математика змішаного режиму, оскільки ви втрачаєте точність у «валі» на зберіганні. Хоча номери з плаваючою комою підтримуються апаратно на айфонах, все ж може знадобитися більше часу, щоб зробити арифметику подвійної точності на відміну від одиничної точності. Список літератури:
На старих телефонах нібито обчислення працюють з однаковою швидкістю, але у регістрах може бути більше одиничних точних компонентів, ніж удвічі, тому для багатьох розрахунків однакова точність в кінцевому підсумку буде швидшою.
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, щоб - не дивно - проаналізувати свій код 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 Reference-Objective-C 2.0.
"Розширення класів дозволяють оголосити додатковий необхідний API для класу в інших місцях, ніж у блоці @interface основного класу"
Отже вони є частиною фактичного класу - а НЕ є приватною категорією, крім класу. Тонка, але важлива відмінність.
()
замість (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;
}
Оскільки назва методу починається з "нового", споживачі вашого API знають, що вони несуть відповідальність за звільнення отриманого об'єкта (див., Наприклад, метод NSObjectControllernewObject
).
(1) Ви можете взяти під контроль, використовуючи власні локальні пули автоматичного випуску. Докладніше про це див. У пулах Autorelease .
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 розсилаються так само динамічно, як методи екземпляра, і їх можна перекрити в підкласах.
Переконайтеся, що ви вибрали закладку на сторінці Magic Debugging Magic . Це має бути вашою першою зупинкою, коли вдаряєтесь головою об стіну, намагаючись знайти джерело помилки з какао.
Наприклад, він розповість, як знайти метод, за яким ви спочатку виділили пам'ять, яка пізніше викликає збої (наприклад, під час завершення роботи програми).
Постарайтеся уникати того, що я вирішив назвати Newbiecategoryaholism. Коли новачки в Objective-C виявляють категорії, вони часто роблять диких свиней, додаючи корисні невеликі категорії до кожного існуючого класу ( "Що? Я можу додати метод перетворення числа в римські цифри в рок NSNumber на!" ).
Не робіть цього.
Ваш код стане більш портативним і простішим для розуміння з десятками методів малої категорії, що розсипаються на два десятки базових класів.
Більшу частину часу, коли ви дійсно думаєте, що вам потрібен метод категорії, який допоможе впорядкувати якийсь код, ви виявите, що ви ніколи не будете повторно використовувати метод.
Існують і інші небезпеки, якщо ви не змінюєте назви методів вашої категорії (а хто, крім абсолютно божевільного ддрібіну?), Є ймовірність, що Apple, або плагін, або щось інше, що працює у вашому адресному просторі, також визначать ту саму категорію метод з однойменною назвою з дещо іншим побічним ефектом ....
ДОБРЕ. Тепер, коли вас попередили, ігноруйте "не робити цю частину". Але проявляйте граничну стриманість.
Протистояти субкласифікації світу. У Какао багато робиться шляхом делегування та використання базового часу виконання, що в інших структурах відбувається за допомогою підкласифікації.
Наприклад, у Java ви багато використовуєте екземпляри анонімних *Listener
підкласів, а в .NET ви багато використовуєте свої EventArgs
підкласи. У какао ви нічого не робите - замість цього використовується цільова дія.
Коли ви сортуєте рядки для подання користувачеві, не слід використовувати простий compare:
метод. Натомість завжди слід використовувати локалізовані методи порівняння, такі як localizedCompare:
або localizedCaseInsensitiveCompare:
.
Детальніше див. Пошук, порівняння та сортування рядків .
Зазвичай ви повинні використовувати функцію оголошених властивостей Objective-C 2.0 для всіх своїх ресурсів. Якщо вони не є загальнодоступними, додайте їх у розширення класу. Використання оголошених властивостей робить семантику управління пам’яттю негайно зрозумілою та полегшує вам перевірку методу угоди - якщо ви згрупуєте декларації властивостей разом, ви можете швидко просканувати їх і порівняти з реалізацією методу угоди.
Вам слід добре подумати, перш ніж не позначати властивості як "неатомічні". Як зазначає Посібник з мов програмування Цілі 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 виберіть Запуск> Почати з інструмента продуктивності> Витоки.
Навіть якщо у вашій програмі не з’являються витоки, ви можете занадто довго тримати об’єкти. У Instruments ви можете використовувати для цього інструмент ObjectAlloc. Виберіть інструмент ObjectAlloc у вашому документі «Інструменти» та підберіть деталі інструменту (якщо він ще не відображається), вибравши «Перегляд»> «Деталі» (біля нього має бути галочка). У розділі "Тривалість розподілу" у деталях ObjectAlloc переконайтесь, що ви вибрали перемикач поруч із "Створено та все ще живе".
Тепер, коли ви припиняєте запис своєї програми, вибір інструмента ObjectAlloc покаже вам, скільки посилань на кожен нерухомий об’єкт у вашій програмі в стовпці "# Net". Переконайтесь, що ви не тільки дивитесь на власні класи, але й на класи об'єктів верхнього рівня ваших файлів NIB. Наприклад, якщо у вас немає вікон на екрані, і ви бачите посилання на ще живе NSWindow, можливо, ви не випустили його у своєму коді.
Прибирати в угоді.
Це одна з найпростіших речей, яку можна забути - esp. при кодуванні 150mph. Завжди, завжди, завжди очищайте свої змінні атрибути / учасники у взаємодії.
Мені подобається використовувати атрибути Objc 2 - з новою позначкою крапок - тому це робить очищення безболісним. Часто так просто, як:
- (void)dealloc
{
self.someAttribute = NULL;
[super dealloc];
}
Це подбає про випуск для вас і встановить атрибут NULL (що я вважаю оборонним програмуванням - на випадок, якщо інший метод, який надалі внизу в операційній операції, знову отримує змінну члена - рідко, але може трапитися).
Якщо GC увімкнено в 10.5, це вже не так вже й потрібно - але вам може знадобитися очищення інших створених вами ресурсів, ви можете зробити це замість методу завершення.
-init
та -dealloc
методи, можна знайти тут: mikeash.com/?page=pyblog/…
Усі ці коментарі чудові, але я дуже здивований, що ніхто не згадував посібник зі стилів Google Objective-C, який був опублікований деякий час назад Я думаю, що вони виконали дуже ретельну роботу.
Також напівспоріднена тема (з простором більше відповідей!):
Які ті маленькі поради та підказки Xcode, які ви хотіли б знати про 2 роки тому? .
Один з досить очевидних для початківців користувачів: використовувати функцію автоматичного відступу Xcode для вашого коду. Навіть якщо ви копіюєте / вставляєте з іншого джерела, після того, як ви вставили код, ви можете вибрати весь блок коду, клацнути правою кнопкою миші на ньому, а потім вибрати опцію для повторного відступу всього цього блоку.
Xcode насправді проаналізує цей розділ і відступить його на основі дужок, циклів тощо. Це набагато ефективніше, ніж натискання на пробіл або клавішу вкладки для кожного рядка.
Я знаю, що я не помітив цього при першому вступі в програму какао.
Переконайтеся, що ви розумієте обов'язки щодо управління пам'яттю стосовно файлів NIB. Ви несете відповідальність за звільнення об'єктів верхнього рівня у будь-якому завантажуваному вами файлі NIB. Прочитайте Документацію Apple з цього питання.
Увімкніть усі попередження GCC, а потім вимкніть ті, які регулярно викликаються заголовками Apple, щоб зменшити шум.
Також часто запускайте статичний аналіз Кланг; ви можете ввімкнути його для всіх збірок за допомогою налаштування збірки "Запустити статичний аналізатор".
Напишіть одиничні тести та запустіть їх із кожною збіркою.
Змінні та властивості
1 / Підтримання чистих заголовків, приховування реалізації
Не включайте змінні екземпляри у свій заголовок. Приватні змінні кладуть у продовження класу як властивості. Загальнодоступні змінні декларуються як загальнодоступні властивості у вашому заголовку. Якщо він повинен бути лише прочитаним, оголосити його як лише прочитане та перезаписати його як readwrite у продовженні класу. Я взагалі не використовую змінні, а лише властивості.
2 / Дайте своїм властивостям ім'я змінної, що не використовується за замовчуванням, наприклад:
@synthesize property = property_;
Причина 1: Ви виявите помилки, викликані забуттям "Я". при відведенні майна. Причина 2. З моїх експериментів у "Аналізатору витоку в інструментах" виникають проблеми з виявленням протікаючих властивостей із замовчуванням.
3 / Ніколи не використовуйте утримувати чи випускати безпосередньо на властивості (або лише у дуже виняткових ситуаціях). У вашій угоді просто призначте їм нуль. Збереження властивостей призначене для обробки збереження / звільнення самостійно. Ніколи не знаєш, чи не сеттер, наприклад, додавання та видалення спостерігачів. Ви повинні використовувати змінну безпосередньо тільки в її сеттері та геттері.
Перегляди
1 / Покладіть кожне визначення перегляду в xib (якщо ви можете, виняток - це зазвичай налаштування динамічного вмісту та шару). Це економить час (простіше, ніж писати код), його легко змінити, і він підтримує чистий код.
2 / Не намагайтеся оптимізувати перегляди, зменшуючи кількість переглядів. Не створюйте UIImageView у своєму коді замість xib лише тому, що ви хочете до нього додати підзагляди. Використовуйте UIImageView як фон. Рамка перегляду може без проблем обробляти сотні переглядів.
3 / IBOutlets не повинні завжди залишатися (або сильними). Зауважте, що більшість ваших IBOutlets є частиною вашої ієрархії перегляду і, таким чином, неявно зберігається.
4 / Відпустіть усі IBOutlets у viewDidUnload
5 / Зателефонуйте viewDidUnload з методу угоди. Це неявно не називається.
Пам'ять
1 / Автоматичні випуски об'єктів під час їх створення. Багато помилок викликані переміщенням виклику випуску в одну гілку if-else або після заяви про повернення. Випуск замість автоматичного випуску слід застосовувати лише у виняткових ситуаціях - наприклад, коли ви очікуєте запуску і не хочете, щоб ваш об'єкт був надрукований занадто рано.
2 / Навіть якщо ви використовуєте Автоматичний довідковий підрахунок, ви повинні чудово розуміти, як працюють методи збереження-випуску. Використовувати функцію утримування-випуску вручну не складніше, ніж ARC, в обох випадках вам доведеться враховувати витоки та цикли утримування. Подумайте про використання ретентивізованого випуску вручну для великих проектів або складних ієрархій об'єктів.
Коментарі
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 ++ та власних доповнень. Документуйте свій код, використовуйте стандартні стандартні відступи, пробіли та порожні рядки в потрібних місцях тощо.
Будьте більш функціональними .
Objective-C - це об'єктно-орієнтована мова, але функціональний стиль какао відомий, і він розроблений функціональним стилем у багатьох випадках.
Відбувається поділ мутабельності. Використовуйте незмінні класи як основний, а об'єкт, що змінюється, як вторинний. Наприклад, в основному використовуйте NSArray і використовуйте NSMutableArray лише тоді, коли вам потрібно.
Є чисті функції. Не так багато, купуйте багато API-програм фреймворку, розроблених як чисті функції. Подивіться на такі функції, як CGRectMake()
або CGAffineTransformMake()
. Очевидно, форма вказівника виглядає більш ефективно. Однак непрямий аргумент з покажчиками не може запропонувати побічних ефектів. Дизайн конструкцій максимально чисто. Відокремте навіть державні об’єкти. Використовуйте -copy
замість того, -retain
щоб передавати значення іншому об'єкту. Оскільки спільний стан може мовчки впливати на мутацію до значення в іншому об'єкті. Тому не може бути побічним ефектом. Якщо у вас є значення зовнішнього від об'єкта, скопіюйте його. Тому також важливо розробити загальний стан якомога мінімальніше.
Однак не бійтеся також використовувати нечисті функції.
Є лінива оцінка. Побачити щось на зразок -[UIViewController view]
власності. Перегляд не буде створено, коли об’єкт створений. Він буде створений під view
час першого читання властивості абонента . UIImage
не завантажуватиметься, поки воно фактично не буде намальовано. Подібної конструкції існує багато. Цей вид конструкцій дуже корисний для управління ресурсами, але якщо ви не знаєте концепції лінивої оцінки, зрозуміти їх поведінку непросто.
Відбувається закриття. Використовуйте С-блоки максимально. Це значно спростить ваше життя. Але прочитайте ще раз про управління блоковою пам’яттю, перш ніж використовувати її.
Є напів-авто GC. NSAutoreleasePool. Використовуйте -autorelease
основне. Використовуйте вручну, -retain/-release
коли вам це справді потрібно. (наприклад: оптимізація пам'яті, явне видалення ресурсів)
autorelease
, що взагалі довше зберігатиме пам’ять, і вручну retain/release
можна зменшити споживання пам'яті у цьому випадку. Однак це повинно бути настановою для оптимізації спеціальних випадків (навіть ви відчуваєте себе завжди!), Не може бути причиною узагальнення передчасної оптимізації як практики . А насправді ваша пропозиція не протилежна мені. Я згадував це як випадок справді потрібного :)