Checking Equality of ApplicationToken Instances in Swift

Hi everyone,

I'm working on a Swift application and trying to determine whether an application has exceeded its limit based on an ApplicationToken. I have the following function to check if the current app's token matches any of the tokens stored when the app limit is reached:

private func isAppLimitExceeded(for application: Application?) -> Bool {
    guard let application = application, let appToken = application.token else { return false }
    let exceededTokens = configManager.getAppLimitExceededTokens()
               
    return exceededTokens.contains { exceededToken in
        appToken == exceededToken
    }
}

The function configManager.getAppLimitExceededTokens() returns a list of [ApplicationToken] that were saved in UserDefaults when an app limit is reached. The goal is to use the isAppLimitExceeded method to verify if the current shield for the app is triggered due to a limit/threshold being exceeded.

This function is part of a class that conforms to the ShieldConfigurationDataSource protocol:

class ShieldConfigurationExtension: ShieldConfigurationDataSource {
    // ...
}

My concern is whether comparing two ApplicationToken instances using == is a reliable method for determining if they are equal.

  • Are ApplicationToken objects guaranteed to be comparable with == out of the box, or do I need to implement Equatable or another method of comparison?
  • Could there be issues with tokens stored in UserDefaults not matching due to reference or serialization differences?

Any guidance on how to ensure proper comparison of these tokens would be appreciated!

Thanks!

Yes, using == to compare Tokens is reliable. When looking in the docs, you can also see why that is the case.

All Tokens are defined as following:

public typealias ActivityCategoryToken = Token<ActivityCategory>
public typealias ApplicationToken = Token<Application>
public typealias WebDomainToken = Token<WebDomain>

where

public struct Token<T> : Codable, Equatable, Hashable 

Therefore any Token you are comparing is Equatable. As you may know any struct that is implementing Equatable need to have the function

    static func == (lhs: Self, rhs: Self) -> Bool

which is the reason why it must work.

Regarding your second question

Could there be issues with tokens stored in UserDefaults not matching due to reference or serialization differences?

It depends on the implementation. If you're storing the tokens correctly inside the UserDefaults (using an AppGroup) there shouldn't be any problem, at least I myself haven't seen any. However when you're not using an AppGroup, the DeviceActivityMonitorExtension won't have access to the tokens due to it being sandboxed.

Hope I could help you!

@amalshyjo the issue you're seeing could be related to a bug that has been talked about in these posts:

and

This bug was introduced by Apple in iOS 17.5 in spring 2024, however until now they have not responded to our feedback reports.

I think it would be useful if you could file a feedback report on this as well, highlighting your perspective on the problem.

Hope that helps!

Checking Equality of ApplicationToken Instances in Swift
 
 
Q