- Avoid Code Duplications. This way you avoid limitless growing codebase plus, more important, you avoid fixing issues in multiple places. This is one of the most important rules.
- Use the
self.
syntax exclusively in closures and appropriate initializers. So it will become easier to track down future retain cycles that are caused by missing[weak self]
in the closure definition. Just leave outself
if it is not necessary. Also use theself.
syntax to initially assign constructor parameters to their respective properties if they have the same name. - Never use the default case in switch statements. Switch is an extremely useful construct in Swift since the compiler warns about missing cases. If you use the default case you disable this behaviour and loose one of the most powerful features of Swift.
- Never omit specifying the value of string-typed enum cases. Imagine you create a string-typed enum and omit the values for every case since Swift infers the value from the case name. Now when you refactor one enum case from somewhere in your app, the inferred value also changes, which is not desired i.e. in JSON keys. You would introduce hard to find errors.
- Create all classes as
final
. This way some optimisations are enabled for these classes which speeds up compilation. - Set thickness of lines device dependent. When you set the thickness of lines to
1.0 / UIScreen.main.scale
then the will appear equally on all devices. - Use UITextView for multiline text. If you follow this rule you get text selection and all the features of an UITextView for free. Be sure you set isEditable and isScrollable to
false
. - Localized-strings used in a framework F must be defined there. If don't folow this rule, F depends on the target/module where the string is defined and thus is not modular/independent anymore. If e.g. another target/module uses a class of F that contains a localized string which is outside of F the translation could not be found.
- Name selectors with the pattern on<action_name> Having a unified pattern for naming selectors helps to make code understandable faster. The on* pattern is also used in other programming languages like JavaScript.
- No file header. Remove comment header for newly created files since it will be always outdated (copyright, spelling errors in file names, etc.).
These guidelines are meant to be used without Interface Builder and teach you how to work with views programmatically.
- Use special function to setup and add EACH subview. Setup each subview of a view or view controller in its own function! The Name of the function has to be
setup<property_name>
. This function should set all parameters necessary for the first setup. This includescontentHuggingPriority
andcontentCompressionResistencyPriority
. It is called only once in init (UIView) or viewDidLoad (UIViewController). Right before the function returns add the view to its superview. This pattern turned out to be one of the cleanest structuring methods possible for the swift language. The advantage is that you have a clean interface of properties on top of the class which helps to recognize all subviews at one glance - in contrast of setting up views in a property closure. Furthermore you can useself
since these functions are called after initialization. You have a clear overview of the adding order of subviews. Additionally you prevent one long function that sets up all properties of all subviews - typically init or viewDidLoad. Last but not least if you stick to this pattern it is much easier to understand the structure of the whole app since you'll find this pattern all over again. - Use special function to setup layout constraints. Always use
func setupLayoutConstraints
to create constraints between all subviews! Call it right after the last subview setup* function in viewDidLoad (UIViewController) or init (UIView). This activates all layout constraints. - Never set
translatesAutoresizingMaskIntoConstraints
manually. We have the functionsaddTo()
andaddMaximizedTo()
which do that automatically.
- Respect the order of symbols. Properties should be listed on the top of a class or struct in the order
public static
,private static
,public
andprivate
. In general static/public symbols are higher ranked than non-static/private ones. - Declare symbols internal if you want to test them. To be able to use symbols in tests declare them as
internal
(no prefix) instead ofprivate
even if they are not used outside of the containing object. If you don't need to test them and they are not required outside of the containing object declare it asprivate
.