Jakie są najlepsze praktyki, z których korzystasz pisząc Objective-C i Cocoa? [zamknięte]

Wiem o HIG (co jest bardzo przydatne!), ale jakich praktyk programistycznych używasz przy pisaniu Objective-C, a dokładniej przy użyciu Cocoa (lub CocoaTouch).

Author: pixel, 2008-10-01

30 answers

Jest kilka rzeczy, które zacząłem robić, które nie są moim zdaniem standardowe:

1) wraz z pojawieniem się właściwości, nie używam już " _ "do prefiksu" prywatnych " zmiennych klasy. W końcu, jeśli zmienna może być dostępna dla innych klas, czy nie powinna istnieć dla niej właściwość? Zawsze nie lubiłem przedrostka " _ " za brzydszy kod, a teraz mogę go pominąć.

2) mówiąc o rzeczach prywatnych, wolę umieścić definicje metod prywatnych w .m plik w rozszerzeniu klasy tak:

#import "MyClass.h"

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

@implementation MyClass

Dlaczego zaśmiecać .plik h z rzeczami, o które nie powinni dbać obcy? Empty () działa dla kategorii prywatnych w .m file, i wystawia Ostrzeżenia kompilacji, jeśli nie zaimplementujesz zadeklarowanych metod.

3) podjąłem się umieszczenia dealloca na szczycie .plik m, tuż pod dyrektywami @ synthesize. Czy to, co dealloc nie powinno być na szczycie listy rzeczy, o których chcesz myśleć w klasie? Jest to szczególnie prawdziwe w środowisku takim jak iPhone.

3.5) w komórkach tabeli, aby każdy element (w tym sama komórka) był nieprzezroczysty dla wydajności. Oznacza to ustawienie odpowiedniego koloru tła we wszystkim.

3.6) używając NSURLConnection, z reguły możesz chcieć zaimplementować metodę delegata:

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

Uważam, że większość połączeń internetowych jest bardzo pojedyncza i jest to bardziej wyjątek niż reguła, którą będziesz chciał buforować odpowiedzi, szczególnie w przypadku połączeń z usługami sieciowymi. Wdrożenie metody jak pokazano wyłącza buforowanie odpowiedzi.

Interesujące są również dobre wskazówki dotyczące iPhone 'a od Josepha Mattiello (otrzymane na liście mailingowej iPhone' a). Jest ich więcej, ale te były najbardziej użyteczne, o których myślałem (zauważ, że kilka bitów zostało teraz nieco zmodyfikowanych od oryginału, aby uwzględnić szczegóły oferowane w odpowiedziach): {]}

4) używaj podwójnej precyzji tylko wtedy, gdy musisz, na przykład podczas pracy z CoreLocation. Upewnij się, że kończysz swoje stałe w 'f', aby gcc przechowywało je jako pływa.

float val = someFloat * 2.2f;

Jest to szczególnie ważne, gdy someFloat może być podwójne, nie potrzebujesz matematyki w trybie mieszanym, ponieważ tracisz precyzję w " val " na magazynie. Podczas gdy liczby zmiennoprzecinkowe są obsługiwane na sprzęcie na iPhone ' ach, wykonanie arytmetyki z podwójną precyzją może zająć więcej czasu, w przeciwieństwie do pojedynczej precyzji. Bibliografia:

Na starsze telefony podobno obliczenia działają z tą samą prędkością, ale można mieć więcej pojedynczych komponentów precyzyjnych w rejestrach niż podwójnych, więc dla wielu obliczeń pojedyncza precyzja będzie szybsza.

5) Ustaw swoje właściwości jako nonatomic. Są one atomic domyślnie i podczas syntezy, kod semafora zostanie utworzony, aby zapobiec problemom z wielowątkowością. 99% z was prawdopodobnie nie musi się tym martwić, a kod jest znacznie mniej nadęty i bardziej wydajny w pamięci, gdy jest ustawiony na nieatomowe.

6) SQLite może być bardzo, bardzo szybkim sposobem buforowania dużych zbiorów danych. Aplikacja map na przykład może buforować swoje płytki do plików SQLite. Najdroższą częścią jest Wejście/Wyjście dyskowe. unikaj wielu małych zapisów wysyłając BEGIN; i COMMIT; pomiędzy dużymi blokami. Używamy na przykład 2 sekund timera, który resetuje się przy każdym nowym przesłaniu. Kiedy wygaśnie, wysyłamy commit;, który powoduje, że wszystkie twoje zapisy idą w jednym dużym kawałku. SQLite przechowuje dane transakcji na dysku i robi to Begin/End zawijanie pozwala uniknąć tworzenia wielu plików transakcji, grupując wszystkie transakcje w jeden plik.

Ponadto, SQL zablokuje GUI, jeśli jest w głównym wątku. Jeśli masz bardzo długie zapytanie, dobrym pomysłem jest przechowywanie zapytań jako obiektów statycznych i uruchamianie SQL w osobnym wątku. Upewnij się, że wszystko, co modyfikuje bazę danych dla ciągów zapytań, zostało zawinięte w @synchronize() {} bloki. W przypadku krótkich zapytań po prostu zostaw rzeczy w głównym wątku dla łatwiejszej wygody.

Więcej SQLite wskazówki dotyczące optymalizacji są tutaj, choć dokument wydaje się Nieaktualny wiele z punktów jest prawdopodobnie nadal dobrych; {]}

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

 399
Author: Kendall Helmstetter Gelner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:56

Nie używaj nieznanych ciągów jako ciągów formatujących

Gdy metody lub funkcje przyjmują argument format string, należy upewnić się, że masz kontrolę nad zawartością formatu string.

Na przykład, podczas logowania łańcuchów, kuszące jest przekazanie zmiennej string jako jedynego argumentu do NSLog:

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

Problem polega na tym, że łańcuch znaków może zawierać znaki, które są interpretowane jako ciągi formatujące. Może to prowadzić do błędnych wyników, awarii i problemy z bezpieczeństwem. Zamiast tego należy zastąpić zmienną string ciągiem formatującym:

    NSLog(@"%@", aString);
 110
Author: mmalc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-03 13:03:50

Używaj standardowych konwencji i terminologii nazewnictwa i formatowania Cocoa zamiast tego, do czego przywykłeś z innego środowiska. Istnieje wielu programistów Cocoa, a kiedy inny z nich zacznie pracować z Twoim kodem, będzie on znacznie bardziej przystępny, jeśli będzie wyglądał i wyglądał podobnie do innych kodu Cocoa.

Przykłady tego, co robić, a czego nie:

  • nie deklaruj id m_something; w interfejsie obiektu i nie nazywaj go członkiem zmienna lub pole ; użyj something lub _something dla jej nazwy i nazwij ją zmienną instancji .
  • nie nazywaj gettera -getSomething; właściwa nazwa kakao to po prostu -something.
  • nie nazywaj setera -something:; powinno być -setSomething:
  • nazwa metody jest przeplatana argumentami i zawiera dwukropki; jest to -[NSObject performSelector:withObject:], a nie NSObject::performSelector.
  • używaj Inter-caps (CamelCase) w nazwach metod, parametrów, zmiennych, nazw klas itp. zamiast podbarek (podkreślenia).
  • nazwy klas rozpoczynają się wielkimi literami, nazwy zmiennych i metod małymi literami.

Cokolwiek jeszcze zrobisz, nie używaj Węgierskiej notacji w stylu Win16/Win32. Nawet Microsoft zrezygnował z tego wraz z przejściem na platformę. NET.

 108
Author: Chris Hanson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-25 18:27:46

IBOutlets

[[3]}historycznie zarządzanie pamięcią punktów sprzedaży było słabe. Obecnie najlepszą praktyką jest deklarowanie punktów sprzedaży jako właściwości:
@interface MyClass :NSObject {
    NSTextField *textField;
}
@property (nonatomic, retain) IBOutlet NSTextField *textField;
@end

Używanie właściwości sprawia, że semantyka zarządzania pamięcią jest jasna; zapewnia również spójny wzorzec, jeśli używasz syntezy zmiennych instancji.

 107
Author: mmalc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-03 16:06:54

Użyj analizatora statycznego LLVM / Clang

Uwaga: pod Xcode 4 jest to teraz wbudowane w IDE.

Używasz Clang Static Analyzer do -- nic dziwnego -- analizy kodu C i Objective-C (nie C++ jeszcze) na Mac OS X 10.5. Instalacja i użytkowanie jest banalne:

  1. Pobierz najnowszą wersję z tej strony .
  2. z linii poleceń, cd do katalogu twojego projektu.
  3. wykonaj scan-build -k -V xcodebuild.

(istnieje kilka dodatkowych ograniczenia itp. w szczególności należy przeanalizować projekt w jego konfiguracji "Debug" -- patrz http://clang.llvm.org/StaticAnalysisUsage.html Po szczegóły -- ale to jest mniej więcej to, co sprowadza się do.)

Analizator następnie tworzy zestaw stron internetowych dla Ciebie, który pokazuje prawdopodobne zarządzanie pamięcią i inne podstawowe problemy, których kompilator nie jest w stanie wykryć.

 98
Author: mmalc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-28 20:49:33

To jest subtelne, ale poręczne. Jeśli przekazujesz siebie jako delegata do innego obiektu, zresetuj delegata tego obiektu przed tobą dealloc.

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

W ten sposób zapewniasz, że żadne metody delegowania nie zostaną wysłane. Kiedy masz zamiar dealloc i zniknąć w eterze, chcesz się upewnić, że nic nie może wysłać więcej wiadomości przez przypadek. Pamiętaj o sobie.someObject może być zachowany przez inny obiekt (może to być singleton lub w Puli autorelease lub cokolwiek) i dopóki nie powiesz mu " przestań wysyłać mi wiadomości!", uważa, że Twój właśnie-o-być-dealloced obiekt jest fair game.

Wprowadzenie tego nawyku uchroni Cię przed wieloma dziwnymi awariami, które są bólem do debugowania.

Ta sama zasada dotyczy obserwacji wartości klucza, a także NSNotifications.

Edit:

Jeszcze bardziej Defensywny, zmiana:

self.someObject.delegate = NULL;

Do:

if (self.someObject.delegate == self)
    self.someObject.delegate = NULL;
 95
Author: schwa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-28 20:50:22

@kendell

Zamiast:

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

Użycie:

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

Nowość w Objective-C 2.0.

Rozszerzenia klas są opisane w Apple Objective-C 2.0 Reference.

"rozszerzenia klas pozwalają zadeklarować dodatkowe wymagane API dla klasy w lokalizacjach innych niż w bloku primary class @ interface"

Są więc częścią rzeczywistej klasy - A nie (prywatnej) kategorii oprócz klasy. Subtelna, ale ważna różnica.

 87
Author: schwa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-28 20:52:21

Unikaj autorelease

Ponieważ zazwyczaj (1) nie masz bezpośredniej kontroli nad ich żywotnością, obiekty z autorelementem mogą utrzymywać się przez stosunkowo długi czas i niepotrzebnie zwiększać ślad pamięci aplikacji. Podczas gdy na komputerze może to mieć niewielkie znaczenie, na bardziej ograniczonych platformach może to być istotny problem. W związku z tym na wszystkich platformach, a zwłaszcza na platformach bardziej ograniczonych, uważa się za najlepszą praktykę unikanie metod, które mogłyby prowadzić do obiektów z autorelementem i zamiast tego zaleca się stosowanie wzorca alloc/INIT.

Zatem zamiast:

aVariable = [AClass convenienceMethod];

Tam, gdzie jest w stanie, powinieneś zamiast tego użyć:

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

Podczas pisania własnych metod zwracających nowo utworzony obiekt, możesz skorzystać z konwencji nazewnictwa Cocoa , aby zaznaczyć do odbiornika, że musi on zostać zwolniony przez dodanie nazwy metody "new".

Zatem zamiast:

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

You could napisz:

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

Ponieważ nazwa metody zaczyna się od "new", użytkownicy twojego API wiedzą, że są odpowiedzialni za zwolnienie otrzymanego obiektu (patrz na przykład metoda newObject NSObjectController ' S newObject).

(1) możesz przejąć kontrolę za pomocą własnych lokalnych pul autorelease. Więcej informacji na ten temat można znaleźć w Autorelease Pools.

 75
Author: mmalc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-28 20:51:35

Niektóre z nich zostały już wspomniane, ale oto, co mogę wymyślić z głowy:

  • postępuj zgodnie z zasadami nazewnictwa KVO. nawet jeśli nie używasz teraz KVO, z mojego doświadczenia często jest to korzystne w przyszłości. A jeśli używasz KVO lub wiązań, musisz wiedzieć, że wszystko działa tak, jak powinno. Obejmuje to nie tylko metody dostępu i zmienne instancji, ale także wiele relacji, walidację, automatyczne powiadamianie kluczy zależnych i i tak dalej.
  • Umieść prywatne metody w kategorii. nie tylko interfejs, ale także implementacja. Dobrze jest mieć pewien dystans koncepcyjny między metodami prywatnymi i nie-prywatnymi. Włączam wszystko w moim .plik M.
  • Umieść metody wątku tła w kategorii. to samo co wyżej. Uważam, że dobrze jest utrzymać wyraźną barierę pojęciową, gdy myślisz o tym, co jest w głównym wątku, a co nie.
  • Użyj #pragma mark [section]. Zwykle grupuję według moje własne metody, nadpisania każdej podklasy i wszelkie informacje lub formalne protokoły. To sprawia, że o wiele łatwiej przejść do dokładnie tego, czego szukam. W tym samym temacie Grupuj podobne metody (jak delegowane metody widoku tabeli) razem, nie przyklejaj ich nigdzie.
  • Prefix private methods & ivars with _. podoba mi się to, jak wygląda, i mniej prawdopodobne, że użyję Ivara, gdy mam na myśli nieruchomość przez przypadek.
  • nie używaj metod / właściwości mutatora w init & dealloc. nigdy nie zdarzyło mi się coś złego z tego powodu, ale widzę logikę, jeśli zmienisz metodę, aby zrobić coś, co zależy od stanu Twojego obiektu.
  • Umieść IBOutlets we właściwościach.[8]] właśnie to przeczytałem, ale zacznę to robić. Bez względu na zalety pamięci, wydaje się lepiej stylistycznie (przynajmniej dla mnie).
  • unikaj pisania kodu, którego nie potrzebujesz. to naprawdę obejmuje wiele rzeczy, jak tworzenie ivarów, gdy a #define zrobi, lub buforuje tablicę zamiast sortować ją za każdym razem, gdy potrzebne są dane. Wiele mogę na ten temat powiedzieć, ale najważniejsze jest to, że nie pisz kodu, dopóki go nie potrzebujesz, albo profiler ci tego każe. To sprawia, że rzeczy o wiele łatwiejsze do utrzymania w dłuższej perspektywie.
  • Zakończ to, co zacząłeś. posiadanie dużo ukończonego, błędnego kodu jest najszybszym sposobem zabicia projektu martwego. Jeśli potrzebujesz metody stub, która jest w porządku, po prostu wskaż ją, umieszczając NSLog( @"stub" ) wewnątrz, lub jakkolwiek chcę mieć wszystko na oku.
 70
Author: Marc Charbonneau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-17 23:11:06

Napisz testy jednostkowe. Możesz przetestować Wiele rzeczy w kakao, które mogą być trudniejsze w innych frameworkach. Na przykład za pomocą kodu interfejsu użytkownika można ogólnie sprawdzić, czy rzeczy są połączone tak, jak powinny i ufać, że będą działać, gdy będą używane. Możesz łatwo skonfigurować metody state & invoke delegate, aby je przetestować.

Nie masz również widoczności publicznych vs. chronionych vs. prywatnych metod, które przeszkadzają w pisaniu testów dla twoich wewnętrznych.

 56
Author: Chris Hanson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-01 08:04:58

Złota zasada: jeśli ty alloc to Ty release!

UPDATE: Unless you are using ARC

 55
Author: logancautrell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-28 20:52:57

Nie pisz Objective-C tak, jakby to było Java / C#/C++ / etc.

Widziałem kiedyś, jak zespół zajmujący się pisaniem aplikacji internetowych Java EE próbował napisać aplikację desktopową Cocoa. Jakby to była aplikacja internetowa Java EE. Było dużo AbstractFooFactory i FooFactory oraz IFoo i Foo latających wokół, gdy wszystko, czego naprawdę potrzebowali, to klasa Foo i ewentualnie protokół Fooable.

Częścią zapewnienia, że tego nie zrobisz, jest naprawdę zrozumienie różnic w języku. Na przykład, ty nie potrzebujesz powyższych klas abstract factory i factory, ponieważ metody klas Objective-C są wysyłane tak samo dynamicznie jak metody instancji i mogą być nadpisywane w podklasach.

 55
Author: Chris Hanson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-06 09:01:14

Upewnij się, że zakładka debugging Magic strona. To powinien być twój pierwszy przystanek, gdy uderzasz głową o ścianę, próbując znaleźć źródło robaka kakaowego.

Na przykład dowiesz się, jak znaleźć metodę, w której najpierw przydzielono pamięć, która później powoduje awarie (np. podczas zakończenia aplikacji).

 50
Author: mj1531,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-01 16:35:03

Sortowanie łańcuchów według potrzeb użytkownika

Podczas sortowania ciągów znaków do przedstawienia Użytkownikowi, nie należy używać prostej metody compare:. Zamiast tego należy zawsze używać lokalnych metod porównawczych, takich jak localizedCompare: lub localizedCaseInsensitiveCompare:.

Aby uzyskać więcej informacji, zobacz wyszukiwanie, porównywanie i sortowanie łańcuchów.

 38
Author: mmalc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-06 16:49:19

Staraj się unikać tego, co postanowiłem teraz nazwać Newbiecategoriaholizmem. Kiedy nowicjusze Objective-C odkrywają kategorie, często szaleją, dodając przydatne małe kategorie do każdej istniejącej klasy ("Co? Mogę dodać metodę konwersji liczby na cyfry rzymskie do nsnumber rock on!").

Nie rób tego.

Twój kod będzie bardziej przenośny i łatwiejszy do zrozumienia dzięki dziesiątkom metod małych kategorii umieszczonych na dwóch tuzinach fundamentów klasy.

Przez większość czasu, kiedy naprawdę myślisz, że potrzebujesz metody kategorii, aby usprawnić kod, który okaże się, że nigdy nie skończy się na ponownym użyciu metody.

Są też inne niebezpieczeństwa, chyba że wymieniasz nazwy swoich metod kategorii (a kto oprócz kompletnie obłąkanego ddribina jest?) istnieje szansa, że Apple, lub wtyczka, lub coś innego działające w przestrzeni adresowej również zdefiniuje tę samą metodę kategorii o tej samej nazwie z nieco inną stroną efekt....

OK. Teraz, kiedy zostałeś ostrzeżony, zignoruj "nie rób tej części". Ale zachowaj ekstremalną powściągliwość.

 38
Author: schwa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-20 05:37:57

Oprzyj się podklasowaniu świata. W Cocoa wiele odbywa się poprzez delegowanie i korzystanie z podstawowego środowiska wykonawczego, które w innych frameworkach odbywa się poprzez podklasowanie.

Na przykład w Javie często używasz instancji anonimowych *Listener podklas, a w.NET często używasz swoich EventArgs podklas. W Cocoa, ty też tego nie robisz - zamiast tego używana jest akcja docelowa.

 37
Author: Chris Hanson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-01 08:10:26

Deklarowane Właściwości

Powinieneś zazwyczaj używać funkcji Objective-C 2.0 deklarowanych właściwości dla wszystkich swoich właściwości. Jeśli nie są publiczne, dodaj je do rozszerzenia klasy. Użycie zadeklarowanych właściwości sprawia, że semantyka zarządzania pamięcią jest natychmiast jasna i ułatwia sprawdzenie metody dealloc - jeśli pogrupujesz deklaracje właściwości razem, możesz szybko je zeskanować i porównać z implementacją metody dealloc.

Powinieneś pomyśleć twarde przed Nie oznaczeniem właściwości jako "nieatomowe". Jak zauważa Przewodnik języka programowania Objective C, właściwości są domyślnie atomowe i ponoszą znaczne koszty. Co więcej, samo wykonanie wszystkich właściwości atomic nie sprawia, że wątek aplikacji jest bezpieczny. Zauważ oczywiście, że jeśli nie określisz "nieatomicznych" i nie zaimplementujesz własnych metod dostępu( zamiast ich syntetyzować), musisz zaimplementować je w sposób atomowy.

 31
Author: mmalc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-28 20:53:13

Pomyśl o zerowych wartościach

Jako to pytanie zauważa, że Wiadomości do nil są ważne w Objective-C. Chociaż jest to często zaletą-prowadzącą do czystszego i bardziej naturalnego kodu-funkcja może czasami prowadzić do osobliwych i trudnych do wyśledzenia błędów, jeśli otrzymasz wartość nil, gdy się jej nie spodziewałeś.

 26
Author: mmalc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:11

Użyj NSAssert i przyjaciele. Cały czas używam nil jako ważnego obiektu ... szczególnie wysyłanie wiadomości do nil jest doskonale poprawne w Obj-C. Jeśli jednak naprawdę chcę mieć pewność co do stanu zmiennej, używam NSAssert i NSParameterAssert, które pomagają łatwo namierzyć problemy.

 26
Author: NikWest,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-07 20:57:48

Proste, ale często zapomniane. Według spec:

Ogólnie, metody w różnych klasy, które mają ten sam selektor (o tej samej nazwie) musi również dzielić się te same typy zwrotów i argumentów. To ograniczenie jest narzucane przez kompilator aby umożliwić dynamiczne Wiązanie.

W takim przypadku wszystkie selektory o tej samej nazwie, , nawet jeśli są w różnych klasach , będą traktowane jako posiadające identyczne typy zwracania / argumentowania. Oto prosty przykład.

@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
Author: Comptrol,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-28 03:09:30

Jeśli używasz Leoparda (Mac OS X 10.5) lub nowszego, możesz użyć aplikacji Instruments, aby znaleźć i śledzić wycieki pamięci. Po zbudowaniu programu w Xcode wybierz Uruchom > zacznij od Narzędzia wydajności > przecieki.

Nawet jeśli aplikacja nie pokazuje żadnych przecieków, możesz trzymać obiekty zbyt długo. W instrumentach można do tego użyć instrumentu ObjectAlloc. Wybierz instrument ObjectAlloc w dokumencie Instruments i wyświetl szczegóły instrumentu (jeśli nie jest już pokazane) wybierając Widok > szczegóły (powinien mieć znacznik wyboru obok). W sekcji" alokacja żywotności " w objectalloc detail, upewnij się, że wybierzesz przycisk radiowy obok "Created & Still Living".

Teraz, gdy przestaniesz nagrywać swoją aplikację, wybranie narzędzia ObjectAlloc pokaże Ci, ile jest referencji do każdego wciąż żywego obiektu w Twojej aplikacji w kolumnie "# Net". Upewnij się, że nie tylko patrzysz na własne zajęcia, ale także na zajęcia twojego Obiekty najwyższego poziomu plików NIB. Na przykład, jeśli nie masz okien na ekranie i widzisz odniesienia do wciąż żyjącego NSWindow, być może nie wydałeś go w swoim kodzie.

 22
Author: mj1531,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-01 16:57:52

Posprzątaj w dealloc.

Jest to jedna z najłatwiejszych rzeczy do zapomnienia - esp. podczas kodowania z prędkością 150 km / h. Zawsze, zawsze, zawsze Wyczyść swoje atrybuty/zmienne członkowskie w dealloc.

Lubię używać atrybutów Objc 2 - z nową notacją kropkową - dzięki temu sprzątanie jest bezbolesne. Często tak proste jak:

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

To zajmie się wydaniem i ustawi atrybut na NULL (co uważam za programowanie defensywne - w przypadku, gdy inna metoda dalej w dealloc uzyskuje dostęp do zmiennej member ponownie-rzadko, ale Może się zdarzyć).

Z włączonym GC w wersji 10.5, nie jest to już tak potrzebne - ale nadal możesz potrzebować wyczyścić inne zasoby, które tworzysz, możesz to zrobić w metodzie finalize.

 21
Author: schwa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-28 20:53:43

Wszystkie te komentarze są świetne, ale jestem naprawdę zaskoczony, że nikt nie wspomniał o Objective-C Style Guide Google , który został opublikowany jakiś czas temu. Myślę, że wykonali bardzo dokładną pracę.

 17
Author: slf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-16 19:27:06

Również temat częściowo związany (z miejscem na Więcej odpowiedzi!):

Co to są te małe Xcode tips & tricks chcesz wiedzieć o 2 lata temu?.

 15
Author: schwa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:39

Nie zapominaj, że NSWindowController i NSViewController wydadzą obiekty najwyższego poziomu plików NIB, którymi zarządzają.

Jeśli ręcznie załadujesz plik NIB, jesteś odpowiedzialny za zwolnienie obiektów najwyższego poziomu, gdy skończysz z nimi.

 13
Author: mj1531,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-01 17:02:07

Jeden dość oczywisty dla początkujących: użyj funkcji automatycznego wcięcia Xcode dla kodu. Nawet jeśli kopiujesz / wklejasz z innego źródła, po wklejeniu kodu możesz wybrać cały blok kodu, kliknąć go prawym przyciskiem myszy, a następnie wybrać opcję ponownego wcięcia wszystkiego w tym bloku.

Xcode faktycznie przetworzy tę sekcję i wcięje ją na podstawie nawiasów, pętli itp. Jest o wiele bardziej wydajny niż naciśnięcie spacji lub klawisza tab dla każda linia.

 12
Author: iWasRobbed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-28 20:54:05

Wiem, że przeoczyłem to, gdy po raz pierwszy dostałem się do programowania Cocoa.

Upewnij się, że rozumiesz obowiązki zarządzania pamięcią dotyczące plików NIB. Jesteś odpowiedzialny za zwolnienie obiektów najwyższego poziomu w każdym załadowanym pliku NIB. Przeczytaj dokumentację Apple na ten temat.

 10
Author: mj1531,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-01 16:19:14

Włącz wszystkie ostrzeżenia GCC, a następnie wyłącz te, które są regularnie powodowane przez nagłówki Apple, aby zmniejszyć hałas.

Często uruchamiaj analizę statyczną Clang; możesz włączyć ją dla wszystkich kompilacji za pomocą ustawienia kompilacji "Uruchom Analizator statyczny".

Pisz testy jednostkowe i uruchamiaj je przy każdej kompilacji.

 10
Author: oefe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-18 18:12:12

Zmienne i właściwości

1 / utrzymanie nagłówków w czystości, ukrywanie implementacji
Nie dołączaj zmiennych instancji do nagłówka. Prywatne zmienne umieszczone w klasie kontynuacja jako właściwości. Publiczne zmienne deklarują jako publiczne właściwości w nagłówku. Jeśli ma być tylko odczytywana, zadeklaruj ją jako readonly i Nadpisz ją jako readwrite w klasie continutation. Zasadniczo nie używam w ogóle zmiennych, tylko właściwości.

2 / Nadaj swoim właściwościom nie domyślną nazwa zmiennej, przykład:


@synthesize property = property_;

Powód 1: wyłapujesz błędy spowodowane zapomnieniem "ja"."przy cesji nieruchomości. Powód 2: z moich eksperymentów wynika, że analizator wycieków w instrumentach ma problemy z wykryciem wycieku z domyślną nazwą.

3 / nigdy nie używaj Zachowaj lub zwolnij bezpośrednio na właściwości (lub tylko w bardzo wyjątkowych sytuacjach). W Twoim dealloc wystarczy przypisać im zero. Właściwości zachowawcze mają na celu samodzielne utrzymanie/zwolnienie. Nigdy nie wiadomo, czy seter jest nie, na przykład, dodawanie lub usuwanie obserwatorów. Powinieneś używać zmiennej bezpośrednio tylko wewnątrz jej settera i gettera.

Views

1 / Umieść definicję każdego widoku w xib, jeśli możesz(wyjątkiem są zazwyczaj dynamiczne ustawienia zawartości i warstw). Oszczędza czas (jest to łatwiejsze niż pisanie kodu), jest łatwe do zmiany i utrzymuje kod w czystości.

2 / nie próbuj optymalizować widoków zmniejszając liczbę wyświetleń. Nie twórz UIImageView w kodzie zamiast xib tylko dlatego, że chcesz dodać do niego podglądy. Zamiast tego użyj UIImageView jako tła. Framework widoku może obsłużyć setki widoków bez problemów.

3 / Iboutlety nie muszą być zawsze zachowane (lub mocne). Zauważ, że większość Twoich Iboutletów jest częścią twojej hierarchii widoków i dlatego jest niejawnie zachowana.

4 / zwolnij wszystkie Iboutlety w viewDidUnload

5 / wywołanie viewDidUnload z metody dealloc. Nie jest to dorozumiane dzwoniłem.

Pamięć

1 / Obiekty Autorelease podczas ich tworzenia. Wiele błędów jest powodowanych przez przeniesienie wywołania release do jednej gałęzi if-else lub po instrukcji return. Release zamiast autorelease powinien być używany tylko w wyjątkowych sytuacjach - np. gdy czekasz na runloop i nie chcesz, aby twój obiekt był autoreleased zbyt wcześnie.

2 / nawet jeśli używasz Authomatic Reference Counting, musisz doskonale zrozumieć, jak zachować-zwolnić metody działają. Używanie ręcznego zatrzymywania i uwalniania nie jest bardziej skomplikowane niż ARC, w obu przypadkach musisz myśleć o przeciekach i cyklach zatrzymywania. Rozważ ręczne używanie funkcji zachowaj-zwolnij w dużych projektach lub skomplikowanych hierarchiach obiektów.

Komentarze

1 / Dokonaj autodokumentacji kodu. Każda nazwa zmiennej i nazwa metody powinny wskazywać, co ona robi. Jeśli kod jest napisany poprawnie( potrzebujesz w tym dużo praktyki), nie będziesz potrzebował żadnych komentarzy do kodu (nie tego samego co komentarze do dokumentacji). Algorytmy mogą być skomplikowane, ale kod powinien być zawsze prosty.

2 / czasami potrzebny jest komentarz. Zazwyczaj w celu opisania nieoczywistego zachowania kodu lub włamania. Jeśli czujesz, że musisz napisać komentarz, najpierw spróbuj przepisać kod, aby był prostszy i bez potrzeby komentarzy.

Wcięcie

1 / nie zwiększaj zbytnio wcięć. Większość kodu metody powinna być wcięta na poziomie metody. Zagnieżdżone bloki (if, for itd.) zmniejsz czytelność. Jeśli masz trzy zagnieżdżone bloki, powinieneś spróbować umieścić wewnętrzne bloki w osobnej metodzie. Cztery lub więcej zagnieżdżonych bloków nie powinno być nigdy używane. Jeśli większość kodu metody znajduje się wewnątrz if, neguj warunek if, przykład:


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

return self;


if (!self) {
   return nil;
}

//... long initialization code ...

return self;

Zrozumieć kod C, głównie struktury C

Zauważ, że Obj-C jest tylko lekką warstwą OOP nad językiem C. Powinieneś zrozumieć, jak działają podstawowe struktury kodu w C (enums, structs, arrays, pointers itp.). Przykład:


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

Jest tym samym co:


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

I wiele innych

Stwórz własny dokument standardów kodowania i często go Aktualizuj. Spróbuj uczyć się na błędach. Zrozum, dlaczego powstał błąd i staraj się go unikać używając standardów kodowania.

Nasze standardy kodowania mają obecnie około 20 stron, mieszankę standardów kodowania Java, standardy Google Obj-C / C++ i nasze własne dodatki. Dokumentuj kod, używaj standardowych standardowych wcięć, białych spacji i pustych linii w odpowiednich miejscach itp.

 10
Author: Sulthan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-19 03:16:31

Być bardziej funkcjonalne.

Objective-C jest językiem zorientowanym obiektowo, ale Cocoa Framework functional-style jest świadomy i w wielu przypadkach projektowany jest w stylu funkcjonalnym.
  1. Istnieje oddzielenie zmienności. Użyj klas immutable jako podstawowych, a obiekt zmienny jako drugorzędnych. Na przykład, używaj przede wszystkim NSArray i używaj NSMutableArray tylko wtedy, gdy potrzebujesz.

  2. Istnieją czyste funkcje. Nie tak wiele, kupić wiele Framework API są zaprojektowany jak czysta funkcja. Spójrz na funkcje takie jak CGRectMake() lub CGAffineTransformMake(). Oczywiście forma wskaźnika wygląda bardziej wydajnie. Jednak argument pośredni ze wskaźnikami nie może oferować efektu ubocznego. Projektuj konstrukcje w jak największym stopniu. Oddziel nawet obiekty stanu. Użyj -copy zamiast -retain podczas przekazywania wartości do innego obiektu. Ponieważ współdzielony stan może po cichu wpływać na wartość w innym obiekcie. Więc nie może być bez skutków ubocznych. Jeśli masz wartość z obiektu external from, skopiuj ją. Więc ważne jest również zaprojektowanie stanu współdzielonego jak najmniejszego.

Nie bój się jednak używać nieczystych funkcji.

  1. Jest leniwa ocena. Zobacz coś w rodzaju -[UIViewController view] property. Widok nie zostanie utworzony podczas tworzenia obiektu. Zostanie utworzona przy pierwszym odczycie właściwości view wywołującego. UIImage nie zostanie załadowany, dopóki nie zostanie narysowany. Istnieje wiele realizacji takich jak ten projekt. Tego rodzaju projekty są bardzo pomocne do zarządzania zasobami, ale jeśli nie znasz pojęcia leniwej oceny, nie jest łatwo zrozumieć ich zachowanie.

  2. Jest zakończenie. Użyj C-bloki jak najwięcej. To znacznie uprości twoje życie. Ale przeczytaj jeszcze raz o zarządzaniu pamięcią blokową przed jej użyciem.

  3. Jest pół-auto GC. NSAutoreleasePool. Użyj -autorelease podstawowej. Użyj ręcznego -retain/-release wtórnego, gdy naprawdę potrzebujesz. (np. Optymalizacja pamięci, jawny zasób delecja)

 9
Author: Eonil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-30 02:59:04