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

Stop location monitoring when app goes to background for usages that don't require 'always' permission #64

Merged
merged 7 commits into from
Apr 10, 2024

Conversation

ubfelix
Copy link
Contributor

@ubfelix ubfelix commented Jul 12, 2023

This PR changes the behavior of UBLocationManager, so that whenever the app goes into the background or becomes active again, it stops location monitoring for usages that are not meant to be getting updates while the app is in the background.

So far, if the app had acquired the 'always' permission at some point, location monitoring would continue in the background, even for delegates that only subscribed for the foregroundLocation usage.

Summary by CodeRabbit

  • New Features

    • Added lifecycle event monitoring for the app to enhance location tracking capabilities.
    • Introduced debug notifications for development purposes using the new LocalNotificationHelper.
  • Enhancements

    • Improved GPS location event handling and delegate management.
    • Enhanced error descriptions and handling in networking components.
  • Bug Fixes

    • Adjusted cache handling logic in the UBURLSession to correctly manage cache results based on specific flags.
  • Refactor

    • Streamlined code and improved readability in various networking components.
  • Tests

    • Updated unit tests to reflect changes in caching and request modification logic.

@github-actions
Copy link

github-actions bot commented Jul 12, 2023

Unit Test Results

    1 files  ±0      3 suites  ±0   1m 55s ⏱️ ±0s
166 tests ±0  164 ✔️ ±0  0 💤 ±0  2 ❌ ±0 

For more details on these failures, see this check.

Results for commit 0cf0b01. ± Comparison against base commit 0cf0b01.

♻️ This comment has been updated with latest results.

@sonarqubecloud
Copy link

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 3 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

@ubfelix
Copy link
Contributor Author

ubfelix commented Nov 29, 2023

@coderabbitai review

Copy link

coderabbitai bot commented Nov 29, 2023

Walkthrough

The recent updates primarily enhance location management in iOS applications by integrating app lifecycle awareness and refining GPS handling. Additional improvements include debugging aids via notifications, and several minor tweaks in networking code to optimize error handling and cache logic. The changes aim to increase the robustness and maintainability of the codebase.

Changes

File Path Change Summary
.../UBLocation/UBLocationManager.swift Enhanced to manage app lifecycle events, improve GPS handling, and added background status checks.
.../UBLocation/UBLocationManagerDelegateWrapper.swift Added method for update necessity based on background status.
.../UBLocation/LocalNotificationHelper.swift New utility for displaying debug notifications.
.../Networking/AutoRefreshCacheLogic.swift Minor access level and formatting adjustments.
.../Networking/CachingLogic.swift Removed an empty line; no logic impact.
.../Networking/Networking+Error.swift Enhanced error handling by refining descriptions and adjusting access control.
.../Networking/UBURLDataTask+Decoder.swift Reformatted and restructured for clarity in image decoding.
.../Networking/UBURLDataTask.swift Removed trailing whitespace; no logic impact.
.../Networking/UBURLSession.swift Modified cache handling logic to better manage cache flags.
Tests/.../HTTPDataTaskTests.swift Minor formatting changes.
Tests/.../TaskAutoRefreshLogicTests.swift Modified cache headers testing functionality.

🐰✨
In the land of code, where the swift rabbits hop,
We tweaked and we tuned, not a moment to stop.
From life cycle to cache, in backgrounds so deep,
With each line we ensure your app's leap.
Cheers to the changes, may bugs fear this script,
For every line’s a victory, perfectly equipped! 🌟
🐰✨


Recent Review Details

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 718811a and e7858ca.
Files selected for processing (11)
  • .swiftformat (1 hunks)
  • Sources/UBFoundation/Networking/AutoRefreshCacheLogic.swift (2 hunks)
  • Sources/UBFoundation/Networking/CachingLogic.swift (1 hunks)
  • Sources/UBFoundation/Networking/Networking+Error.swift (1 hunks)
  • Sources/UBFoundation/Networking/UBURLDataTask+Decoder.swift (2 hunks)
  • Sources/UBFoundation/Networking/UBURLDataTask.swift (1 hunks)
  • Sources/UBFoundation/Networking/UBURLSession.swift (1 hunks)
  • Sources/UBLocation/UBLocationManager.swift (19 hunks)
  • Sources/UBLocation/UBLocationManagerDelegateWrapper.swift (1 hunks)
  • Tests/UBFoundationTests/Networking/HTTPDataTaskTests.swift (1 hunks)
  • Tests/UBFoundationTests/Networking/TaskAutoRefreshLogicTests.swift (1 hunks)
Files not reviewed due to errors (1)
  • UBLocationManager.swift (no review received)
Files skipped from review due to trivial changes (3)
  • Sources/UBFoundation/Networking/CachingLogic.swift
  • Sources/UBFoundation/Networking/UBURLDataTask.swift
  • Tests/UBFoundationTests/Networking/HTTPDataTaskTests.swift
Files skipped from review as they are similar to previous changes (1)
  • Sources/UBLocation/UBLocationManagerDelegateWrapper.swift
Additional comments not posted (10)
.swiftformat (1)

7-7: Disabling the preferForLoop rule aligns with specific coding style preferences. Ensure this change is consistent with the team's coding standards.

Sources/UBFoundation/Networking/UBURLDataTask+Decoder.swift (2)

11-11: Conditional import of UIKit is a standard practice for platform-specific code in Swift.


109-125: The restructuring of UBImageDecoder enhances image handling by supporting different scales, improving flexibility and functionality.

Sources/UBFoundation/Networking/AutoRefreshCacheLogic.swift (2)

12-12: Tightening the access control of the Log struct to private enhances encapsulation without likely affecting functionality.


50-50: The minor formatting adjustment aligns with stylistic preferences and does not impact functionality.

Sources/UBFoundation/Networking/UBURLSession.swift (1)

56-63: Adjusting the control flow to handle cache flags more appropriately improves the robustness and correctness of cache handling.

Sources/UBFoundation/Networking/Networking+Error.swift (3)

121-141: Reorganizing the extension of UBNetworkingError to conform to UBCodedError enhances clarity and maintainability of error handling.


121-141: Adjusting the access control of error properties likely enhances encapsulation without restricting necessary access.


121-141: Refining error descriptions enhances the user experience by providing clearer and more informative error messages.

Tests/UBFoundationTests/Networking/TaskAutoRefreshLogicTests.swift (1)

11-16: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [1-100]

Modifying the testNoCacheHeaders method to handle cache headers testing more effectively likely improves test coverage and accuracy.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 43c6608 and a33ab33.
Files selected for processing (1)
  • Sources/UBLocation/UBLocationManager.swift (6 hunks)
Additional comments: 9
Sources/UBLocation/UBLocationManager.swift (9)
  • 8-11: The addition of import UIKit is appropriate for handling app lifecycle events.

  • 91-91: The appIsInBackground property is correctly declared as a private variable to track the background state of the app.

  • 297-300: The setupAppLifeCycleNotifications() method correctly sets up observers for UIApplication.didEnterBackgroundNotification and UIApplication.didBecomeActiveNotification.

  • 302-313: The appDidEnterBackground() and appDidBecomeActive() methods are correctly implemented to update appIsInBackground and manage location monitoring based on the app's state.

  • 494-498: The conditional check in startMonitoring(for:) to determine if the app is in the background before starting location updates is correctly implemented.

  • 507-508: The conditional check in startMonitoring(for:) to determine if the app is in the background before starting heading updates is correctly implemented.

  • 511-512: The region monitoring within startMonitoring(for:) does not include a conditional check for the background state, which is consistent with the expected behavior since region monitoring should continue in the background.

  • 280-281: The call to setupAppLifeCycleNotifications() within setupLocationManager() ensures that lifecycle notifications are set up during the initialization of the location manager.

  • 291-294: The configuration of pausesLocationUpdatesAutomatically and showsBackgroundLocationIndicator within setupLocationManager() is correctly set to align with the intended behavior of continuous location updates and visibility of the location indicator in the background.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Review Status

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between a33ab33 and 188baac.
Files selected for processing (3)
  • Sources/UBLocation/LocalNotificationHelper.swift (1 hunks)
  • Sources/UBLocation/UBLocationManager.swift (19 hunks)
  • Sources/UBLocation/UBLocationManagerDelegateWrapper.swift (1 hunks)
Additional comments not posted (2)
Sources/UBLocation/UBLocationManager.swift (2)

318-324: Ensure that stopLocationMonitoring and startLocationMonitoringForAllDelegates are correctly handling the app's transition to the background without causing unnecessary stops and starts of location monitoring.


506-521: Ensure that the decision to start location updates based on appIsInBackground and usage.contains(.backgroundLocation) is correctly implemented and does not lead to unintended behavior when the app transitions between foreground and background.

Verification successful

Given the need to verify the logic for starting location updates based on the app's background status and the usage of location services, and considering the limitations of the previous script, let's attempt to find related code snippets or comments in the codebase that might provide insight into how these conditions are handled. Specifically, we'll look for references to appIsInBackground, backgroundLocation, and how location updates are started or paused based on these conditions.


The verification process has confirmed that the logic for starting location updates in UBLocationManager, based on the app's background status and the specified usage of location services, is correctly implemented. The code appropriately checks if the app is in the background and if the usage includes background location updates before starting location updates. This approach aligns with the intended behavior, ensuring that location updates are managed correctly as the app transitions between foreground and background states.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Verify the logic for starting location updates based on background status and usage.
echo "Manual review required to ensure correct logic for starting location updates in UBLocationManager."

Length of output: 206



Script:

#!/bin/bash
# Search for references to appIsInBackground, backgroundLocation, and starting/pausing location updates.
rg "appIsInBackground" -C 5
rg "backgroundLocation" -C 5
rg "startUpdatingLocation" -C 5
rg "pausedDelegateIds" -C 5

Length of output: 23061

notification.body = body
notification.sound = .default

notificationCenter.add(UNNotificationRequest(identifier: UUID().uuidString, content: notification, trigger: UNTimeIntervalNotificationTrigger(timeInterval: 3, repeats: false)), withCompletionHandler: nil)
Copy link

Choose a reason for hiding this comment

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

Consider adding error handling for the notification scheduling completion handler to log or handle potential errors.

- notificationCenter.add(UNNotificationRequest(identifier: UUID().uuidString, content: notification, trigger: UNTimeIntervalNotificationTrigger(timeInterval: 3, repeats: false)), withCompletionHandler: nil)
+ notificationCenter.add(UNNotificationRequest(identifier: UUID().uuidString, content: notification, trigger: UNTimeIntervalNotificationTrigger(timeInterval: 3, repeats: false))) { error in
+     if let error = error {
+         // Log or handle the error appropriately
+         print("Error scheduling notification: \(error)")
+     }
+ }

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
notificationCenter.add(UNNotificationRequest(identifier: UUID().uuidString, content: notification, trigger: UNTimeIntervalNotificationTrigger(timeInterval: 3, repeats: false)), withCompletionHandler: nil)
notificationCenter.add(UNNotificationRequest(identifier: UUID().uuidString, content: notification, trigger: UNTimeIntervalNotificationTrigger(timeInterval: 3, repeats: false))) { error in
if let error = error {
// Log or handle the error appropriately
print("Error scheduling notification: \(error)")
}
}

Comment on lines 20 to 28
func wantsUpdate(for usg: Set<UBLocationManager.LocationMonitoringUsage>?, isBackground: Bool) -> Bool {
if let usg {
guard !usage.isDisjoint(with: usg) else { return false }
let union = usage.union(usg)
return isBackground ? union.requiresBackgroundUpdates : true
} else {
return isBackground ? usage.requiresBackgroundUpdates : true
}
}
Copy link

Choose a reason for hiding this comment

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

Add documentation to the wantsUpdate method to explain its purpose, parameters, and return value.

+    /// Determines whether an update is needed based on the specified usage and background status.
+    ///
+    /// - Parameters:
+    ///   - usg: The set of `LocationMonitoringUsage` to consider for the update.
+    ///   - isBackground: A Boolean value indicating whether the app is currently in the background.
+    /// - Returns: A Boolean value indicating whether an update is needed.

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
func wantsUpdate(for usg: Set<UBLocationManager.LocationMonitoringUsage>?, isBackground: Bool) -> Bool {
if let usg {
guard !usage.isDisjoint(with: usg) else { return false }
let union = usage.union(usg)
return isBackground ? union.requiresBackgroundUpdates : true
} else {
return isBackground ? usage.requiresBackgroundUpdates : true
}
}
/// Determines whether an update is needed based on the specified usage and background status.
///
/// - Parameters:
/// - usg: The set of `LocationMonitoringUsage` to consider for the update.
/// - isBackground: A Boolean value indicating whether the app is currently in the background.
/// - Returns: A Boolean value indicating whether an update is needed.
func wantsUpdate(for usg: Set<UBLocationManager.LocationMonitoringUsage>?, isBackground: Bool) -> Bool {
if let usg {
guard !usage.isDisjoint(with: usg) else { return false }
let union = usage.union(usg)
return isBackground ? union.requiresBackgroundUpdates : true
} else {
return isBackground ? usage.requiresBackgroundUpdates : true
}
}

Comment on lines 68 to 79
private func delegates(onlyActive: Bool = false, usage: Set<LocationMonitoringUsage>? = nil) -> [UBLocationManagerDelegate] {
if onlyActive {
return delegateWrappers.values.compactMap {
if $0.wantsUpdate(for: usage, isBackground: appIsInBackground) {
return $0.delegate
} else {
return nil
}
}
} else {
return delegateWrappers.values.compactMap(\.delegate)
}
Copy link

Choose a reason for hiding this comment

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

Refactor the delegates method to improve readability by using a single return statement.

-        if onlyActive {
-            return delegateWrappers.values.compactMap {
-                if $0.wantsUpdate(for: usage, isBackground: appIsInBackground) {
-                    return $0.delegate
-                } else {
-                    return nil
-                }
-            }
-        } else {
-            return delegateWrappers.values.compactMap(\.delegate)
-        }
+        return delegateWrappers.values.compactMap { wrapper in
+            onlyActive && !wrapper.wantsUpdate(for: usage, isBackground: appIsInBackground) ? nil : wrapper.delegate
+        }

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
private func delegates(onlyActive: Bool = false, usage: Set<LocationMonitoringUsage>? = nil) -> [UBLocationManagerDelegate] {
if onlyActive {
return delegateWrappers.values.compactMap {
if $0.wantsUpdate(for: usage, isBackground: appIsInBackground) {
return $0.delegate
} else {
return nil
}
}
} else {
return delegateWrappers.values.compactMap(\.delegate)
}
private func delegates(onlyActive: Bool = false, usage: Set<LocationMonitoringUsage>? = nil) -> [UBLocationManagerDelegate] {
return delegateWrappers.values.compactMap { wrapper in
onlyActive && !wrapper.wantsUpdate(for: usage, isBackground: appIsInBackground) ? nil : wrapper.delegate
}

Comment on lines 654 to 656
if UIApplication.shared.applicationState == .background {
LocalNotificationHelper.showDebugNotification(title: "Background notifyDelegates", body: "Delegate Count: \(delegates(onlyActive: true).count)")
}
Copy link

Choose a reason for hiding this comment

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

Consider removing or guarding debug notifications with a compile-time flag to prevent them from being included in production builds.

-            LocalNotificationHelper.showDebugNotification(title: "Background notifyDelegates", body: "Delegate Count: \(delegates(onlyActive: true).count)")
+            #if DEBUG
+            LocalNotificationHelper.showDebugNotification(title: "Background notifyDelegates", body: "Delegate Count: \(delegates(onlyActive: true).count)")
+            #endif

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
if UIApplication.shared.applicationState == .background {
LocalNotificationHelper.showDebugNotification(title: "Background notifyDelegates", body: "Delegate Count: \(delegates(onlyActive: true).count)")
}
if UIApplication.shared.applicationState == .background {
#if DEBUG
LocalNotificationHelper.showDebugNotification(title: "Background notifyDelegates", body: "Delegate Count: \(delegates(onlyActive: true).count)")
#endif
}

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Review Status

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 188baac and 23d7f0a.
Files selected for processing (1)
  • Sources/UBLocation/UBLocationManager.swift (18 hunks)
Additional comments not posted (10)
Sources/UBLocation/UBLocationManager.swift (10)

11-11: The import of UIKit is appropriate for handling app lifecycle events.


64-71: The refactoring of the delegates method improves readability and conciseness.


97-97: The addition of appIsInBackground is crucial for conditional location monitoring based on the app's lifecycle.


301-304: Setting up lifecycle event observers for didEnterBackgroundNotification and didBecomeActiveNotification is essential for managing location monitoring based on the app's state.


306-315: The implementation of appDidEnterBackground correctly handles stopping location updates when the app moves to the background, aligning with the PR's objectives.


309-309: Guarding debug notifications with a compile-time flag is a good practice to prevent their inclusion in production builds.


295-323: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [285-299]

The addition of new methods for handling location updates and permissions aligns with the PR's objectives and is well-implemented.


334-340: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [337-346]

Updates to authorization status handling support the new functionality and correctly handle different authorization statuses.


306-315: The implementation of conditional location monitoring effectively adjusts location updates based on the app's state, fulfilling the PR's objectives.


492-511: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [495-519]

Miscellaneous changes, including minor refactoring and adjustments to existing methods, support the new functionality and are correctly implemented.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Review Status

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 23d7f0a and c175150.
Files selected for processing (1)
  • Sources/UBLocation/UBLocationManager.swift (18 hunks)

@@ -8,6 +8,7 @@

import CoreLocation
import UBFoundation
import UIKit
Copy link

Choose a reason for hiding this comment

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

Document the reason for importing UIKit, as it's not immediately clear from the context.

+ // UIKit is imported for handling app lifecycle events.

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
import UIKit
// UIKit is imported for handling app lifecycle events.
import UIKit

Comment on lines +64 to +72
private func delegates(onlyActive: Bool = false, usage: Set<LocationMonitoringUsage>? = nil) -> [UBLocationManagerDelegate] {
delegateWrappers.values.compactMap { wrapper in
if onlyActive {
wrapper.wantsUpdate(for: usage, isBackground: appIsInBackground) ? wrapper.delegate : nil
} else {
wrapper.delegate
}
}
}
Copy link

Choose a reason for hiding this comment

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

Refactor the delegates method to improve readability by using a single return statement.

-        if onlyActive {
-            return delegateWrappers.values.compactMap {
-                if $0.wantsUpdate(for: usage, isBackground: appIsInBackground) {
-                    return $0.delegate
-                } else {
-                    return nil
-                }
-            }
-        } else {
-            return delegateWrappers.values.compactMap(\.delegate)
-        }
+        return delegateWrappers.values.compactMap { wrapper in
+            onlyActive && !wrapper.wantsUpdate(for: usage, isBackground: appIsInBackground) ? nil : wrapper.delegate
+        }

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
private func delegates(onlyActive: Bool = false, usage: Set<LocationMonitoringUsage>? = nil) -> [UBLocationManagerDelegate] {
delegateWrappers.values.compactMap { wrapper in
if onlyActive {
wrapper.wantsUpdate(for: usage, isBackground: appIsInBackground) ? wrapper.delegate : nil
} else {
wrapper.delegate
}
}
}
private func delegates(onlyActive: Bool = false, usage: Set<LocationMonitoringUsage>? = nil) -> [UBLocationManagerDelegate] {
return delegateWrappers.values.compactMap { wrapper in
onlyActive && !wrapper.wantsUpdate(for: usage, isBackground: appIsInBackground) ? nil : wrapper.delegate
}
}

delegateWrappers.values
.map(\.usage)
.reduce([]) { $0.union($1) }
}

private var appIsInBackground: Bool = UIApplication.shared.applicationState == .background
Copy link

Choose a reason for hiding this comment

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

Consider removing or guarding debug notifications with a compile-time flag to prevent them from being included in production builds.

-            LocalNotificationHelper.showDebugNotification(title: "Background notifyDelegates", body: "Delegate Count: \(delegates(onlyActive: true).count)")
+            #if DEBUG
+            LocalNotificationHelper.showDebugNotification(title: "Background notifyDelegates", body: "Delegate Count: \(delegates(onlyActive: true).count)")
+            #endif

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
private var appIsInBackground: Bool = UIApplication.shared.applicationState == .background
private var appIsInBackground: Bool = UIApplication.shared.applicationState == .background

Comment on lines +304 to +307
private func setupAppLifeCycleNotifications() {
NotificationCenter.default.addObserver(self, selector: #selector(appDidEnterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(appDidBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
}
Copy link

Choose a reason for hiding this comment

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

Ensure app lifecycle notifications are properly removed to prevent memory leaks.

+ deinit {
+     NotificationCenter.default.removeObserver(self)
+ }

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
private func setupAppLifeCycleNotifications() {
NotificationCenter.default.addObserver(self, selector: #selector(appDidEnterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(appDidBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
}
private func setupAppLifeCycleNotifications() {
NotificationCenter.default.addObserver(self, selector: #selector(appDidEnterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(appDidBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self)
}

Copy link

Quality Gate Passed Quality Gate passed

Issues
6 New issues
0 Accepted issues

Measures
0 Security Hotspots
No data about Coverage
0.0% Duplication on New Code

See analysis details on SonarCloud

@ubfelix ubfelix merged commit 0cf0b01 into main Apr 10, 2024
2 of 4 checks passed
@ubfelix ubfelix deleted the bugfix/ublocationmanager-background-behavior branch April 10, 2024 16:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants