firebase / firebase-ios-sdk

Firebase SDK for Apple App Development
https://firebase.google.com
Apache License 2.0
5.67k stars 1.49k forks source link

Callbacks are not called when client is offline #13012

Closed liamcharger closed 5 months ago

liamcharger commented 5 months ago

Description

When using update, delete, or write functions when the client is offline, callbacks do not appear to be called.

Firestore.firestore().collection("users").document(uid).collection("songs").document(song.id!)
    .updateData(["notes": notes]) { error in
        if let error = error {
               print(error.localizedDescription)
        }
                // Sheet isn't dismissed...
                dismiss()
    }

It works fine when the client is online.

Reproducing the issue

Run this code:

struct ContentView: View {
    @State private var showSheet = false

    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
            Button {
                showSheet = true
            } label: {
                Text("Present Sheet")
            }
        }
        .padding()
    }

    var sheetContent: some View {
        VStack {
            Button {
                Firestore.firestore().collection("your-collection").document("your-doc")
                    .updateData(["your-field": "your-data"]) { error in
                        if let error = error {
                            print(error.localizedDescription)
                            return
                        }
                        showSheet = false
                    }
            } label: {
                Text("Call Firestore Function")
            }
        }
    }
}

Firebase SDK Version

10.26.0

Xcode Version

15.3

Installation Method

Swift Package Manager

Firebase Product(s)

Analytics, Authentication, Firestore, In-App Messaging, Remote Config

Targeted Platforms

iOS

If using Swift Package Manager, the project's Package.resolved

{
  "originHash" : "d1d2645338e6d65e01cc36dc0d1f106d40d171095ee7fb99213041202e59ed39",
  "pins" : [
    {
      "identity" : "abseil-cpp-binary",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/google/abseil-cpp-binary.git",
      "state" : {
        "revision" : "748c7837511d0e6a507737353af268484e1745e2",
        "version" : "1.2024011601.1"
      }
    },
    {
      "identity" : "app-check",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/google/app-check.git",
      "state" : {
        "revision" : "076b241a625e25eac22f8849be256dfb960fcdfe",
        "version" : "10.19.1"
      }
    },
    {
      "identity" : "bottomsheet",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/adamfootdev/BottomSheet",
      "state" : {
        "revision" : "0e6db002eeb5e3ba402e94dfe6a120f78b5a64df",
        "version" : "0.2.4"
      }
    },
    {
      "identity" : "firebase-ios-sdk",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/firebase/firebase-ios-sdk",
      "state" : {
        "revision" : "9d17b500cd98d9a7009751ad62f802e152e97021",
        "version" : "10.26.0"
      }
    },
    {
      "identity" : "googleappmeasurement",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/google/GoogleAppMeasurement.git",
      "state" : {
        "revision" : "16244d177c4e989f87b25e9db1012b382cfedc55",
        "version" : "10.25.0"
      }
    },
    {
      "identity" : "googledatatransport",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/google/GoogleDataTransport.git",
      "state" : {
        "revision" : "a637d318ae7ae246b02d7305121275bc75ed5565",
        "version" : "9.4.0"
      }
    },
    {
      "identity" : "googleutilities",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/google/GoogleUtilities.git",
      "state" : {
        "revision" : "26c898aed8bed13b8a63057ee26500abbbcb8d55",
        "version" : "7.13.1"
      }
    },
    {
      "identity" : "grpc-binary",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/google/grpc-binary.git",
      "state" : {
        "revision" : "e9fad491d0673bdda7063a0341fb6b47a30c5359",
        "version" : "1.62.2"
      }
    },
    {
      "identity" : "gtm-session-fetcher",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/google/gtm-session-fetcher.git",
      "state" : {
        "revision" : "9534039303015a84837090d20fa21cae6e5eadb6",
        "version" : "3.3.2"
      }
    },
    {
      "identity" : "interop-ios-for-google-sdks",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/google/interop-ios-for-google-sdks.git",
      "state" : {
        "revision" : "2d12673670417654f08f5f90fdd62926dc3a2648",
        "version" : "100.0.0"
      }
    },
    {
      "identity" : "leveldb",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/firebase/leveldb.git",
      "state" : {
        "revision" : "a0bc79961d7be727d258d33d5a6b2f1023270ba1",
        "version" : "1.22.5"
      }
    },
    {
      "identity" : "nanopb",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/firebase/nanopb.git",
      "state" : {
        "revision" : "b7e1104502eca3a213b46303391ca4d3bc8ddec1",
        "version" : "2.30910.0"
      }
    },
    {
      "identity" : "promises",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/google/promises.git",
      "state" : {
        "revision" : "540318ecedd63d883069ae7f1ed811a2df00b6ac",
        "version" : "2.4.0"
      }
    },
    {
      "identity" : "swift-package-manager-google-mobile-ads",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/googleads/swift-package-manager-google-mobile-ads.git",
      "state" : {
        "revision" : "9ab66e38f5f0c2d02f2b024b1babd880130f19bf",
        "version" : "11.3.0"
      }
    },
    {
      "identity" : "swift-package-manager-google-user-messaging-platform",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/googleads/swift-package-manager-google-user-messaging-platform.git",
      "state" : {
        "revision" : "cfe8b2ae16b9bc81f4cdf1d1a12a01a452489c32",
        "version" : "2.3.0"
      }
    },
    {
      "identity" : "swift-protobuf",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-protobuf.git",
      "state" : {
        "revision" : "9f0c76544701845ad98716f3f6a774a892152bcb",
        "version" : "1.26.0"
      }
    },
    {
      "identity" : "swiftui-introspect",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/siteline/swiftui-introspect.git",
      "state" : {
        "revision" : "0cd2a5a5895306bc21d54a2254302d24a9a571e4",
        "version" : "1.1.3"
      }
    }
  ],
  "version" : 3
}

Note: there are some other packages included that I use in my project.

google-oss-bot commented 5 months ago

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

MarkDuckworth commented 5 months ago

This is expected behavior and is covered in the API reference docs. The completion handler is not called until the write is acknowledged by the server, so the completion handler cannot be called while offline.

I'm going to close this, but if you have follow up concerns, please let us know.

liamcharger commented 5 months ago

How should I handle this properly then? Should I just dismiss the sheet, and not worry if there's an error, or is there a better way? Are errors even called when the client is offline?

MarkDuckworth commented 5 months ago

I generally can't advise you on how to architect your app. But if you decide it works for you then it would be possible to take an action, like dismissing the sheet, after the call updateData. You can still handle errors when the callback is eventually called after the device reconnects.

If your use case requires immediate feedback from the Firestore backend, like confirming that the write was successful, then there's no other way to handle this use case than to be online.