Powiedziano mi to kilka razy w tej samej witrynie, ale chciałem się upewnić, że tak jest naprawdę.
Spodziewałem się, że będę w stanie obsypać wywołania funkcji NSLog w całym kodzie i że Xcode / gcc automatycznie usunie te wywołania podczas budowania moich kompilacji Release / Distribution.
Czy powinienem tego unikać? Jeśli tak, jakie alternatywy są najczęstsze między doświadczonymi programistami Objective-C?
iphone
objective-c
nslog
jpm
źródło
źródło
Odpowiedzi:
Makra preprocesora są rzeczywiście świetne do debugowania. Nie ma nic złego w NSLog (), ale łatwo jest zdefiniować własną funkcję logowania z lepszą funkcjonalnością. Oto ten, którego używam, zawiera nazwę pliku i numer wiersza, aby ułatwić śledzenie wyciągów dziennika.
Okazało się, że łatwiej było umieścić całą instrukcję w nagłówku prefiksu niż we własnym pliku. Możesz, jeśli chcesz, zbudować bardziej skomplikowany system logowania poprzez interakcję DebugLog z normalnymi obiektami Objective-C. Na przykład, możesz mieć klasę rejestrowania, która zapisuje do swojego własnego pliku dziennika (lub bazy danych) i zawiera argument `` priorytet '', który możesz ustawić w czasie wykonywania, więc komunikaty debugowania nie są wyświetlane w Twojej wersji, ale komunikaty o błędach to ( jeśli to zrobiłeś, możesz zrobić DebugLog (), WarningLog () i tak dalej).
Aha, i pamiętaj, że
#define DEBUG_MODE
można go ponownie wykorzystać w różnych miejscach w aplikacji. Na przykład w mojej aplikacji używam go do wyłączania sprawdzania kluczy licencyjnych i zezwalania aplikacji na działanie tylko przed określoną datą. To pozwala mi rozpowszechniać ograniczoną czasowo, w pełni funkcjonalną wersję beta przy minimalnym wysiłku z mojej strony.źródło
Umieść te 3 wiersze na końcu pliku -prefix.pch:
Nie musisz niczego definiować w swoim projekcie, ponieważ
DEBUG
jest to domyślnie definiowane w ustawieniach kompilacji podczas tworzenia projektu.źródło
Wywołania NSLog można pozostawić w kodzie produkcyjnym, ale powinny one występować tylko w naprawdę wyjątkowych przypadkach lub w informacjach, które są wymagane, aby były rejestrowane w dzienniku systemowym.
Aplikacje, które zaśmiecają dzienniki systemowe, są denerwujące i postrzegane jako nieprofesjonalne.
źródło
Nie mogę komentować odpowiedzi Marca Charbonneau , więc opublikuję to jako odpowiedź.
Oprócz dodania makra do wstępnie skompilowanego nagłówka, możesz użyć konfiguracji kompilacji docelowej, aby kontrolować definiowanie (lub brak definiowania)
DEBUG_MODE
.W przypadku wybrania opcji „ Debuguj ” aktywna konfiguracja
DEBUG_MODE
zostanie zdefiniowana, a makro rozwinie się do pełnejNSLog
definicji.Wybranie aktywnej konfiguracji „ Wydanie ” nie spowoduje zdefiniowania,
DEBUG_MODE
a twojeNSLog
ging zostanie pominięte w kompilacji wydania.Kroki:
GCC_PREPROCESSOR_DEFINITIONS
)DEBUG_MODE=1
DEBUG_MODE
nie jest ustawioneGCC_PREPROCESSOR_DEFINITIONS
jeśli pominiesz znak „=” w definicji, otrzymasz błąd z preprocesora
Wklej również ten komentarz (pokazany poniżej) nad definicją makra, aby przypomnieć Ci, skąd
DEBUG_MACRO
pochodzi definicja;)źródło
DEBUG_MODE
iDEBUG_MACRO
są niekonwencjonalne. Znalazłem tylko jedno odniesienie do wDEBUG_MACRO
witrynie Apple ( opensource.apple.com/source/gm4/gm4-15/src/m4.h?txt ). Może bardziej standardowyDEBUG
iNDEBUG
byłby lepszym wyborem?NDEBUG
jest określony przez Posix; whileDEBUG
jest używany przez konwencję.EDIT: metoda wysłane przez Marc Charbonneau i zwrócił moją uwagę przez sho , jest o wiele lepszy niż ten.
Usunąłem część mojej odpowiedzi, która sugerowała użycie pustej funkcji do wyłączenia rejestrowania, gdy tryb debugowania jest wyłączony. Część, która dotyczy ustawienia automatycznego makra preprocesora, jest nadal aktualna, więc pozostaje. Zmieniłem również nazwę makra preprocesora, aby lepiej pasowała do odpowiedzi Marca Charbonneau.
Aby osiągnąć automatyczne (i oczekiwane) zachowanie w Xcode:
W ustawieniach projektu przejdź do zakładki „Build” i wybierz konfigurację „Debug”. Znajdź sekcję „Preprocessor Macros” i dodaj makro o nazwie
DEBUG_MODE
....
EDYCJA: Zobacz odpowiedź Marca Charbonneau, aby dowiedzieć się, jak prawidłowo włączać i wyłączać rejestrowanie za pomocą
DEBUG_MODE
makra.źródło
Zgadzam się z Matthew. Nie ma nic złego w NSLog w kodzie produkcyjnym. W rzeczywistości może to być przydatne dla użytkownika. To powiedziawszy, jeśli jedynym powodem używania NSLog jest pomoc w debugowaniu, to tak, powinno to zostać usunięte przed wydaniem.
Co więcej, ponieważ oznaczyłeś to jako pytanie dotyczące iPhone'a, NSLog pobiera zasoby, których iPhone ma niewiele. Jeśli nie rejestrujesz niczego na iPhonie, zabiera to czas procesora Twojej aplikacji. Używaj rozważnie.
źródło
Prosta prawda jest taka, że NSLog jest po prostu wolny.
Ale dlaczego? Aby odpowiedzieć na to pytanie, dowiedzmy się, co robi NSLog i jak to robi.
Co dokładnie robi NSLog?
NSLog robi 2 rzeczy:
Zapisuje komunikaty dziennika w narzędziu Apple System Logging (asl). Umożliwia to wyświetlanie komunikatów dziennika w Console.app. Sprawdza również, czy strumień stderr aplikacji trafia do terminala (na przykład, gdy aplikacja jest uruchamiana przez Xcode). Jeśli tak, zapisuje komunikat dziennika na stderr (tak, aby pojawił się w konsoli Xcode).
Pisanie do STDERR nie wydaje się trudne. Można to osiągnąć za pomocą fprintf i odwołania do deskryptora pliku stderr. Ale co z asl?
Najlepszą dokumentacją dotyczącą ASL, jaką znalazłem, jest 10-częściowy post na blogu autorstwa Petera Hoseya: link
Bez wchodzenia w szczegóły, najważniejsza (jeśli chodzi o wydajność) jest:
Aby wysłać komunikat dziennika do narzędzia ASL, po prostu otwierasz połączenie klienta z demonem ASL i wysyłasz wiadomość. ALE - każdy wątek musi używać osobnego połączenia klienta. Tak więc, aby zapewnić bezpieczeństwo wątków, za każdym razem, gdy wywoływany jest NSLog, otwiera nowe połączenie klienta asl, wysyła wiadomość, a następnie zamyka połączenie.
Zasoby można znaleźć tutaj i tutaj .
źródło
Jak zauważono w innych odpowiedziach, możesz użyć #define, aby zmienić, czy NSLog jest używany, czy nie w czasie kompilacji.
Jednak bardziej elastycznym sposobem jest użycie biblioteki rejestrowania, takiej jak Cocoa Lumberjack , która pozwala zmienić, czy coś jest również rejestrowane w czasie wykonywania.
W kodzie zamień NSLog na DDLogVerbose lub DDLogError itp., Dodaj #import dla definicji makr itp. I skonfiguruj rejestratory, często w metodzie applicationDidFinishLaunching.
Aby mieć taki sam efekt jak NSLog, kod konfiguracyjny to
źródło
Z punktu widzenia bezpieczeństwa zależy to od tego, co jest rejestrowane. Jeśli
NSLog
(lub inne rejestratory) zapisują poufne informacje, należy usunąć rejestrator w kodzie produkcyjnym.Z punktu widzenia audytu audytor nie chce patrzeć na każde użycie,
NSLog
aby upewnić się, że nie rejestruje poufnych informacji. On / ona po prostu powie ci, żebyś usunął rejestrator.Pracuję z obiema grupami. Audytujemy kod, piszemy przewodniki po kodowaniu, itp. Nasz przewodnik wymaga wyłączenia logowania w kodzie produkcyjnym. Więc wewnętrzne zespoły wiedzą, żeby tego nie próbować;)
Odrzucimy również zewnętrzną aplikację, która loguje się w środowisku produkcyjnym, ponieważ nie chcemy zaakceptować ryzyka związanego z przypadkowym wyciekiem poufnych informacji. Nie obchodzi nas, co powie nam programista. Po prostu nie warto poświęcać nam czasu na badanie.
I pamiętaj, że definiujemy „wrażliwy”, a nie dewelopera;)
Postrzegam również aplikację, która wykonuje wiele operacji logowania, jako aplikację gotową do implodowania. Jest powód, dla którego rejestrowanie jest wykonywane / potrzebne, a zwykle nie jest to stabilne. Jest tam z wątkami „watchdog”, które ponownie uruchamiają zawieszone usługi.
Jeśli nigdy nie przeszedłeś przez przegląd architektury bezpieczeństwa (SecArch), to są rodzaje rzeczy, którym się przyglądamy.
źródło
Nie powinieneś być niepotrzebnie gadatliwy z printf lub NSLog w kodzie wydania. Spróbuj wykonać printf lub NSLog tylko wtedy, gdy aplikacja ma coś złego, IE jest to nieodwracalny błąd.
źródło
Pamiętaj, że NSLogs może spowolnić interfejs użytkownika / główny wątek. Najlepiej jest usunąć je z kompilacji wydania, chyba że jest to absolutnie konieczne.
źródło
Gorąco polecam korzystanie z TestFlight do logowania (za darmo). Ich metoda zastąpi NSLog (przy użyciu makra) i umożliwi włączenie / wyłączenie logowania do ich serwera, dziennika systemu Apple i dziennika STDERR dla wszystkich istniejących wywołań NSLog. Zaletą tego jest to, że nadal możesz przeglądać komunikaty dziennika pod kątem aplikacji wdrożonych na testerach i aplikacji wdrożonych w App Store, bez dzienników pojawiających się w dzienniku systemowym użytkownika. Najlepsze z obu światów.
źródło