We are building a solution for field technicians that utilize Apple iPhones out in the field to track data for installations at assigned sites. The iPhone is running a custom-built application that field techs utilize to view their list of assigned installations for the day. They can also log the necessary data for the installation including: Numbers, Text Data, and Photos. GPS location and timestamps are logged automatically by the application. All text/numeric data is stored inside of Quick Base. Photos are uploaded to an Amazon S3 bucket and the URL reference to the image is stored in Quick Base. The field technicians work in areas that have inconsistent data coverage. Therefore, the application has functionality to enable edited/added data to be stored locally while in an offline state.

The offline functionality has proven to cause some issues with data getting lost or not syncing properly to Quick Base. Some of the more common issues with the offline saving are: records missing data in some fields in Quick Base, images not coming through to Amazon S3, and full records occasionally getting completely lost. The offline mode currently pulls in a copy of the Quick Base tables to a local database on the user's device. When there is no Internet connection, the application makes updates in the local database. Once the Internet connection is reestablished, the app will synchronize the local database with Quick Base automatically.

Given the issues we've run into, is there a better way to maintain data integrity in the offline state to ensure data isn't getting lost? Is utilizing a local database the best way to accomplish the offline syncing capabilities?

Dani AI

Generated

You can make offline rock-solid, but not by mirroring server tables. That pattern invites partial writes (record saved, photos missing) and crash windows. is right about verify-and-retry; the missing piece is a durable outbox. Instead of editing the local copy of Quick Base tables, capture every user action as an immutable mutation with a client-generated UUID and a monotonic device sequence number. Persist it in SQLite in a single transaction and only mark it delivered after the server acknowledges the exact UUID. Add a custom field in Quick Base such as ClientMutationId so server-side writes are idempotent and duplicates are harmless.

For photos, treat media as a prerequisite step: upload each asset first (background URLSession, resume support, checksum verification), capture the final S3 key, then post the Quick Base record that references those keys. If the app crashes mid-flight, the next sync pass sees an undelivered mutation and resumes. Use exponential backoff with jitter and classify errors as retryable vs. fatal. Run a periodic reconciliation: ask Quick Base for recent ClientMutationId values and replay any missing ones. Also validate required fields offline so half-complete records never enter the outbox.

A minimal shape for the sync loop:

struct Mutation: Codable {
    let id: UUID
    let deviceSeq: Int64
    let type: String   // create, update, delete
    var payload: [String: AnyCodable]
    var assets: [LocalAsset]   // local URLs + intended S3 keys
}

func sync() {
    for m in db.pending().sorted(by: { $0.deviceSeq < $1.deviceSeq }) {
        guard uploadAssetsIfNeeded(m) else { scheduleRetry(m); continue }
        guard postRecordWithIdempotency(m) else { scheduleRetry(m); continue }
        db.markDelivered(m.id)
    }
}

To curb conflicts across multiple techs, store the server snapshot version/timestamp with each mutation. On edit, if the server has changed since your base snapshot, either do field-level merges (preferred) or raise a concise conflict UI. Avoid full-table local copies; sync the per-tech assignment set and keep a lightweight cursor for deltas.

The answer is yes but. The yes is just that but it requires a programmer to sit down with the client to discuss what the problems are then send the programmer out to fix the sync issues.

Today however I run into systems that were built without a top tier programmer and the owner wants this fixed. They often dismiss it as something simple if only someone will reveal the cure.

So your current code is losing records. Sounds like a verify, re-try system is needed.

PS. As to your local database part of the question. Your choice of how to design that. Both database and simple files to be sent later work.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.