Is het waar dat men NSLog() niet mag gebruiken op productiecode?

Dit is mij een paar keer verteld op deze site, maar ik wilde er zeker van zijn dat dit ook echt het geval is.

Ik verwachtte dat ik NSLog-functieaanroepen door mijn code zou kunnen sprenkelen, en dat Xcode/gcc die aanroepen automatisch zou verwijderen bij het bouwen van mijn release-/distributie-builds.

Moet ik dit vermijden? Zo ja, welke alternatieven komen het meest voor bij ervaren Objective-C-programmeurs?


Antwoord 1, autoriteit 100%

Preprocessor-macro’s zijn inderdaad geweldig voor het opsporen van fouten. Er is niets mis met NSLog(), maar het is eenvoudig om uw eigen logfunctie te definiëren met betere functionaliteit. Dit is degene die ik gebruik, het bevat de bestandsnaam en het regelnummer om het gemakkelijker te maken om logverklaringen op te sporen.

#define DEBUG_MODE
#ifdef DEBUG_MODE
    #define DebugLog( s, ... ) NSLog( @"<%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
    #define DebugLog( s, ... ) 
#endif

Ik vond het makkelijker om dit hele statement in de prefix header te plaatsen in plaats van in zijn eigen bestand. Je zou, als je wilde, een ingewikkelder logsysteem kunnen bouwen door DebugLog te laten communiceren met normale Objective-C-objecten. U kunt bijvoorbeeld een logboekklasse hebben die naar zijn eigen logbestand (of database) schrijft en een ‘prioriteit’-argument bevat dat u tijdens runtime zou kunnen instellen, zodat foutopsporingsberichten niet worden weergegeven in uw releaseversie, maar foutmeldingen zijn ( als je dit deed, zou je DebugLog(), WarningLog() enzovoort kunnen maken.

O, en onthoud dat #define DEBUG_MODEop verschillende plaatsen in je applicatie kan worden hergebruikt. In mijn applicatie gebruik ik het bijvoorbeeld om licentiesleutelcontroles uit te schakelen en de applicatie alleen te laten draaien als deze vóór een bepaalde datum is. Hierdoor kan ik een in de tijd beperkte, volledig functionele bètaversie verspreiden met minimale inspanning van mijn kant.


Antwoord 2, autoriteit 40%

Zet deze 3 regels aan het einde van het -prefix.pch-bestand:

#ifndef DEBUG
  #define NSLog(...) /* suppress NSLog when in release mode */
#endif

U hoeft niets in uw project te definiëren, omdat DEBUGstandaard wordt gedefinieerd in uw build-instelling wanneer u uw project maakt.


Antwoord 3, autoriteit 13%

NSLog-oproepen kunnen in productiecode worden achtergelaten, maar mogen er alleen zijn voor echt uitzonderlijke gevallen, of informatie die gewenst is, wordt vastgelegd in het systeemlogboek.

Applicaties die het systeemlogboek vervuilen, zijn vervelend en komen onprofessioneel over.


Antwoord 4, autoriteit 12%

Ik kan geen commentaar geven op Het antwoord van Marc Charbonneau, dus ik zal dit als antwoord posten.

Naast het toevoegen van de macro aan uw vooraf gecompileerde header, kunt u de Target build-configuraties gebruiken om het definiëren (of het ontbreken van het definiëren) van de DEBUG_MODEte regelen.

Als u de actieve configuratie “Debug” selecteert, wordt DEBUG_MODEgedefinieerd en wordt de macro uitgebreid tot de volledige NSLog-definitie.

p>

Als u de actieve configuratie “Release” selecteert, wordt DEBUG_MODEniet gedefinieerd en wordt uw NSLogging weggelaten uit de release-build.

Stappen:

  • Doel > Informatie opvragen
  • Tabblad Bouwen
  • Zoeken naar “PreProcessor-macro’s” (of GCC_PREPROCESSOR_DEFINITIONS)
  • Selecteer configuratie: Debug
  • Definitie bewerken op dit niveau
  • Voeg DEBUG_MODE=1
  • toe

  • Selecteer configuratie: Vrijgeven
  • bevestig dat DEBUG_MODEniet is ingesteld in GCC_PREPROCESSOR_DEFINITIONS

als u het ‘=’-teken in de definitie weglaat, krijgt u een foutmelding van de preprocessor

Plak deze opmerking (hieronder weergegeven) ook boven de macrodefinitie om u eraan te herinneren waar de DEBUG_MACRO-definitie vandaan komt;)

// Target > Get Info > Build > GCC_PREPROCESSOR_DEFINITIONS
// Configuration = Release: <empty>
//               = Debug:   DEBUG_MODE=1

Antwoord 5, autoriteit 6%

BEWERKEN:de methodegepost door Marc Charbonneau, en onder mijn aandacht gebracht door sho, is veel beter dan deze.

Ik heb het gedeelte van mijn antwoord verwijderd waarin werd gesuggereerd om een ​​lege functie te gebruiken om logboekregistratie uit te schakelen wanneer de foutopsporingsmodus is uitgeschakeld. Het gedeelte dat zich bezighoudt met het instellen van een automatische preprocessor-macro is nog steeds relevant, dus dat blijft zo. Ik heb ook de naam van de preprocessor-macro aangepast, zodat deze beter past bij het antwoord van Marc Charbonneau.


Om het automatische (en verwachte) gedrag in Xcode te bereiken:

Ga in de projectinstellingen naar het tabblad “Build” en selecteer de configuratie “Debug”. Zoek de sectie “Preprocessor-macro’s” en voeg een macro toe met de naam DEBUG_MODE.

BEWERKEN:Zie Marc Charbonneau’s antwoordvoor de juiste manier om logboekregistratie in en uit te schakelen met de macro DEBUG_MODE.


Antwoord 6, autoriteit 4%

Ik ben het met Matthew eens. Er is niets mis met NSLog in productiecode. In feite kan het nuttig zijn voor de gebruiker. Dat gezegd hebbende, als de enige reden dat u NSLog gebruikt, is om te helpen bij het opsporen van fouten, dan moet dat inderdaad worden verwijderd voordat u het uitbrengt.

Bovendien, aangezien je dit als een iPhone-vraag hebt gemarkeerd, neemt NSLog middelen in beslag, iets waar de iPhone maar heel weinig van heeft. Als je ietsop de iPhone aan het NSloggen bent, kost dat de processortijd van je app. Gebruik het verstandig.


Antwoord 7, autoriteit 2%

De simpele waarheid is dat NSLog gewoon traag is.

Maar waarom? Laten we, om die vraag te beantwoorden, eens kijken wat NSLog doet en vervolgens hoe het dat doet.

Wat doet NSLog precies?

NSLog doet 2 dingen:

Het schrijft logberichten naar de Apple System Logging (asl)-faciliteit. Hierdoor kunnen logberichten worden weergegeven in Console.app.
Het controleert ook of de stderr-stream van de applicatie naar een terminal gaat (zoals wanneer de applicatie wordt uitgevoerd via Xcode). Als dat zo is, schrijft het het logbericht naar stderr (zodat het verschijnt in de Xcode-console).

Schrijven naar STDERR klinkt niet moeilijk. Dat kan worden bereikt met fprintf en de verwijzing naar de stderr-bestandsbeschrijving. Maar hoe zit het met asl?

De beste documentatie die ik heb gevonden over ASL is een 10-delige blogpost van Peter Hosey: link

Zonder al te veel in detail te treden, het hoogtepunt (wat betreft de prestaties) is dit:

Om een ​​logbericht naar de ASL-faciliteit te sturen, opent u in feite een clientverbinding met de ASL-daemon en verzendt u het bericht. MAAR – elke thread moet een afzonderlijke clientverbinding gebruiken. Dus om thread-safe te zijn, wordt elke keer dat NSLog wordt aangeroepen, een nieuwe asl-clientverbinding geopend, het bericht verzonden en vervolgens de verbinding gesloten.

Bronnen kunnen hier& hier.


8

U mag niet onnodig verbruik zijn met PrintF of NSLOG in Release Code. Probeer alleen een printf of nslog uit te doen als de app er iets slechts mee gebeurt, d.w.z. een onherstelbare fout.


9

Houd er rekening mee dat NSlogs de UI / Hoofddraad kunnen vertragen. Het is het beste om ze te verwijderen van ontgrendelingsbouwers, tenzij absoluut noodzakelijk.


10

Ik zou het ten zeerste aanbevelen om Testflight voor logging (gratis) te gebruiken. Hun methode zal NSLOG (met behulp van een macro) overschrijven en kunt u aan / uitloggen op hun server, Apple-systeemlogboek en Stderr Log, voor al uw bestaande oproepen naar NSLOG. Het leuke hierover is je je log-berichten nog steeds herzien voor apps die worden geïmplementeerd op testers en apps die worden geïmplementeerd in de App Store, zonder dat de logs op het systeemlogboek van de gebruiker worden weergegeven. Het beste van beide werelden.

Other episodes