Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Swift rules from ecocode-ios #224

Merged
20 changes: 20 additions & 0 deletions ecocode-rules-specifications/src/main/rules/EC14/EC14.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"title": "Do not disable idle timer, unless absolutely necessary.",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "5min"
},
"tags": [
"eco-design",
"environment",
"sobriety",
"ecocode"
],
"defaultSeverity": "Major",
"compatibleLanguages": [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's useful to set this property.

Additionally, JSON in rule folder level is supposed to be language agnostic.
For language specificities, it would be necessary to be able to manage a JSON override with a JSON file placed in the corresponding subfolder language directory.

The ability to overload JSON metadata is currently not implemented (but could be if necessary).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest, I followed the template of the others rules at the time (late August) and almost all of them had this property and still are (eg: EC11, EC12, etc.).

So what should I do, remove or leave it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, leave it like that.
We improve metadata in future commits if needed

"SWIFT"
]
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
To avoid draining the battery, an iOS device that is left idle quickly falls asleep.
Hence, keeping the screen on should be avoided, unless it is absolutely necessary. If so, developers typically
disable the idle timer with `UIApplication.shared.isIdleTimerDisabled = true`.

## Noncompliant Code Example

```swift
UIApplication.shared.isIdleTimerDisabled = true // Noncompliant
```

## Compliant Solution

```swift
UIApplication.shared.isIdleTimerDisabled = false
```
20 changes: 20 additions & 0 deletions ecocode-rules-specifications/src/main/rules/EC15/EC15.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"title": "Setting a tolerance for timers will allow them to fire later than the scheduled fire date.",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "1min"
},
"tags": [
"eco-design",
"environment",
"idleness",
"ecocode"
],
"defaultSeverity": "Major",
"compatibleLanguages": [
"SWIFT"
]
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Setting a tolerance for timers will allow them to fire later than the scheduled fire date.
The system will use this flexibility to shift the execution of timers by small amounts of time,
within their tolerances, increasing the ability to optimize power savings.
Your app can set the `Timer#tolerance` property to specify a tolerance for a timer.
Using this approach dramatically increases the amount of time that the processor spends idling
while users detect no change in system responsiveness.

## Noncompliant Code Example

```swift
let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in } // Noncompliant
```

## Compliant Solution

```swift
let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in }
timer.tolerance = 0.5
```
20 changes: 20 additions & 0 deletions ecocode-rules-specifications/src/main/rules/EC16/EC16.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"title": "Monitoring power changes and customizing behavior depending on battery level is a good practice.",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "0min"
},
"tags": [
"eco-design",
"environment",
"power",
"ecocode"
],
"defaultSeverity": "Info",
"compatibleLanguages": [
"SWIFT"
]
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
It's always good that an app has different behavior when device is connected/disconnected to a power station,
or has different battery levels. Your app can query the `UIDevice#batteryLevel` and
`UIDevice#batteryState` properties at any time to determine the level of charge and
the state of the battery. Your app can also register to receive notifications when the battery level
or state changes, using `batteryLevelDidChangeNotification` and batteryStateDidChangeNotification`.

## Compliant Code Example

```swift
let level = UIDevice.current.batteryLevel
let state = UIDevice.current.batteryState
NotificationCenter.default.addObserver(forName: UIDevice.batteryLevelDidChangeNotification, object: nil, queue: nil) { _ in }
NotificationCenter.default.addObserver(forName: UIDevice.batteryStateDidChangeNotification, object: nil, queue: nil) { _ in }
```
20 changes: 20 additions & 0 deletions ecocode-rules-specifications/src/main/rules/EC17/EC17.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"title": "Taking into account when the device is entering or exiting the power save mode is a good practice.",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "0min"
},
"tags": [
"eco-design",
"environment",
"power",
"ecocode"
],
"defaultSeverity": "Info",
"compatibleLanguages": [
"SWIFT"
]
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Use device API to check if low power mode is enabled, and adapt resources usage accordingly.
For example, you can reduce frequency of data update if low power mode is enabled.
Your app can query the `ProcessInfo.processInfo.isLowPowerModeEnabled` property at any time
to determine whether Low Power Mode is active. Your app can also register to receive notifications
when the Low Power Mode state of a device changes, using `NSProcessInfoPowerStateDidChange`.

## Compliant Code Example

```swift
let isLowPowerModeEnabled = ProcessInfo.processInfo.isLowPowerModeEnabled
NotificationCenter.default.addObserver(forName: .NSProcessInfoPowerStateDidChange, object: nil, queue: nil) { _ in }
NotificationCenter.default.addObserver(forName: Notification.Name.NSProcessInfoPowerStateDidChange, object: nil, queue: nil) { _ in }
```
20 changes: 20 additions & 0 deletions ecocode-rules-specifications/src/main/rules/EC18/EC18.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"title": "Do not disable location updates pause, unless absolutely necessary.",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "5min"
},
"tags": [
"eco-design",
"environment",
"sobriety",
"ecocode"
],
"defaultSeverity": "Major",
"compatibleLanguages": [
"SWIFT"
]
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Allowing the system to pause location updates, at times when the location data is unlikely to change, can improve
battery life without sacrificing location data. This is the default behavior. For example, if the user stops for
food while using a navigation app, the location manager might pause updates for a period of time. It is possible
to disable this behavior, by setting the `CLLocationManager#pausesLocationUpdatesAutomatically`
property to `false`, but applications are strongly discouraged of doing it.

## Noncompliant Code Example

```swift
let manager = CLLocationManager()
manager.pausesLocationUpdatesAutomatically = false // Noncompliant
```
20 changes: 20 additions & 0 deletions ecocode-rules-specifications/src/main/rules/EC19/EC19.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"title": "Adapt location accuracy and type to applications needs.",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "5min"
},
"tags": [
"eco-design",
"environment",
"sobriety",
"ecocode"
],
"defaultSeverity": "Major",
"compatibleLanguages": [
"SWIFT"
]
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Location awareness is one of the most popular features used by apps.
By default standard location updates run with the best accuracy level,
but unless your app really needs to know the user’s position within a few meters,
this level of accuracy isn't needed.
Requesting higher accuracy than you need causes the system to power up additional hardware
and waste power for unnecessary precision. You can specify a degree of accuracy by setting
the `CLLocationManager#desiredAccuracy` property.
Also, setting the `CLLocationManager#activityType` property will let the system knows what type
of location activity your app is performing and helps it determine
the most appropriate time to perform location updates.
Finally, if your app just needs a quick fix on the user’s location,
it’s best to call the `CLLocationManager#requestLocation` method,
that will deliver a single location update.

## Compliant Code Example

```swift
let manager = CLLocationManager()
manager.desiredAccuracy = 2
```
20 changes: 20 additions & 0 deletions ecocode-rules-specifications/src/main/rules/EC20/EC20.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"title": "Set appropriate motion sensor update rates for the application's needs.",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "5min"
},
"tags": [
"eco-design",
"environment",
"sobriety",
"ecocode"
],
"defaultSeverity": "Major",
"compatibleLanguages": [
"SWIFT"
]
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Using the Core Motion API, your app can receive continuous motion updates in the form of
accelerometer, gyroscope, and device motion (rotation, acceleration, and more) events.
Yet you don't often need these updates as soon as they are generated.
Before registering to receive these recurring motion updates, you can specify an interval
that meets your app’s needs, using `CMMotionManager#accelerometerUpdateInterval`,
`CMMotionManager#gyroUpdateInterval`, `CMMotionManager#deviceMotionUpdateInterval` and
`CMMotionManager#magnetometerUpdateInterval` properties. The larger the interval,
the fewer events are delivered to your app, improving battery life.

## Compliant Code Example

```swift
CMMotionManager.accelerometerUpdateInterval = 1000
CMMotionManager.gyroUpdateInterval = 1000
CMMotionManager.deviceMotionUpdateInterval = 1000
CMMotionManager.magnetometerUpdateInterval = 1000
```
20 changes: 20 additions & 0 deletions ecocode-rules-specifications/src/main/rules/EC21/EC21.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"title": "Do not force brightness in your code, unless absolutely necessary.",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "5min"
},
"tags": [
"eco-design",
"environment",
"sobriety",
"ecocode"
],
"defaultSeverity": "Major",
"compatibleLanguages": [
"SWIFT"
]
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
To avoid draining the battery, an iOS device adapt its brightness to the environment.
Hence, keeping forcing the screen brightness on should be avoided, unless it is absolutely necessary.
If so, developers typically force the brightness to 1 with `UIScreen.main.brightness`.

## Non-Compliant Code Example

```swift
UIScreen.main.brightness = 0.3
```
20 changes: 20 additions & 0 deletions ecocode-rules-specifications/src/main/rules/EC23/EC23.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"title": "Turning on the torch mode programmatically must absolutely be avoided because the flashlight is one of the most energy-intensive component.",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "5min"
},
"tags": [
"eco-design",
"environment",
"sobriety",
"ecocode"
],
"defaultSeverity": "Major",
"compatibleLanguages": [
"SWIFT"
]
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Turning on the torch mode programmatically using `AVCaptureDevice#torchMode` or `AVCaptureDevice#setTorchModeOn(level:)`
methods must absolutely be avoided because the flashlight is one of the most energy-intensive component.

## Non-Compliant Code Example

```swift
guard let videoDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) else { return }
guard videoDevice.hasTorch else { return }

videoDevice.lockForConfiguration()
videoDevice.torchMode = .on // non-compliant
videoDevice.setTorchModeOn(level: 1.0) // non-compliant
videoDevice.unlockForConfiguration()
```