W moim obecnym projekcie używam UALoggera . Nie loguje się do produkcji , jeśli nie poprosisz o to wyraźnie. I ma inne zalety w stosunku do zwykłego NSLog, takie jak poziomy ważności (z DEBUG , INFO itp.) Po wyjęciu z pudełka. Dobra robota!
Anton Gaenko,
1
Odpowiadając na pytanie „czy będzie działać lepiej?” Tak, ale uzyskany zysk zależy od tego, ile NSLog()masz w swojej aplikacji. NSLog()wymaga czasu na wykonanie i dodaje dodatkowe obciążenie do środowiska uruchomieniowego aplikacji. W każdym razie, jeśli pomaga to w działaniu z prostym makrem preprocesora DEBUG, to powinniśmy je wyłączyć.
Scott,
Sugerowałbym również, że jeśli masz dużo instrukcji NSLog / print w swoim kodzie, może to zasugerować, że powinieneś poświęcić trochę czasu na poznanie debuggera. Regularnie ustawiam punkty przerwania, które drukują informacje, które mnie interesują, i automatycznie kontynuuję. Tak, może trochę spowolnić bieg, ale w większości przypadków nie jest przytłaczający. Ponadto warunkowe przerwy, abyś mógł zbadać, kiedy wydarzyło się coś nieoczekiwanego.
bshirley,
Odpowiedzi:
127
Jednym ze sposobów jest przejście do ustawień kompilacji i w ramach konfiguracji debugowania dodanie wartości do wartości „Preprocessor Macros”, na przykład:
DEBUG_MODE=1
Upewnij się, że robisz to tylko dla konfiguracji debugowania, a nie dla wersji Beta lub Release. Następnie we wspólnym pliku nagłówkowym możesz zrobić coś takiego:
Teraz zamiast NSLog używać DLogwszędzie. Podczas testowania i debugowania otrzymasz komunikaty debugowania. Kiedy jesteś gotowy do wydania wersji beta lub ostatecznej, wszystkie te DLogwiersze automatycznie stają się puste i nic nie jest emitowane. W ten sposób nie ma ręcznego ustawiania zmiennych ani komentowania NSLogswymaganych. Wystarczy wybrać cel kompilacji.
W Xcode 4.5 daje ostrzeżenie, które mówi: „Niejawna deklaracja funkcji 'DLog' jest nieprawidłowa w C99”, więc ta rzecz nie działa.
Sergey Grischyov
2
@SergiusGee: Otrzymujesz niejawne ostrzeżenie o deklaracji, jeśli nie można znaleźć deklaracji funkcji, w takim przypadku myśli, że próbujesz ją zadeklarować. Upewnij się, że Twoja klasa ma dostęp do pliku nagłówkowego, w którym jest to zadeklarowane.
sudo rm -rf
1
Nie rezygnuję z wylogowywania się, ponieważ pozbawia Cię to możliwości otrzymywania lepszych raportów o błędach od użytkowników. użyj rejestrowania asynchronicznego i logLevels, aby ograniczyć wydajność do prawie zera! (patrz cocoa lumberjack lub java's log4j
Daij-Djan
2
Wybrałbym #if zamiast #ifdef, ponieważ DEBUG_MODE 0 nadal będzie podążał prawdziwą ścieżką
Grady Player
1
to nie odpowiada na pytanie
Martin Mlostek
117
Aktualizacja dla Xcode 5 i iOS 7
Uwaga: w przypadku rozwiązania Xcode 7 / Swift 2.1 do usuwania instrukcji print () w kompilacji wydania, moją odpowiedź znajdziesz tutaj .
Tak, powinieneś usunąć wszelkie instrukcje NSLog z kodu wydania, ponieważ spowalnia to twój kod i nie ma żadnego zastosowania w wydanej wersji. Na szczęście w Xcode 5 (iOS 7) niezwykle proste jest usunięcie wszystkich instrukcji NSLog „automatycznie” w kompilacjach wydań. Więc dlaczego tego nie zrobić.
Najpierw 3 kroki do wykonania, a następnie wyjaśnienia
1) w swoim projekcie Xcode znajdź plik „yourProjectName-prefix.pch” (zwykle znajdziesz go w grupie „Support files”), w której znajduje się Twój plik main.m
2) dodaj te 3 wiersze na końcu pliku „.pch”:
#ifndef DEBUG
#defineNSLog(...);#endif
3) sprawdź różnicę między wersją do debugowania a wersją do wydania. Jednym ze sposobów jest skorzystanie z opcji „edytuj schemat” -> „uruchom nazwę aplikacji” -> w zakładce „informacje” wybierz za pomocą menu rozwijanego między debugowaniem a wydaniem. W wydanej wersji nie zobaczysz żadnych wyników NSLog w konsoli debugowania!
Jak to wszystko działa?
Przede wszystkim trzeba wiedzieć, że preprocesor jest stosunkowo „głupi” i po prostu działa jako „zamiennik tekstu” przed wywołaniem kompilatora. Zastępuje wszystko, co „# zdefiniujesz”, tym, co następuje po #defineinstrukcji.
#defineNSLog(...);
(...)Oznacza „coś” między nawiasami (). Zwróć także uwagę ;na koniec. Nie jest to absolutnie konieczne, ponieważ kompilator to zoptymalizuje, ale lubię to tam umieścić, ponieważ jest bardziej „poprawne”. Po naszym #definenie ma „nic”, więc preprocesor zamieni go na „nic”, a więc po prostu wyrzuci całą linię, zaczynając od NSLog...do i włączając ;.
Zdefiniuj instrukcje można uczynić warunkowymi za pomocą #ifdef(jeśli zdefiniowano) lub #ifndef(jeśli nie zdefiniowano)
tutaj piszemy #ifndef DEBUG, co oznacza „jeśli symbol DEBUG nie jest zdefiniowany”. #ifdefAlbo #ifndeftrzeba być „zamknięty” z#endif
Xcode 5 domyślnie definiuje dla nas symbol „DEBUG”, gdy tryb kompilacji to „DEBUG”. W „wersji” nie jest to zdefiniowane. możesz to sprawdzić w ustawieniach projektu, zakładka „Ustawienia kompilacji” -> przewiń w dół do sekcji „Apple LLVM 5.0 - Przetwarzanie wstępne” -> makra preprocesora. Zobaczysz, że symbol „DEBUG” nie jest zdefiniowany dla kompilacji wydań!
na koniec plik .pch jest tworzony automatycznie przez Xcode i automatycznie dołączany do każdego pliku źródłowego podczas kompilacji. To tak, jakbyś umieścił całość #definew każdym z plików źródłowych.
Dzięki @Whasssaaahhh, działa świetnie. Uważaj, aby nie umieszczać kodu w instrukcjach dziennika! Preprocesor usunie całe NSLoginstrukcje bez względu na to, co jest w środku.
Eric Platon
1
Jeśli jest to starszy projekt, który nie ma flagi debugowania w preprocessor makrach, należy dodać parametr „debug = 1” dla projektu, a nie celu
Niemal wszystkie powyższe odpowiedzi sugerują rozwiązanie, ale nie wyjaśniają problemu. Wyszukałem w google i znalazłem powód. Oto moja odpowiedź:
Tak, jeśli skomentujesz NSLog w swojej wydanej wersji, wydajność będzie lepsza. Ponieważ NSLog działa dość wolno. Czemu? NSLog zrobi dwie rzeczy 1) zapisze komunikaty dziennika do Apple System Logging (ASL), 2) jeśli aplikacja działa w xcode, zapisze również na stderr.
Główny problem tkwi w pierwszym. Aby zapewnić bezpieczeństwo wątków, za każdym razem , gdy wywoływany jest NSLog, otwiera połączenie z narzędziem ASL , wysyła wiadomość i zamyka połączenie. Operacja połączenia jest bardzo droga. Innym powodem jest to, że NSLog poświęca trochę czasu na pobranie sygnatury czasowej do logowania.
Oprócz wszystkich osób, które mądrze skomentowały, że nie dzwonienie NSLog()w ogóle w produkcji działa nieco szybciej, dodam, że:
Wszystkie te NSLog()ciągi wyjściowe są widoczne dla każdego, kto pobierze aplikację ze sklepu i uruchomi ją z urządzeniem podłączonym do komputera Mac z uruchomionym Xcode (przez okno Organizatora).
W zależności od tego, jakie informacje rejestrujesz (a zwłaszcza jeśli aplikacja kontaktuje się z serwerem, przeprowadza uwierzytelnianie itp.), Może to być poważny problem z bezpieczeństwem .
dzięki za info - czy to jest gdzieś w dokumencie, czy właśnie sam to odkryłeś? Czy nadal dotyczy to drukowania w języku Swift?
Ronny Webers
Nie pamiętam, żebym czytał jakąkolwiek dokumentację. Właśnie zainstalowałem moją zarchiwizowaną kompilację (ten sam plik binarny, który przesłałem do sklepu) na moim urządzeniu i podłączyłem ją do Xcode. Nie mam pojęcia, czy to samo dotyczy Swifta print(), ale najprawdopodobniej tak jest.
Nicolas Miari,
@NicolasMiari Co masz na myśli mówiąc, że jest podłączony do Xcode? Jak możemy podłączyć nasz plik binarny do Xcode, właściwie chcę spróbować tego samego. Więc proszę zasugeruj. Dzięki.
iDevAmit
@iDeveloper Mam na myśli pobranie aplikacji z AppStore na urządzenie (np. iPhone), podłączenie tego urządzenia do Xcode przez USB, uruchomienie aplikacji i oglądanie logów w oknie „Urządzenia” Xcode.
Nicolas Miari
3
@Whasssaaahhh print nie jest wyświetlany w konsoli urządzenia .. Właśnie to przetestowałem
Anish Parajuli 웃
13
W bieżącym domyślnym ustawieniu projektu w Xcode NS_BLOCK_ASSERTIONSmakro zostanie ustawione na 1 w wersji wydania i DEBUG=1wersji debugowania.
Więc wolę następującą metodę.
// NS_BLOCK_ASSERTIONS is defined by default, as shown in the screenshot above.// Or, you can define yourself Flags in the `Other C Flags` -> `Release`.#ifndef NS_BLOCK_ASSERTIONS
#define _DEBUG
#endif#ifdef _DEBUG
// for debug mode #defineDLog(fmt,...)NSLog(@"%s " fmt, __FUNCTION,##__VA_ARGS__) .../// something extra#else// for release mode#defineDLog(fmt,...)/* throw it away */.../// something extra#endif
Tak, powinieneś to wyłączyć. Zwłaszcza jeśli próbujesz zmaksymalizować szybkość swojego kodu. NSLogging rzeczy lewy i prawy zanieczyszcza dziennik systemowy, który inni programiści mogą próbować przekopać i może mieć duży wpływ na kod krytyczny dla szybkości (wewnątrz pętli itp.) Przypadkowo zostawiłem kilka komunikatów dziennika w funkcji rekurencyjnej i muszę wydać aktualizację z „30% wzrostem szybkości!” parę tygodni później... ;-)
Wszystkie dobre odpowiedzi, ale oto kolejna mała sztuczka, którą możesz rozważyć, głównie w fazach programowania / testowania aplikacji.
Może to być również przydatne w przypadku kodu wydania aplikacji, jeśli chcesz wyłączyć tylko SWÓJ kod debugowania, a nie komunikaty, które mogą wskazywać na problemy poza bezpośrednią kontrolą kodu.
Sztuczka:
Możesz wyłączyć NSLog dla każdego pliku .m, po prostu dołączając następujący wiersz na górze pliku .m :
#defineNSLog(...)
( UWAGA: NIE umieszczaj tego pliku .h, tylko plik .m! )
To po prostu sprawia, że kompilator ocenia NSLog(), rozszerzając zamiast tego makro preprocesora. Makro nie robi nic poza obcinaniem argumentów.
jeśli chcesz go ponownie włączyć, zawsze możesz użyć
#undefNSLog
Możesz na przykład po prostu uniemożliwić wywołanie NSLog wokół określonej grupy metod, wykonując coś takiego jak
NSLog jest powolny i nie powinien być używany do kompilacji wydań. Proste makro, takie jak to poniżej, wyłączy je wraz z wszelkimi potwierdzeniami, które możesz mieć, które również powinny być wyłączone. W mniej powszechnym przypadku, gdy potrzebujesz NSLog w kompilacji wydania, po prostu wywołaj go bezpośrednio. Nie zapomnij dodać „-DNDEBUG” do ustawień kompilacji „innych flag c”.
Jest to miłe, ale nadal występuje problem z całym narzutem wywołań i każdym narzutem (i potencjalnymi efektami ubocznymi) obliczania wszelkich argumentów przekazywanych do Dlogfunkcji.
NSLog()
masz w swojej aplikacji.NSLog()
wymaga czasu na wykonanie i dodaje dodatkowe obciążenie do środowiska uruchomieniowego aplikacji. W każdym razie, jeśli pomaga to w działaniu z prostym makrem preprocesora DEBUG, to powinniśmy je wyłączyć.Odpowiedzi:
Jednym ze sposobów jest przejście do ustawień kompilacji i w ramach konfiguracji debugowania dodanie wartości do wartości „Preprocessor Macros”, na przykład:
Upewnij się, że robisz to tylko dla konfiguracji debugowania, a nie dla wersji Beta lub Release. Następnie we wspólnym pliku nagłówkowym możesz zrobić coś takiego:
Teraz zamiast
NSLog
używaćDLog
wszędzie. Podczas testowania i debugowania otrzymasz komunikaty debugowania. Kiedy jesteś gotowy do wydania wersji beta lub ostatecznej, wszystkie teDLog
wiersze automatycznie stają się puste i nic nie jest emitowane. W ten sposób nie ma ręcznego ustawiania zmiennych ani komentowaniaNSLogs
wymaganych. Wystarczy wybrać cel kompilacji.źródło
Aktualizacja dla Xcode 5 i iOS 7
Uwaga: w przypadku rozwiązania Xcode 7 / Swift 2.1 do usuwania instrukcji print () w kompilacji wydania, moją odpowiedź znajdziesz tutaj .
Tak, powinieneś usunąć wszelkie instrukcje NSLog z kodu wydania, ponieważ spowalnia to twój kod i nie ma żadnego zastosowania w wydanej wersji. Na szczęście w Xcode 5 (iOS 7) niezwykle proste jest usunięcie wszystkich instrukcji NSLog „automatycznie” w kompilacjach wydań. Więc dlaczego tego nie zrobić.
Najpierw 3 kroki do wykonania, a następnie wyjaśnienia
1) w swoim projekcie Xcode znajdź plik „yourProjectName-prefix.pch” (zwykle znajdziesz go w grupie „Support files”), w której znajduje się Twój plik main.m
2) dodaj te 3 wiersze na końcu pliku „.pch”:
3) sprawdź różnicę między wersją do debugowania a wersją do wydania. Jednym ze sposobów jest skorzystanie z opcji „edytuj schemat” -> „uruchom nazwę aplikacji” -> w zakładce „informacje” wybierz za pomocą menu rozwijanego między debugowaniem a wydaniem. W wydanej wersji nie zobaczysz żadnych wyników NSLog w konsoli debugowania!
Jak to wszystko działa?
Przede wszystkim trzeba wiedzieć, że preprocesor jest stosunkowo „głupi” i po prostu działa jako „zamiennik tekstu” przed wywołaniem kompilatora. Zastępuje wszystko, co „# zdefiniujesz”, tym, co następuje po
#define
instrukcji.(...)
Oznacza „coś” między nawiasami (). Zwróć także uwagę;
na koniec. Nie jest to absolutnie konieczne, ponieważ kompilator to zoptymalizuje, ale lubię to tam umieścić, ponieważ jest bardziej „poprawne”. Po naszym#define
nie ma „nic”, więc preprocesor zamieni go na „nic”, a więc po prostu wyrzuci całą linię, zaczynając odNSLog...
do i włączając;
.Zdefiniuj instrukcje można uczynić warunkowymi za pomocą
#ifdef
(jeśli zdefiniowano) lub#ifndef
(jeśli nie zdefiniowano)tutaj piszemy
#ifndef DEBUG
, co oznacza „jeśli symbol DEBUG nie jest zdefiniowany”.#ifdef
Albo#ifndef
trzeba być „zamknięty” z#endif
Xcode 5 domyślnie definiuje dla nas symbol „DEBUG”, gdy tryb kompilacji to „DEBUG”. W „wersji” nie jest to zdefiniowane. możesz to sprawdzić w ustawieniach projektu, zakładka „Ustawienia kompilacji” -> przewiń w dół do sekcji „Apple LLVM 5.0 - Przetwarzanie wstępne” -> makra preprocesora. Zobaczysz, że symbol „DEBUG” nie jest zdefiniowany dla kompilacji wydań!
na koniec plik .pch jest tworzony automatycznie przez Xcode i automatycznie dołączany do każdego pliku źródłowego podczas kompilacji. To tak, jakbyś umieścił całość
#define
w każdym z plików źródłowych.źródło
NSLog
instrukcje bez względu na to, co jest w środku.NSLog
też instrukcjiif(AllCool) NSLog(@"Cool!Do Nothing!"); else...
NSLog
if(AllCool) {NSLog(@"Cool!Do Nothing!");} else...
Niemal wszystkie powyższe odpowiedzi sugerują rozwiązanie, ale nie wyjaśniają problemu. Wyszukałem w google i znalazłem powód. Oto moja odpowiedź:
Tak, jeśli skomentujesz NSLog w swojej wydanej wersji, wydajność będzie lepsza. Ponieważ NSLog działa dość wolno. Czemu? NSLog zrobi dwie rzeczy 1) zapisze komunikaty dziennika do Apple System Logging (ASL), 2) jeśli aplikacja działa w xcode, zapisze również na stderr.
Główny problem tkwi w pierwszym. Aby zapewnić bezpieczeństwo wątków, za każdym razem , gdy wywoływany jest NSLog, otwiera połączenie z narzędziem ASL , wysyła wiadomość i zamyka połączenie. Operacja połączenia jest bardzo droga. Innym powodem jest to, że NSLog poświęca trochę czasu na pobranie sygnatury czasowej do logowania.
Odniesienie stąd .
źródło
Moim ulubionym jest używanie wariadycznego makra.
źródło
Oprócz wszystkich osób, które mądrze skomentowały, że nie dzwonienie
NSLog()
w ogóle w produkcji działa nieco szybciej, dodam, że:Wszystkie te
NSLog()
ciągi wyjściowe są widoczne dla każdego, kto pobierze aplikację ze sklepu i uruchomi ją z urządzeniem podłączonym do komputera Mac z uruchomionym Xcode (przez okno Organizatora).W zależności od tego, jakie informacje rejestrujesz (a zwłaszcza jeśli aplikacja kontaktuje się z serwerem, przeprowadza uwierzytelnianie itp.), Może to być poważny problem z bezpieczeństwem .
źródło
print()
, ale najprawdopodobniej tak jest.W bieżącym domyślnym ustawieniu projektu w Xcode
NS_BLOCK_ASSERTIONS
makro zostanie ustawione na 1 w wersji wydania iDEBUG=1
wersji debugowania.Więc wolę następującą metodę.
źródło
Tak, powinieneś to wyłączyć. Zwłaszcza jeśli próbujesz zmaksymalizować szybkość swojego kodu. NSLogging rzeczy lewy i prawy zanieczyszcza dziennik systemowy, który inni programiści mogą próbować przekopać i może mieć duży wpływ na kod krytyczny dla szybkości (wewnątrz pętli itp.) Przypadkowo zostawiłem kilka komunikatów dziennika w funkcji rekurencyjnej i muszę wydać aktualizację z „30% wzrostem szybkości!” parę tygodni później... ;-)
źródło
Wszystkie dobre odpowiedzi, ale oto kolejna mała sztuczka, którą możesz rozważyć, głównie w fazach programowania / testowania aplikacji.
Może to być również przydatne w przypadku kodu wydania aplikacji, jeśli chcesz wyłączyć tylko SWÓJ kod debugowania, a nie komunikaty, które mogą wskazywać na problemy poza bezpośrednią kontrolą kodu.
Sztuczka:
Możesz wyłączyć NSLog dla każdego pliku .m, po prostu dołączając następujący wiersz na górze pliku .m :
( UWAGA: NIE umieszczaj tego pliku .h, tylko plik .m! )
To po prostu sprawia, że kompilator ocenia
NSLog()
, rozszerzając zamiast tego makro preprocesora. Makro nie robi nic poza obcinaniem argumentów.jeśli chcesz go ponownie włączyć, zawsze możesz użyć
Możesz na przykład po prostu uniemożliwić wywołanie NSLog wokół określonej grupy metod, wykonując coś takiego jak
źródło
NSLog jest powolny i nie powinien być używany do kompilacji wydań. Proste makro, takie jak to poniżej, wyłączy je wraz z wszelkimi potwierdzeniami, które możesz mieć, które również powinny być wyłączone. W mniej powszechnym przypadku, gdy potrzebujesz NSLog w kompilacji wydania, po prostu wywołaj go bezpośrednio. Nie zapomnij dodać „-DNDEBUG” do ustawień kompilacji „innych flag c”.
źródło
w pliku pch zapisz to przed #endif
źródło
a co z tym?
źródło
Spowoduje to również zaakceptowanie dodatkowych argumentów. Tylko wartość parametru showDebugLogs na true lub false, zgodnie z potrzebami
źródło
Dlog
funkcji.