Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save scott-lydon/3215db7abd1d92054b3cba028471aab4 to your computer and use it in GitHub Desktop.
Save scott-lydon/3215db7abd1d92054b3cba028471aab4 to your computer and use it in GitHub Desktop.
# Coding Guidelines
## Rules
1. **Omit the return keyword in one-line functions that return a value.**
2. **Use trailing closure syntax.**
3. **Remove the Google indentation guide rule due to lack of specific guidelines in the Google Swift style guide and because SwiftLint handles indentation.**
4. **Reevaluate the rule regarding DispatchQueue from inaction on the main thread for feasibility in static analysis.**
5. **Use higher-order functions when multiple properties call the same function.**
6. **Require every method to have a comment.**
7. **Remove one-line functions that do not return anything and call the code directly.**
8. **Avoid print statements; use a logging function instead (as a warning).**
9. **Avoid function declarations within other function bodies.**
10. **Use higher-order functions for processing arrays instead of loops.**
11. **Avoid using `[String: Any]`; use `Codable` instead.**
12. **Combine nested if-else statements into a single initialization statement.**
13. **Avoid empty files.**
14. **Inline constants or variables used only once.**
## Removed Rules and Reasons
1. **Google Indentation Guide:** Removed because there is no specific section on indentation in the Google Swift style guide, and SwiftLint already handles indentation.
2. **DispatchQueue from inaction is already on main thread:** Reevaluate the feasibility of enforcing this rule statically. Consider dynamic analysis or runtime checks to ensure code runs on the correct thread.
## Examples
### 1. Omit the return keyword in one-line functions that return a value.
**Non-triggering examples:**
```swift
func blocks() -> [Block] {
.all(with: .retained, times: 2)
}
```
```swift
func fetchUser() -> User {
User(name: "John")
}
```
```swift
func calculateSum(a: Int, b: Int) -> Int {
a + b
}
```
**Triggering examples:**
```swift
func blocks() -> [Block] { return .all(with: .retained, times: 2) }
```
```swift
func fetchUser() -> User { return User(name: "John") }
```
```swift
func calculateSum(a: Int, b: Int) -> Int { return a + b }
```
### 2. Use trailing closure syntax.
**Non-triggering examples:**
```swift
someFunction { value in
print(value)
}
```
```swift
UIView.animate(withDuration: 0.3) {
self.view.alpha = 1.0
}
```
```swift
fetchData { result in
handle(result)
}
```
**Triggering examples:**
```swift
someFunction(settingsAction: { value in
print(value)
})
```
```swift
UIView.animate(withDuration: 0.3, animations: {
self.view.alpha = 1.0
})
```
```swift
fetchData(completion: { result in
handle(result)
})
```
### 4. Use higher-order functions when multiple properties call the same function.
**Non-triggering examples:**
```swift
[am6Btn, am7Btn].forEach { $0.titleLabel?.setAkinFont() }
```
```swift
[btn1, btn2, btn3].forEach { $0.isEnabled = true }
```
```swift
[view1, view2, view3].forEach { $0.isHidden = false }
```
**Triggering examples:**
```swift
am6Btn.titleLabel?.setAkinFont()
am7Btn.titleLabel?.setAkinFont()
```
```swift
btn1.isEnabled = true
btn2.isEnabled = true
btn3.isEnabled = true
```
```swift
view1.isHidden = false
view2.isHidden = false
view3.isHidden = false
```
**More examples:**
```swift
addButton.addTarget(
self,
action: #selector(addProfilePicPress),
for: .touchUpInside
)
addProfilePicButton.addTarget(
self,
action: #selector(addProfilePicPress),
for: .touchUpInside
)
```
Should be:
```swift
[addButton, addProfilePicButton].forEach {
$0.addTarget(self, action: #selector(addProfilePicPress), for: .touchUpInside)
}
```
```swift
logoutLabel.text = "Logout"
logoutLabel.textColor = .romanceRed
contentView.addSubview(logoutLabel)
logoutLabel.constraint(from: .centeredHorizontallyWith(contentView))
logoutLabel.constraint(from: .centeredVerticallyTo(contentView))
logoutLabel.constraint(from: .distanceToBottom(contentView.bottomAnchor, 36))
logoutLabel.constraint(from: .distanceToTop(contentView.topAnchor, 36))
```
Should be:
```swift
logoutLabel.text = "Logout"
logoutLabel.textColor = .romanceRed
contentView.addSubview(logoutLabel)
[.centeredHorizontallyWith(contentView), .centeredVerticallyTo(contentView),
.distanceToBottom(contentView.bottomAnchor, 36), .distanceToTop(contentView.topAnchor, 36)].forEach {
logoutLabel.constraint(from: $0)
}
```
```swift
rightAddButton.titleLabel?.setAkinFont()
scrollButton.titleLabel?.setAkinFont()
closeButton.titleLabel?.setAkinFont()
closeButtonBordered.titleLabel?.setAkinFont()
```
Should be:
```swift
[rightAddButton, scrollButton, closeButton, closeButtonBordered].forEach {
$0.titleLabel?.setAkinFont()
}
```
### 5. Require every method to have a comment.
**Non-triggering examples:**
```swift
/// Fetches data from the server.
func fetchData() {
// implementation
}
/// Handles user login.
func loginUser() {
// implementation
}
```
**Triggering examples:**
```swift
func fetchData() {
// implementation
}
func loginUser() {
// implementation
}
```
### 6. Remove one-line functions that do not return anything and call the code directly.
**Non-triggering examples:**
```swift
print("Hello, World!")
```
**Triggering examples:**
```swift
func printHello() {
print("Hello, World!")
}
```
```swift
func reset() {
value = 0
}
```
### 7. Avoid print statements; use a logging function instead.
**Non-triggering examples:**
```swift
logger.log("This is a log message")
```
```swift
Log.info("User logged in successfully")
```
```swift
debugPrint("Debugging information")
```
**Triggering examples:**
```swift
print("This is a log message")
```
```swift
print("User logged in successfully")
```
```swift
print("Debugging information")
```
### 8. Avoid function declarations within other function bodies.
**Non-triggering examples:**
```swift
func outerFunction() {
// code
}
func innerFunction() {
// code
}
```
```swift
func calculate() {
let result = compute()
// other code
}
```
```swift
func performAction() {
// action code
}
```
**Triggering examples:**
```swift
func outerFunction() {
func innerFunction() {
// code
}
innerFunction()
}
```
```swift
func calculate() {
func compute() -> Int {
return 5
}
let result = compute()
}
```
```swift
func performAction() {
func action() {
// action code
}
action()
}
```
### 9. Use higher-order functions for processing arrays instead of loops.
**Non-triggering examples:**
```swift
let values = ["a", "b", "c"].map { $0.uppercased() }
```
```swift
let filtered = numbers.filter { $0 > 10 }
```
```swift
let sum = numbers.reduce(0, +)
```
**Triggering examples:**
```swift
var values = [String]()
for item in ["a", "b", "c"] {
values.append(item.uppercased())
}
```
```swift
var filtered = [Int]()
for number in numbers {
if number > 10 {
filtered.append(number)
}
}
```
```swift
var sum = 0
for number in numbers {
sum += number
}
```
### 10. Avoid using `[String: Any]`; use `Codable` instead.
**Non-triggering examples:**
```swift
struct MyData: Codable {
let name: String
let age: Int
}
```
```swift
let jsonData = try? JSONEncoder().encode(myData)
```
```swift
let myData = try? JSONDecoder().decode(MyData.self, from: jsonData)
```
**Triggering examples:**
```swift
let data: [String: Any] = ["name": "John", "age": 30]
```
```swift
let jsonData = try? JSONSerialization.data(withJSONObject: data)
```
```swift
let data = try? JSONSerialization.jsonObject(with: jsonData)
```
### 11. Combine nested if-else statements into a single initialization statement.
**Non-triggering examples:**
```swift
self.init(
presentation: enabled ? .enabled(importance ?? .irrelevant) : .disabled(importance),
auto
changedImportance: enabled && importance != nil
)
```
**Triggering examples:**
```swift
if enabled {
if let importance = importance {
self.init(presentation: .enabled(importance), autoChangedImportance: false)
} else {
self.init(presentation: .enabled(.irrelevant), autoChangedImportance: true)
}
} else {
self.init(presentation: .disabled(importance), autoChangedImportance: false)
}
```
### 12. Avoid empty files.
**Non-triggering examples:**
- Any file with content.
**Triggering examples:**
- Any file that is completely empty.
### 13. Inline constants or variables used only once.
**Non-triggering examples:**
```swift
alertViewController.styleCancelAlert(
regularContentsModel: RegularContentsView.Model(
title: "Are you sure?",
message: "If you close this greet, it can't be reopened."
),
models: UIButton.SimpleModel(
title: "Yes close it.",
action: {
self?.refuseGreetAndClose()
}
)
)
```
**Triggering examples:**
```swift
let contents = RegularContentsView.Model(
title: "Are you sure?",
message: "If you close this greet, it can't be reopened."
)
let buttonModel = UIButton.SimpleModel(
title: "Yes close it.",
action: {
self?.refuseGreetAndClose()
}
)
alertViewController.styleCancelAlert(
regularContentsModel: contents,
models: buttonModel
)
```
### 14. Inline constants or variables used only once.
**Non-triggering examples:**
```swift
alertViewController.styleCancelAlert(
regularContentsModel: RegularContentsView.Model(
title: "Are you sure?",
message: "If you close this greet, it can't be reopened."
),
models: UIButton.SimpleModel(
title: "Yes close it.",
action: {
self?.refuseGreetAndClose()
}
)
)
```
**Triggering examples:**
```swift
let contents = RegularContentsView.Model(
title: "Are you sure?",
message: "If you close this greet, it can't be reopened."
)
let buttonModel = UIButton.SimpleModel(
title: "Yes close it.",
action: {
self?.refuseGreetAndClose()
}
)
alertViewController.styleCancelAlert(
regularContentsModel: contents,
models: buttonModel
)
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment