MirroredIndex

@objcMembers
public class MirroredIndex : Index

An online index that can also be mirrored locally.

Note

You cannot construct this class directly. Please use OfflineClient.index(withName:) to obtain an instance.

Note

Requires Algolia Offline Core. The OfflineClient.enableOfflineMode(...) method must be called with a valid license key prior to calling any offline-related method.

When created, an instance of this class has its mirrored flag set to false, and behaves like a normal, online Index. When the mirrored flag is set to true, the index becomes capable of acting upon local data.

Warning

It is a programming error to call methods acting on the local data when mirrored is false. Doing so will result in an assertion error being raised.

Request strategy

When the index is mirrored and the device is online, it becomes possible to transparently switch between online and offline requests. There is no single best strategy for that, because it depends on the use case and the current network conditions. You can choose the strategy through the requestStrategy property. The default is FallbackOnFailure, which will always target the online API first, then fallback to the offline mirror in case of failure (including network unavailability).

Note

If you want to explicitly target either the online API or the offline mirror, doing so is always possible using searchOnline(...) or searchOffline(...).

Note

The strategy applies to:

  • search(...)
  • searchDisjunctiveFaceting(...)
  • multipleQueries(...)
  • getObject(...)
  • getObjects(...)

Bootstrapping

Before the first sync has successfully completed, a mirrored index is not available offline, because it has simply no data to search in yet. In most cases, this is not a problem: the app will sync as soon as instructed, so unless the device is offline when the app is started for the first time, or unless search is required right after the first launch, the user should not notice anything.

However, in some cases, you might need to have offline data available as soon as possible. To achieve that, MirroredIndex provides a manual build feature.

Manual build

Manual building consists in specifying the source data for your index from local files, instead of downloading it from the API. Namely, you need:

  • the index settings (one JSON file); and
  • the objects (as many JSON files as needed, each containing an array of objects).

Those files are typically embedded in the application as resources, although any other origin works too.

Conditional bootstrapping

To avoid replacing the local mirror every time the app is started (and potentially overwriting more recent data synced from the API), you should test whether the index already has offline data using the hasOfflineData property.

Discussion

Warning

We strongly advise against prepackaging index files. While it may work in some cases, Algolia Offline makes no guarantee whatsoever that the index file format will remain backward-compatible forever, nor that it is independent of the hardware architecture (e.g. 32 bits vs 64 bits, or Little Endian vs Big Endian). Instead, always use the manual build feature.

While a manual build involves computing the offline index on the device, and therefore incurs a small delay before the mirror is actually usable, using plain JSON offers several advantages compared to prepackaging the index file itself:

  • You only need to ship the raw object data, which is smaller than shipping an entire index file, which contains both the raw data and indexing metadata.

  • Plain JSON compresses well with standard compression techniques like GZip, whereas an index file uses a binary format which doesn’t compress very efficiently.

  • Build automation is facilitated: you can easily extract the required data from your back-end, whereas building an index would involve running the app on each mobile platform as part of your build process and capturing the filesystem.

Also, the build process is purposedly single-threaded across all indices, which means that on most modern devices with multi-core CPUs, the impact of manual building on the app’s performance will be very moderate, especially regarding UI responsiveness.

Limitations

Algolia’s core features are fully supported offline, including (but not limited to): ranking, typo tolerance, filtering, faceting, highlighting/snippeting

However, and partly due to tight memory, CPU and disk space constraints, some features are disabled:

  • Synonyms are only partially supported:

    • Multi-way (regular) synonyms are fully supported.
    • One-way synonyms are not supported.
    • Alternative corrections are limited to one alternative (compared to multiple alternatives with online indices).
    • Placeholders are fully supported.
  • Dictionary-based plurals are not supported. (Simple plurals with a final S are supported.)

  • IP geolocation (see Query.aroundLatLngViaIP) is not supported.

  • CJK segmentation is not supported.

Resource handling

Native resources are lazily instantiated when mirrored is set to true. They are released when the object is released, or if mirrored is set to false again.

  • Default minimum delay between two syncs.

    Declaration

    Swift

    @objc
    public static let defaultDelayBetweenSyncs: TimeInterval
  • Key used to indicate the origin of results in the returned JSON.

    Declaration

    Swift

    @objc
    public static let jsonKeyOrigin: String
  • Value for jsonKeyOrigin indicating that the results come from the local mirror.

    Declaration

    Swift

    @objc
    public static let jsonValueOriginLocal: String
  • Value for jsonKeyOrigin indicating that the results come from the online API.

    Declaration

    Swift

    @objc
    public static let jsonValueOriginRemote: String
  • The offline client used by this index.

    Declaration

    Swift

    @objc
    public var offlineClient: OfflineClient { get }
  • Whether the index is mirrored locally. Default = false.

    Note

    Setting this property to true create the resources required to access the local mirror. Setting it to false does not deallocate those resources.

    Declaration

    Swift

    @objc
    public var mirrored: Bool { get set }
  • Data selection queries.

    Declaration

    Swift

    @objc
    public var dataSelectionQueries: [DataSelectionQuery] { get set }
  • Minimum delay between two syncs.

    Declaration

    Swift

    @objc
    public var delayBetweenSyncs: TimeInterval
  • Date of the last successful sync, or nil if the index has never been successfully synced.

    Declaration

    Swift

    @objc
    public var lastSuccessfulSyncDate: Date? { get }
  • Error encountered by the current/last sync (if any).

    Declaration

    Swift

    @objc
    public private(set) var syncError: Error?
  • Whether this index has offline data on disk.

    Declaration

    Swift

    @objc
    public var hasOfflineData: Bool { get }
  • Add a data selection query to the local mirror. The query is not run immediately. It will be run during the subsequent refreshes.

    Precondition

    Mirroring must have been activated on this index (see the mirrored property).

    Declaration

    Swift

    @objc
    public func addDataSelectionQuery(_ query: DataSelectionQuery)
  • Add any number of data selection queries to the local mirror. The query is not run immediately. It will be run during the subsequent refreshes.

    Precondition

    Mirroring must have been activated on this index (see the mirrored property).

    Declaration

    Swift

    @objc
    public func addDataSelectionQueries(_ queries: [DataSelectionQuery])
  • Launch a sync. This unconditionally launches a sync, unless one is already running.

    Precondition

    Mirroring must have been activated on this index (see the mirrored property).

    Declaration

    Swift

    @objc
    public func sync()
  • Launch a sync if needed. This takes into account the delay between syncs.

    Precondition

    Mirroring must have been activated on this index (see the mirrored property).

    Declaration

    Swift

    @objc
    public func syncIfNeeded()
  • Replace the local mirror with local data.

    Note

    Cancelling the request does not cancel the build; it merely prevents the completion handler from being called.

    Declaration

    Swift

    @discardableResult
    @objc
    public func buildOffline(settingsFile: String, objectFiles: [String], completionHandler: CompletionHandler? = nil) -> Operation

    Parameters

    settingsFile

    Absolute path to the file containing the index settings, in JSON format.

    objectFiles

    Absolute path(s) to the file(s) containing the objects. Each file must contain an array of objects, in JSON format.

    completionHandler

    An optional completion handler to be notified when the build has finished.

    Return Value

    A cancellable operation.

  • Browse the local mirror (initial call). Same semantics as Index.browse(query:completionHandler:).

    Declaration

    Swift

    @discardableResult
    @objc(browseMirrorWithQuery:completionHandler:)
    public func browseMirror(query: Query, completionHandler: @escaping CompletionHandler) -> Operation
  • Browse the index from a cursor. Same semantics as Index.browse(from:completionHandler:).

    Declaration

    Swift

    @discardableResult
    @objc(browseMirrorFromCursor:completionHandler:)
    public func browseMirror(from cursor: String, completionHandler: @escaping CompletionHandler) -> Operation
  • Notification sent when the sync has started.

    Declaration

    Swift

    @objc
    public static let SyncDidStartNotification: Notification.Name
  • Notification sent when the sync has finished.

    Declaration

    Swift

    @objc
    public static let SyncDidFinishNotification: Notification.Name
  • Notification user info key used to pass the error, when an error occurred during a sync or a build.

    Declaration

    Swift

    @objc
    public static let errorKey: String
  • Notification sent when the build of the local mirror has started. This notification is sent both for syncs or manual builds.

    Declaration

    Swift

    @objc
    public static let BuildDidStartNotification: Notification.Name
  • Notification sent when the build of the local mirror has finished. This notification is sent both for syncs or manual builds.

    Declaration

    Swift

    @objc
    public static let BuildDidFinishNotification: Notification.Name