Flint
final public class Flint
This is the Flint class, with entry points for application-level convenience functions and metadata.
Your application must call Flint.quickSetup
or Flint.setup
at startup to bootstrap the Feature & Action declarations,
to set up all the URL mappings and other conventions.
Failure to do so will usually result in a precondition failure in your app.
-
Undocumented
See moreDeclaration
Swift
public class DependenciesConfig
-
Undocumented
See moreDeclaration
Swift
public struct Dependencies
-
Undocumented
Declaration
Swift
public private(set) static var dependencies: Flint.Dependencies?
-
The default link generator to use when creating automatic links to actions for Activities and so on. This is populated by default in
quickSetup
with a generator that uses the first app scheme and first domain.If you need to create URLs to actions in your app, use this. Example:
let appUrl = Flint.linkCreator.appLink(to: MyFeature.someAction, with: someInput) let webUrl = Flint.linkCreator.universalLink(to: MyFeature.someAction, with: someInput)
Declaration
Swift
public static var linkCreator: LinkCreator!
-
The dispatcher for all actions
Declaration
Swift
public static var dispatcher: ActionDispatcher
-
The availability checker for conditional features
Declaration
Swift
public static var availabilityChecker: AvailabilityChecker { get }
-
The permission checker to verify availability of system permissions. You should not need to replace this unless you are writing tests and want a mock instance
Declaration
Swift
public static var permissionChecker: SystemPermissionChecker { get }
-
The constraints evaluator used to define the constraints on features
Declaration
Swift
public static var constraintsEvaluator: ConstraintsEvaluator { get }
-
The user feature toggles implementation. By default it will use
UserDefaults
for this, replace with your own implementation if you’d like to store these elsewhere.Declaration
Swift
public static var userFeatureToggles: UserFeatureToggles? { get }
-
The purchase tracker to use to verify purchased products. Replace this with your own implementation if the Flint StoreKit tracker is not sufficient.
Declaration
Swift
public static var purchaseTracker: PurchaseTracker? { get }
-
The metadata for all features available
See
FlintUI.FeatureBrowserFeature
Declaration
Swift
public private(set) static var allFeatures: Set<FeatureMetadata>
-
The metadata for only the conditional features
See
FlintUI.FeatureBrowserFeature
Declaration
Swift
public static var conditionalFeatures: Set<FeatureMetadata> { get }
-
Get the metadata for the specified feature
Declaration
Swift
public static func metadata(for feature: FeatureDefinition.Type) -> FeatureMetadata?
-
Get the metadata for the specified action binding
Declaration
Swift
public static func metadata<FeatureType, ActionType>(for action: StaticActionBinding<FeatureType, ActionType>) -> ActionMetadata? where FeatureType : FeatureDefinition, ActionType : Action
-
Call for the default setup of loggers, link creation, automatic logging of action start/end.
- param group: The main group of your application features
- param domains: The list of universal link domains your app supports. The first one will be used to create new universal links. (Domains vannot be extracted automatically by Flint)
- param initialDebugLogLevel: The default log level for debug logging. Default if not specified is
.debug
- param initialProductionLogLevel: The default log level for production logging. Default if not specified is
.info
- param briefLogging: Set to
true
for logging with less verbosity (primarily dates)
Declaration
Swift
public static func quickSetup(_ group: FeatureGroup.Type, domains: [String] = [], initialDebugLogLevel: LoggerLevel = .debug, initialProductionLogLevel: LoggerLevel = .off, briefLogging: Bool = true, configuration: ((_ dependencies: DependenciesConfig) -> Void)? = nil)
-
Call to set up your application features and Flint’s internal features.
Use this only if you have manually configured your logging and action sessions.
Declaration
Swift
public static func setup(_ group: FeatureGroup.Type, configuration: ((_ dependencies: DependenciesConfig) -> Void)? = nil)
-
Register the feature with Flint. Call this to register specific features if they are not already registered by way of being subfeatures of a group. Only call this if you have not passed this feature to
setup
orquickSetup
.Registration of features at runtime is required because Swift does not provide runtime discovery of types conforming to a protocol, without using the Objective-C runtime upon which we do not want to depend, to be future proof. We need to know which types are features because:
- We want to be able to show the info about all the features in debug UIs
- Some apps will want to be able to show info about features in their user-facing UIs
- We need to process the conventions on the types to know what actions they support
- We need to process the conventions on the types to know what URL mappings they support, if any
- We need to know if a feature is enabled currently, and to test for permissions and preconditions
We can switch to lazy registration (processing of conventions etc.) at a later point to reduce startup overheads. However we will still need to know the types required to e.g. invoke an action on a feature via a URL, or continue an activity, or perform a Siri shortcut.
If users only register some of their feature types, they would have to always remember to register all feature types that require URL mappings and/or have actions that support activity continuation. This is very error prone, and should be discouraged. It is better to minimize the overheads at the point of calling
register
and defer any processing where possible. Even in this case it is unlikely to be very profitable because you need to evaluate the conventions in order to know whether or not an Action or Feature is going to be required for URL or activity handling.Note
Even with the Objective-C runtime, iterating (and hence forcing+load
) on all Obj-C compatible classes is a slow process as there are thousands of them.Declaration
Swift
public static func register(_ feature: FeatureDefinition.Type)
-
Register a feature group with Flint. This will recursively register all the subfeatures. Only call this if you have not passed this group to
setup
orquickSetup
.Registration of features at runtime is required because Swift does not provide runtime discovery of types conforming to a protocol, without using the Objective-C runtime upon which we do not want to depend, to be future proof. We need to know which types are features because:
- We want to be able to show the info about all the features in debug UIs
- Some apps will want to be able to show info about features in their user-facing UIs
- We need to process the conventions on the types to know what actions they support
- We need to process the conventions on the types to know what URL mappings they support, if any
- We need to know if a feature is enabled currently, and to test for permissions and preconditions
We can switch to lazy registration (processing of conventions etc.) at a later point to reduce startup overheads. However we will still need to know the types required to e.g. invoke an action on a feature via a URL, or continue an activity, or perform a Siri shortcut.
If users only register some of their feature types, they would have to always remember to register all feature types that require URL mappings and/or have actions that support activity continuation. This is very error prone, and should be discouraged. It is better to minimize the overheads at the point of calling
register
and defer any processing where possible. Even in this case it is unlikely to be very profitable because you need to evaluate the conventions in order to know whether or not an Action or Feature is going to be required for URL or activity handling.Note
Even with the Objective-C runtime, iterating (and hence forcing+load
) on all Obj-C compatible classes is a slow process as there are thousands of them.Declaration
Swift
public static func register(group: FeatureGroup.Type)
-
Open the specified URL, dispatching the appropriately mapped action if it has been set up via a
URLMapped
Feature.Add this to your AppDelegate:
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool { let result: URLRoutingResult = Flint.open(url: url, with: presentationRouter) return result == .success }
- param url: The URL that may point to an action in the app.
- param presentationRouter: The object that will return the correct presenter for the router
- return: The routing result indicating whether or not an action was found and performed
Declaration
Swift
public static func open(url: URL, with presentationRouter: PresentationRouter) -> MappedActionResult
-
Call this to continue an
NSUserActivity
that may map to an Action in your application.Add this to your AppDelegate:
Perform the action required to continue a user activity.
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool { return Flint.continueActivity(activity: userActivity, with: presentationRouter) == .success }
- param activity: The activity pass to the application - param presentationRouter: The object that will return the correct presenter for the router - return: The routing result indicating whether or not an action was found and performed
Declaration
Swift
public static func continueActivity(activity: NSUserActivity, with presentationRouter: PresentationRouter) -> MappedActionResult
-
Gather all logs, timelines and stacks into a single ZIP suitable for sharing.
This will use
DebugReporting
to enumerate over all theDebugReportable
objects in the app, asking each to generate their reports, and then it will zip all the contents into a single file.- return: A URL pointing to a Zip file containing the reports. You should delete this after generating it.
Declaration
Swift
public static func gatherReportZip(options: Set<DebugReportOption>) -> URL
-
Undocumented
Declaration
Swift
static func resetForTesting()