Benutzerdefinierte SwiftLint-Regeln

Hallo Habr! Mein Name ist Alex, ich bin iOS-Entwickler bei FINCH. Bald ist das neue Jahr die Zeit, anders zu leben, und so eine coole Sache wie SwiftLint wird dabei helfen. In dem Artikel werde ich Ihnen erklären, warum es in allen Projekten, einschließlich Legacy- und Pet-Projekten, implementiert werden muss, und zeigen, wie Sie das meiste aus diesem Tool mit regulären Zeilen herausholen können.

Ich werde Ihnen nicht sagen, was SwiftLint ist und wie es installiert werden kann. Wenn Sie mit dem Tool nicht vertraut sind, lesen Sie besser die offizielle Dokumentation .

Es ist besser, direkt auf das häufig auftretende Problem bei der Arbeit mit großen Projekten zuzugreifen - die Nichteinhaltung von Stilrichtlinien unter dem Deckmantel von Hotfixes oder anderen Dingen. Aber selbst wenn Sie die Styleguides lesen und sie sogar als extrem berauscht bezeichnen können, garantiert niemand, dass es nicht zu einem banalen Tippfehler kommt, der zwar keinen logischen Zusammenbruch zur Folge hat, aber das ästhetische Vergnügen deutlich beeinträchtigt.

Also denk dran:

1. Mit SwiftLint können Sie:

  • Ein Style mit Styleguides

Eigentlich alles.

Der Artikel könnte hier enden, aber wenn es so wäre, würde ich überhaupt nicht anfangen, diesen Artikel zu schreiben. Interessanterweise erlaubt Ihnen SwiftLint nicht , diesen Hotfix-Code zu schreiben.

2. Mit SwiftLint können Sie Folgendes verhindern:

  • Auspacken erzwingen
  • Starke Delegierte
  • CyclomaticComplexity
  • Noch etwas ...

Ich finde es schön, vor solchen Fehlern sicher zu sein, oder? Dies ist besonders gut für einen unerfahrenen Entwickler, da er nur lernt und manchmal solche Fehler nicht vermutet.

3. Swiftlint kann nach eigenen Regeln erweitert werden.

Ich beginne mit der Angabe von final für Klassen, die anderen nicht übergeordnet sind. Dank final sparen wir Projektmontagezeit. In der Apple-Dokumentation erfahren wir Folgendes über Abschlusskurse:
Deklarationen mit internem Zugriff (die Standardeinstellung, wenn nichts deklariert ist) sind nur innerhalb des Moduls sichtbar, in dem sie deklariert sind. Da Swift normalerweise die Dateien, aus denen ein Modul besteht, separat kompiliert, kann der Compiler nicht feststellen, ob eine interne Deklaration in einer anderen Datei überschrieben wird. Wenn jedoch die Gesamtmoduloptimierung aktiviert ist, werden alle Module gleichzeitig kompiliert. Auf diese Weise kann der Compiler gemeinsam Rückschlüsse auf das gesamte Modul ziehen und auf Deklarationen mit internal ableiten, wenn keine sichtbaren Überschreibungen vorhanden sind.

Wir werden diese Unaufmerksamkeit durch eine einfache reguläre Saison beheben. Als nächstes schreibe ich sofort an ruby, damit Sie Code direkt in Ihr Projekt einbetten können:

final_class: included: ".*.swift" name: "Final class requrement" regex: '^class' message: "All classes must be final or nonfinal" saverity: error 

Ein kleines und recht einfaches Beispiel. Ich werde nicht für jede Regel etwas Ähnliches schreiben, aber der Quellcode wird am Ende des Artikels stehen.

 class SomeClass { } //  internal class SomeClass { } //  /* @non-final */ class SomeClass { } //   

Der nächste Punkt ist init erforderlich. Wir im Unternehmen verwenden keine Storyboards, daher ist es nicht ganz normal, in jeder UIView-Klasse einen schwerwiegenden Initialisierer anzugeben. Für diesen Fall haben wir unser eigenes NLView (NL - NibLess) - eine Klasse, in der erforderliches init nur einmal implementiert wird. Neue Entwickler des Projekts wissen das vielleicht nicht, aber der Vorteil von SwiftLint ist immer von Vorteil, anstatt von einem verantwortungsvollen Vorsprung. Oder damit.

 required_init: regex: 'required init\?\(coder: NSCoder\)' message: "Use NL class instead" 

Wenn Sie noch Storyboards verwenden, können Sie die folgenden Regeln anwenden, um zu wissen, dass alle Ihre Storyboards privat sind:

 open_iboutlets: included: ".*.swift" name: "IBOutlet opening" regex: '@IBOutlet ?(weak){0,1} var' message: "IBOutlet should be private" severity: error 

 open_ibaction: included: ".*.swift" name: "IBAction opening" regex: '@IBAction func' message: "IBAction should be private" severity: error 

Es kommt oft vor, dass Foundation dort eingesetzt wird, wo es völlig unnötig ist. Daher ist es besser, es jedes Mal zu markieren, um Folgendes nicht zu vergessen:

  foundation_using: included: ".*.swift" regex: 'import Foundation' message: "Do you really need for Foundation ???" 

Ich hoffe, jeder weiß, dass das Drucken ein ziemlich schwieriger Vorgang ist, der die Anwendungsleistung erheblich beeinträchtigen kann (insbesondere in Schleifen). Das einzige Urteil - Drucke sollten überhaupt nicht sein.

 print_using: regex: 'print' message: "Print decrease performance of the app" severity: error 

Außerdem sollten Sie keine Protokolle nur für Klassen erstellen, da eine solche Syntax möglicherweise bald veraltet sein wird und dies von Swift-Entwicklern nicht empfohlen wird .

 class_protocol: regex: ': class' message: "Use Anyobject instead" 

Unten ist die Regel für Projekte, die R.swift verwenden.

 image_name_initialization: included: ".*.swift" name: "Image initialization without R.swift" regex: 'UIImage\(named:[^)]+\)' message: "Use R.image.name() or typealias of this instead" severity: error 

Dies ist nur ein kleiner Teil von dem, was ich mir einfallen lassen könnte, aber es gibt noch weniger Beispiele im Internet. Sie können meine gesamte "Sammlung" auf Github ansehen .

Vielen Dank für Ihre Aufmerksamkeit. Wenn Sie SwiftLint auch mit benutzerdefinierten Regeln verwenden, teilen Sie uns diese mit - ich werde gerne mögliche Fälle besprechen.

Source: https://habr.com/ru/post/de481666/


All Articles