Preface This post is a compilation of notes I took while working on SwiftGraphics. Most of the suggestions are well thought out, but there are other similar solutions. So if other solutions make sense, they will be added. This best practice does not impose or recommend a procedural, object-oriented, or functional style for using Swift. Rather, it is about a pragmatic approach. Some suggestions may focus on object-oriented or pragmatic solutions where necessary. This article is primarily focused on the Swift language and the Swift standard library. Even so, if we can offer a unique Swift perspective and insight, we will still provide special advice on using Swift on Mac OS, iOS, WatchOS, and TV OS. And how to use Swift effectively with Xcode and LLDB will also be provided in the style of Hints & tips. This process required a lot of hard work, and I am very grateful to those who contributed to this article. Additionally, you can discuss this in the [Swift-Lang slack]. Notes for Contributors Please make sure all examples are runnable first (some examples may not work correctly). This markdown can be converted to a Mac OS X playground. Golden Rule
Best Practices 1. Naming As in the Swift Programming Language, type names are named in upper camel case (for example: VehicleController). Variables and constants are named using lowerCamelCase (for example: vehicleName). You should use Swift templates to name your code rather than using the Objective-C class prefix style (unless connected to Objective-C). Do not use any Hungarian notation names (e.g. k for constants, m for methods), use short names and use Xcode's Type Quick Help ( + click) to find out the type of the variable. Also, do not use SNAKE_CASE names.The only special thing is the naming of enum values, which need to use upper camel case naming (this also follows Apple's Swift Programming Language style):
Wherever possible, unnecessary shortening and abbreviation of names should be avoided, in the future you should be able to specify the type trait " ViewController " without any damage and without relying on Xcode's autocomplete functionality. Very common abbreviations such as URL are allowed. Abbreviations should be written in all uppercase ( URL ) or all lowercase ( url ). The same rules apply to types and variables. If url is a type, it should be uppercase, if it is a variable, it should be lowercase. 2. Annotations Comments should not be used to invalidate code, commenting code invalidates it and affects the cleanliness of the code. If you want to remove code, but still want to keep it in case it is needed in the future, you should rely on git or the bug tracker. 3. Type Inference Where possible, use Swift’s type inference to reduce redundant type information. For example, the correct way to write:
instead of:
4. Self-inference Let the compiler infer self wherever it is allowed. Explicit use of self should be used in init functions to set parameters and in non-escaping closures. For example:
5. Parameter list type inference Specifying parameter types in a closure expression can make the code more verbose. Specify types only when necessary.
If the compiler is able to infer the type, then the type definition should be removed.
Using ordered parameter numbers ("$0", "$1", "$2") can help reduce redundancy, as they often fully match the parameter list. Use numbered names only when the closure parameter names don't contain too much information (such as very simple maps and filters). Apple can and will change the parameter types of Swift when converted from Objective-C frameworks. For example, options may be removed or become automatically expanded. We should intentionally specify your options and rely on Swift to infer the types to reduce the risk of your program breaking in this situation. You should always specify return types sparingly. For example, this parameter list is clearly overly verbose:
6. Constants When defining a type, constants should be declared as static in the type. For example:
Using static to modify constants allows them to be referenced without requiring an instantiation of the type. Except for singletons, global constants should be avoided as much as possible. 7. Computed Properties When you only need to inherit getter methods, return simple Computed properties. For example, you should do this:
instead of:
If you add set or didSet to a property, you should explicitly provide a get method.
8. Converting Instances When creating code to convert from one type to another init() method:
In the Swift standard library, init methods are now the preferred way to convert instances of one type to another. The "to" method is another reasonable technique (although you should follow Apple's guidance and use the init method):
And you might be tempted to use a getter, for example:
Getters are generally limited in that they should return a component of an acceptable type. For example, returning an instance of Circle is a good candidate for a getter, but converting a Circle to a CGPath is best done using the "to" function or the init() extension on CGPath. 9. Singletons Singletons are simple to create in Swift:
Swift's runtime ensures that singletons are created and accessed in a thread-safe manner. Singletons should usually only need to access the static property "sharedInstance" unless you have a compelling reason to rename it. Be careful not to use static methods or global functions to access your singletons. (Since singletons are so simple in Swift, and since constant naming is taking up so much of your time, you should have more time to complain about why singletons are an anti-pattern, but avoid spending so much time on it, and your peers will thank you.) 10. Use extensions to organize your code Extensions should be used to organize code. Secondary methods and properties of an instance should be moved to extensions. Note that not all property types currently support moving to extensions, and for best results you should use extensions within this limitation. You should use extensions to help organize your instance definitions. A good example is a view controller that extends table view data source and delegate protocols. To minimize the code in the table view, consolidate the data source and delegate methods into extensions that adapt to the corresponding protocols. In a single source file, add some definitions to extensions as you feel best organized. Don’t be afraid to add methods of the main class or methods pointing to method and property definitions in the struct to the extension. As long as everything is contained in one Swift file, it’s fine. Conversely, main's instance definition should not refer to elements defined in extensions outside the scope of the main Swift file. 11. Chained Setters For simple setter properties, do not use chained setters as a convenient alternative. The right way:
Wrong approach:
Compared to chained setters, traditional setters are simpler and less formulaic. 12. Error Handling Swift 2.0's do/try/catch mechanism is awesome. 13. Avoid using try! Generally speaking, use the following syntax:
Instead of:
Even though this form is quite verbose, it provides context for other developers to examine the code. Until a more detailed error handling strategy is developed, it is fine to use try! as a temporary error handling. However, it is recommended that you check your code periodically to find any illegal try! that may escape your code check. 14. Avoid using try? try? is used to "suppress" errors, and is only useful if you are sure that you don't care about the error that was generated. Generally speaking, you should catch errors and at least print them out. 15. Premature Return & Guards When possible, use guard statements to handle premature returns or other exit situations (for example, fatal errors or thorough errors). Correct way to write it:
Wrong way of writing:
or:
This flattened code otherwise enters an if let block and exits prematurely near the relevant context, instead of entering the else block. Even when you don’t capture a value ( guard let ), this pattern will force a premature exit during compilation. In the second if example, even though the code flattens out like the guard, a catastrophic error or other process that returns something that can’t be exited (or is an invalid state depending on the instance) will cause a crash. When a premature exit occurs, the guard statement will catch the error and remove it from the else block. 16. Early access control Even if your code is not separated into independent modules, you should always think about access control. Marking a definition as private or internal acts as a lightweight documentation for the code. Everyone who reads the code will know that this element cannot be "touched". Conversely, making a definition public is equivalent to inviting other code to access this element. It is better to specify it explicitly rather than relying on Swift's default access control level. (internal) If your codebase grows in the future, it may be broken up into submodules. Doing so will make it easier and faster to work with a codebase that is already decorated with access control information. 17. Restrictive Access Control In general, when adding access control to your code, it's best to be exhaustive. Here, it makes more sense to use private than internal, and internal is definitely better than public. (Note: internal is the default). It is easy to make the access control of code more open (along the lines of "private" to "internal" to "public") if necessary. Code with too open access control may not be appropriate for use by other code. Code with sufficiently restrictive access can detect inappropriate and incorrect usage and provide a better interface. An example is a type that publicly exposes an internal cache. Moreover, restricting access to code limits the "exposed surface area" and allows code to be refactored with less impact on other code. Other techniques such as Protocol Driven Development can also play a similar role. TODO Section
|
<<: Baidu, Alibaba, Tencent, which of the three giants is the most dangerous?
>>: Apple kills ad blocking tool that dares to block Apple apps
Isn’t it a bit outrageous that a tanker truck tha...
Expert of this article: Pa Lize, Chief Physician ...
The customer service group was shouting: This use...
Zhou Yanjie lady body 10-session quick slimming y...
Call 185-6916-1745 for QQ synchronization. It can...
"Nezha" has grossed over 3.5 billion yu...
Everyone has put most of their time and energy in...
Guangzhou website SEO optimization is not just ab...
Black holes have always been an incredible existe...
As competition among domestic content platforms e...
Re-think: “ Marketing Jobs” This time, I hope to ...
WeChat Mini Program is an application that users ...
The Spring Festival marketing war is about to beg...
Brand marketing is a long-term thing. The communi...
With the development of intelligence, mobile e-co...