Best Practice - NSError-Domänen und -Codes für Ihr eigenes Projekt / Ihre eigene App

114

Es gibt einen früheren SO-Beitrag zum Einrichten von Fehlerdomänen für Ihre eigenen Frameworks. Was ist jedoch die beste Vorgehensweise zum Einrichten von Fehlerdomänen und benutzerdefinierten Fehlercodes für Ihr eigenes Projekt / Ihre eigene App ?

Angenommen, Sie arbeiten an einer Core Data-intensiven App mit vielen Validierungen, sollten Sie sich nur an die "Standard" -Core Data-Fehlercodes (z. B. NSManagedObjectValidationErrorvon CoreDataErrors.h) halten oder Ihre eigenen erstellen MyAppErrors.hund Fehler mit definieren mehr Spezifität (dh MyAppValidationErrorInvalidCombinationOfLimbs?

Das Erstellen einer benutzerdefinierten Fehlerdomäne und einer Reihe von Fehlercodes kann Ihren Code erheblich disambiguieren. Ist der Aufwand jedoch zu hoch, um ihn zu warten, und müssen Sie sich über Konflikte bei der Nummerierung von Fehlercodes Gedanken machen? Oder gibt es hier andere Bedenken?

Neal L.
quelle

Antworten:

152

Ich persönlich verwende eine Reverse-DNS-Domain. Beispielsweise:

NSError * myInternalError = [NSError errorWithDomain:@"com.davedelong.myproject" code:42 userInfo:someUserInfo];

Der dritte Teil der Domäne ( @"myproject") wird nur verwendet, um die Fehler aus diesem Projekt ( "My Project") von Fehlern in einem anderen Projekt ( "My Other Project"=> com.davedelong.myotherproject) zu unterscheiden.

Dies ist eine einfache Möglichkeit, um sicherzustellen, dass ich nicht mit den Fehlerdomänen anderer in Konflikt gerate (wenn ich Code von Drittanbietern verwende), es sei denn, dieser Entwickler versucht absichtlich, sich nur mit mir anzulegen (was meiner Meinung nach höchst unwahrscheinlich ist. ..).

Machen Sie sich darüber keine Sorgen um Code-Nummerierungskonflikte. Solange Codes innerhalb einer Domain eindeutig sind , sollten Sie in Ordnung sein.

Die Übersetzung von Fehlern liegt bei Ihnen. Was auch immer Sie tun, stellen Sie sicher, dass Sie es gut dokumentieren. Persönlich gebe ich normalerweise nur vom Framework generierte Fehler weiter, wenn sie zu mir kommen, da ich nie ganz sicher bin, ob ich alle Codes verarbeiten und alle userInfo in etwas Spezifischeres für mein Projekt übersetzen werde. Die Frameworks können weitere Codes ändern und hinzufügen oder die Bedeutung vorhandener Codes usw. ändern. Außerdem kann ich genauer identifizieren, woher der Fehler stammt. Wenn mein StackKit- Framework beispielsweise einen Fehler in der com.stackkitDomäne generiert , weiß ich, dass es sich um ein Framework-Problem handelt. Wenn es jedoch einen Fehler in der generiert NSURLErrorDomain, weiß ich, dass es speziell vom URL-Lademechanismus stammt.

Was Sie könnten tun , ist das Framework erzeugt Fehler erfassen und in einem neuen Fehlerobjekt wickeln , die Ihre Domain und einen allgemeinen Code hat, so etwas wie kFrameworkErrorCodeUnknownoder etwas, und dann den erfassten Fehler in der userInfounter der NSUnderlyingErrorKey. CoreData macht dies häufig (wenn Sie beispielsweise versuchen, save:eine NSManagedObjectContextBeziehung herzustellen , aber Beziehungsintegritätsfehler haben, erhalten Sie einen einzelnen Fehler zurück, der jedoch NSUnderlyingErrorKeyviel mehr Informationen enthält, z. B. speziell, welche Beziehungen falsch sind usw.).

Dave DeLong
quelle
Da Apple auch Reverse DNS verwendet, erscheint es für andere angemessen, diesen Stil ebenfalls zu verwenden.
Johan Karlsson
36

Ich habe nicht genug Repräsentanten, um Kommentare abzugeben, aber für die akzeptierte Antwort von Dave DeLong ist es möglicherweise etwas besser, sie [[NSBundle mainBundle] bundleIdentifier]anstelle von zu verwenden @"com.myName.myProject". Auf diese Weise wird der Name Ihres Projekts oder eines Projekts genau wiedergegeben.

Connor
quelle
4
Gute Idee. Wenn Sie Swift verwenden, sollten Sie die unverpackte Option verwenden: NSBundle.mainBundle().bundleIdentifier!(Wenn Sie wissen, dass die Bundle-
Juul
Warum sollten Sie Änderungen des Projektnamens in der Fehlerdomäne widerspiegeln?
zrslv
1
@zrxq Es ist sicher sinnvoll, unterschiedliche Fehlerdomänen zu haben, aber stellen Sie sich vor, Sie haben Ihr Projekt falsch geschrieben oder Ihren Namen geändert und wollten, dass es sich überall widerspiegelt. Besser dynamisch einstellen als fest codieren.
Connor
1
@vare So viel ist klar, ich verstehe nicht wirklich, welche praktischen Vorteile dies bieten würde. Mein Verständnis ist, dass diese Bezeichner im Kontext der App nur eindeutig sein müssen, das ist alles. Okay, vielleicht möchten Sie nur, dass sie ästhetischer sind, ich verstehe!
zrslv
1
Ja, Sie sprechen einen guten Punkt an. Es gibt Zeiten, in denen Sie möchten, dass die Domain eindeutig ist, würde ich annehmen ... Wenn Sie beispielsweise ein SDK oder einen (Kakao-) Pod erstellen, möchten Sie, dass Ihre Fehlerdomäne widerspiegelt, woher sie stammt, nicht die des Projekts Name. EDIT: Ich wollte auch (in meiner Antwort) darauf hinweisen, dass @ "com.myName.myProject" in diesem Fall mit dem bundleIdentifier identisch ist, was die Leute möglicherweise nicht wissen.
Connor
4

So erstellen Sie einen benutzerdefinierten NSError:

Erstellen Sie zunächst ein Wörterbuch der Fehlermeldung

NSDictionary *userInfo = @{   
   NSLocalizedDescriptionKey: NSLocalizedString(@"Unknown Error - Please try again", nil),
   NSLocalizedFailureReasonErrorKey: NSLocalizedString(@"Unknown Error - Please try again", nil),
   NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"Unknown Error - Please try again", nil)
                                               };
NSError *error = [NSError errorWithDomain:[[NSBundle mainBundle] bundleIdentifier] 
  code:-58 userInfo:userInfo];

Weisen Sie dann die userInfo dem NSDictionary zu und fertig.

Mike Zriel
quelle