1

I have a Firebase database connected to my IOS app with the GoogleService-Info.plist. In AppDelegate I configured the App FIRApp.configure(). I could read/write data.

Now, from within this IOS app, I would like to access another FireBase Database brevCustomer. For some reason let dbRef from viewDidLoad has a flag in Xcode saying this 'immutable value dbRef was never used' and the app crashes on the first line in fun startObserving() dbRef.observe(.value, with: { (snapshot: FIRDataSnapshot) in.

Could anyone show how to do the configuration so that I can read/write to brevCustomer database?

EDIT

Please consider the following scenario:

  • I have two IOS apps Customer and Worker and two Firebase Projects named CustomerFireBase and WorkerFirebase and I would like them to work in the following way.

  • Customer registers with email and password, logs in, makes a booking, and data is saved in CustomerFireBase.

  • Worker registers with email and password, logs is, observe WorkerFirebase for value changes or child added
    • read from CustomerFireBase
      • write to CustomerFireBase
      • write to WorkerFirebase

How can I achieve this? Basically, I need to get read/write access from one IOS app configured in the usual way with Firebase, to another Firebase Database contained in another Firebase project.

Class Claim {

  var dbRef:FIRDatabaseReference! //create a reference to Firebase database `brevCustomer`, not the one from .plist file

   override func viewDidLoad() {
       super.viewDidLoad()

     let app = FIRApp(named: "brevCustomer")
     let dbRef = FIRDatabase.database(app: app!).reference().child("Users")
     startObservingDB() // observe the database for value changes
    }

 func startObservingDB() {
   //it crashes on the line below
    dbRef.observe(.value, with: { (snapshot: FIRDataSnapshot) in

        //iterate over each user node child
        for user_child in snapshot.children {
             print(user_child)} 

          }, withCancel: { (Error: Any) in
         print(Error)
       })
   } // end of startObservingDB()
}//end of Claim class



class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

// Use Firebase library to configure APIs for the initial project with .plist file saved in Xcode
FIRApp.configure()


    /** 1. create a Firebase options object to hold the configuration data for the second Firebase Project */
    let secondaryOptions = FIROptions(googleAppID: "1:82424687545:ios:71df5d45218ad27",
                                      bundleID: "com.vivvdaplar.Brev",
                                      gcmSenderID: "8201647545",
                                      apiKey: "AIzaSyCNtyUf2T3UunH6-ci_WyvOqCl_RzXI",
                                      clientID: "8200687545-42vklp94reavi6li6bolhcraoofc6.apps.googleusercontent.com",
                                      trackingID: nil,
                                      androidClientID: nil,
                                      databaseURL: "https://brev-72e10.firebaseio.com",
                                      storageBucket: "com.vivvdaplar.Brev",
                                      deepLinkURLScheme: nil)

    // Configure the app
    FIRApp.configure(withName: "brevCustomer", options: secondaryOptions!) 
       return true
  }
} //end of AppDelegate
bibscy
  • 2,598
  • 4
  • 34
  • 82
  • You 'can't' do that, and probably shouldn't. The .plist file links a specific Firebase database to the app. Also, when you use *let dbRef = FIR...* it's defining the deRef var to be local to the function that contains it, and Xcode is indicating it's not used because it's not used within that function. – Jay Jul 02 '17 at 13:36
  • @Jay. Thanks for your answer. What would be the alternative? How could I read from/write to another database from within an IOS app in which I am already using the default Firebase SDK? I saw this answer and that's why I thought it should work https://stackoverflow.com/questions/37634767 – bibscy Jul 02 '17 at 13:38
  • I put 'can't' in quotes because it is possible, however, there's a lot of stuff to take into consideration before doing it. If you can detail your use case, we may be able to provide and answer or best practice. See the instructions here [Configure Multiple Projects](https://firebase.google.com/docs/configure/). – Jay Jul 02 '17 at 13:49
  • @Jay I have edited my question now, please review – bibscy Jul 02 '17 at 14:33
  • It appears there's a pretty tight relationship between workers and customers and with two apps, you've got a LOT of redundant code and overlapping data. Why not just put it in one app? When the user logs in, if they are a customer, access Firebase customer related data and if they are a worker, access the Firebase worker data. If you want visual separation keep them in two nodes like /app/worker_data and /app/customer_data. If you did that, setting up a Firebase rule to ensure users can't access the data in the other node would be a snap. – Jay Jul 02 '17 at 14:42
  • @Jay. If there's one database for both IOS apps, I assume that when user logs I have to make a `for in` loop in the whole database and determine if user.uid logged in is worker or customer. I guess this is the only possibility since all firebase apps under a firebase project share the same database for users named in firebase console as 'Authentication`. Now, both apps are in AppStore, I am a customer and by mistake I download worker's app and log in the worker's app. In this case I'd have to do for in loop in the whole database and then log out customer with alert "..." – bibscy Jul 02 '17 at 15:02
  • @Jay, is this how you picture the scenario? Whenever a user registers, write to /app/worker_data/uid or /app/customer_data.uid. As far as I know all users would be stored under a single `FIRAuth.auth()` object. If I were to store the data in two nodes /app/worker_data and /app/customer_data, I would have to make one `for in` loop both in /app/worker_data and /app/customer_data to check if `FIRAuth.auth()?.currentUser?.uid` is contained in any of those nodes and based on that keep the user logged in or log out with Alert. – bibscy Jul 02 '17 at 15:19
  • You don't need any kind of looping at all. See my answer! – Jay Jul 02 '17 at 15:21

1 Answers1

3

Responding the question and comments.

As you know, when a user registers with Firebase, a user account is created on the Firebase server and the user is provided a user id (uid).

A typical design pattern is to have a /users node in Firebase that stores other information about the user, such as a nickname, address or phone number.

We can leverage that /users node to also indicate what kind of user it is; Worker or Client, which would tie into the rest of the app and Firebase so they get to the correct data.

For example

users
  uid_0
    nickname: "John"
    user_type: "Worker"
  uid_1
    nickname: "Paul"
    user_type: "Client"
  uid_2
    nickname: "George"
    user_type: "Worker"
  uid_3
    nickname: "Ringo"
    user_type: "Worker"

As you can see, John, George and Ringo are all workers and Paul is a client.

When the user logs in, the Firebase signIn function will return the users auth data, which contains the uid.

    Auth.auth().signIn(withEmail: "paul@harddaysnight.com", password: "dog",
     completion: { (auth, error) in

        if error != nil {
            let err = error?.localizedDescription
            print(err!)
        } else {
            print(auth!.uid)
            //with the uid, we now lookup their user type from the
            //users node, which tells the app if they are a client
            //or worker
        }
    })

If the app data is divided like this

app
  client_data
     ...
  worker_data
     ...

A simple rule could be set up that verifies the users user_type is Worker for the worker_data node and Client for the client_data node. Here's a pseudo example that will allow a Client user to only access the data in the client_data node (conceptual)

rules 
  client_data
     $user_id
        ".read": "auth != null && root.child(users)
                                      .child($user_id)
                                      .child("user_type") == 'Client'"
Jay
  • 34,438
  • 18
  • 52
  • 81
  • when I add an app in console.firebase.google.com, it requires me enter in a textField the bundle identifier for the IOS app I want to connect to firebase app. I have two IOS apps with two different bundle identifier, meaning that one IOS app will contain the GoogleInfo.plist file with the bundle identifier from the other IOS app. How do I sort this out? – bibscy Jul 02 '17 at 19:49
  • @bibscy Using the above answer, you won't need two apps. One app will serve both workers and clients. That's a huge advantage in that you have one codebase to support, once set or variables and one database. Super easy to manage and maintain and also as you add features they could be rolled out in one app instead of having to update two different sets of code. – Jay Jul 03 '17 at 17:33
  • Thank you so much for your guidance – bibscy Jul 03 '17 at 17:47
  • I got stuck with another issue and I'd very much appreciate your help. https://stackoverflow.com/questions/45266392 – bibscy Jul 23 '17 at 21:19