0

I am using ionic with capacitor and angularfire. It works fine but does not work on ios. On ios I don't see any error - just the firebase call that never returns anything. Below is my package.json and other relevant info.

ionic.info:

ionic info    

Ionic:

   Ionic CLI                     : 6.18.1 (/usr/local/lib/node_modules/@ionic/cli)
   Ionic Framework               : @ionic/angular 5.9.1
   @angular-devkit/build-angular : 12.1.4
   @angular-devkit/schematics    : 12.1.4
   @angular/cli                  : 12.1.4
   @ionic/angular-toolkit        : 4.0.0

Capacitor:

   Capacitor CLI      : 3.3.2
   @capacitor/android : 3.3.2
   @capacitor/core    : 3.3.2
   @capacitor/ios     : 3.3.2

Cordova:

   Cordova CLI       : 10.0.0 (cordova-lib@10.1.0)
   Cordova Platforms : android broken, ios 5.1.1
   Cordova Plugins   : no whitelisted plugins (0 plugins total)

Utility:

   cordova-res (update available: 0.15.4) : 0.15.3
   native-run                             : 1.5.0

System:

   ios-deploy : 1.9.4
   ios-sim    : ios-sim/9.0.0 darwin-x64 node-v14.17.0
   NodeJS     : v14.17.0 (/usr/local/bin/node)
   npm        : 7.24.0
   OS         : macOS Monterey
   Xcode      : Xcode 13.1 Build version 13A1030d

Package.json:

  "dependencies": {
    "@angular/common": "~12.1.1",
    "@angular/core": "~12.1.1",
    "@angular/fire": "^7.2.0",
    "@angular/forms": "~12.1.1",
    "@angular/platform-browser": "~12.1.1",
    "@angular/platform-browser-dynamic": "~12.1.1",
    "@angular/router": "~12.1.1",
    "@capacitor/android": "^3.3.2",
    "@capacitor/app": "^1.0.6",
    "@capacitor/browser": "^1.0.6",
    "@capacitor/core": "3.3.2",
    "@capacitor/device": "^1.1.0",
    "@capacitor/haptics": "^1.1.3",
    "@capacitor/ios": "^3.3.2",
    "@capacitor/keyboard": "^1.1.3",
    "@capacitor/splash-screen": "^1.1.6",
    "@capacitor/status-bar": "^1.0.6",
    "@capacitor/storage": "^1.2.3",
    "@ionic-native/app-version": "^5.36.0",
    "@ionic-native/barcode-scanner": "^5.36.0",
    "@ionic-native/call-number": "^5.36.0",
    "@ionic-native/camera": "^5.36.0",
    "@ionic-native/camera-preview": "^5.36.0",
    "@ionic-native/contacts": "^5.36.0",
    "@ionic-native/email-composer": "^5.36.0",
    "@ionic-native/in-app-browser": "^5.36.0",
    "@ionic-native/in-app-purchase": "^5.36.0",
    "@ionic-native/in-app-purchase-2": "^5.36.0",
    "@ionic-native/social-sharing": "^5.36.0",
    "@ionic/angular": "^5.5.2",
    "@ngx-translate/core": "^11.0.1",
    "@ngx-translate/http-loader": "^4.0.0",
    "call-number": "^1.0.1",
    "cordova-plugin-app-version": "^0.1.12",
    "cordova-plugin-camera": "^6.0.0",
    "cordova-plugin-camera-preview": "^0.12.3",
    "cordova-plugin-contacts": "^3.0.1",
    "cordova-plugin-email-composer": "^0.10.0",
    "cordova-plugin-inappbrowser": "^5.0.0",
    "cordova-plugin-inapppurchase": "^1.2.0",
    "cordova-plugin-purchase": "^10.6.1",
    "cordova-plugin-x-socialsharing": "^6.0.3",
    "firebase": "^9.5.0",
    "forcejs": "^2.2.1",
    "phonegap-plugin-barcodescanner": "^8.1.0",
    "rxjs": "~6.6.0",
    "tslib": "^2.2.0",
    "xcode": "^3.0.1",
    "xml-js": "^1.6.11",
    "zone.js": "~0.11.4"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~12.1.1",
    "@angular-eslint/builder": "~12.0.0",
    "@angular-eslint/eslint-plugin": "~12.0.0",
    "@angular-eslint/eslint-plugin-template": "~12.0.0",
    "@angular-eslint/template-parser": "~12.0.0",
    "@angular/cli": "~12.1.1",
    "@angular/compiler": "~12.1.1",
    "@angular/compiler-cli": "~12.1.1",
    "@angular/language-service": "~12.0.1",
    "@capacitor/cli": "3.3.2",
    "@ionic/angular-toolkit": "^4.0.0",
    "@types/jasmine": "~3.6.0",
    "@types/jasminewd2": "~2.0.3",
    "@types/node": "^12.11.1",
    "@typescript-eslint/eslint-plugin": "4.16.1",
    "@typescript-eslint/parser": "4.16.1",
    "es6-promise-plugin": "^4.2.2",
    "eslint": "^7.6.0",
    "eslint-plugin-import": "2.22.1",
    "eslint-plugin-jsdoc": "30.7.6",
    "eslint-plugin-prefer-arrow": "1.2.2",
    "jasmine-core": "~3.8.0",
    "jasmine-spec-reporter": "~5.0.0",
    "karma": "~6.3.2",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage": "~2.0.3",
    "karma-coverage-istanbul-reporter": "~3.0.2",
    "karma-jasmine": "~4.0.0",
    "karma-jasmine-html-reporter": "^1.5.0",
    "protractor": "~7.0.0",
    "ts-node": "~8.3.0",
    "typescript": "~4.2.4"
  }

app.module.ts:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';

import { AngularFireModule } from '@angular/fire/compat';
import { AngularFireDatabaseModule } from '@angular/fire/compat/database';

import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { FormsModule } from '@angular/forms';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent,
  ],
  entryComponents: [
  ],
  imports: [
    AngularFireModule.initializeApp(firebaseConfig),
    AngularFireDatabaseModule,
    BrowserModule,
    HttpClientModule, 
    IonicModule.forRoot(), 
    AppRoutingModule,
    FormsModule,
  ],
  providers: [
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

The code that never executes and no error in catch block is below. Same works just fine on android:

 const resp:any = await this.dataSvc.getSeedConfig()
 console.log("seed config is::" + JSON.stringify(resp))

So the above code does not go to the catch block and does not print the seed config on ios. Works fine on android.

Also on ios it works using live reload using

ionic capacitor run ios -l --external

so if i run it using xcode then it does not work. not sure what is blocking in that specific case

Moblize IT
  • 1,140
  • 2
  • 18
  • 44

3 Answers3

1

Already answered this here https://stackoverflow.com/a/70594992/5701521 but could be useful to answer it here as well.

Been struggling a lot with this issue too but I managed to fix it. For those who need help here's my code.

You can delete all Firebase related imports from app.module.ts since this solution only uses Firebase. The packages rxfire and @angular/fire can be removed from your package.json. The only dependency I have is "firebase": "^9.6.1". I used observables for the getObject and list functions since that's what I'm used to and I didn't want to rewrite my original code.

import { Injectable } from '@angular/core';
import { Capacitor } from '@capacitor/core';
import { environment } from '@environment';
import { initializeApp } from 'firebase/app';
import { Auth, getAuth, indexedDBLocalPersistence, initializeAuth, signInWithCustomToken } from 'firebase/auth';
import { Database, getDatabase, onValue, orderByChild, query, ref } from 'firebase/database';
import { Observable, Observer, from } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class FirebaseService {
  private readonly database: Database;
  private readonly auth: Auth;

  constructor() {
    const firebaseApp = initializeApp(environment.firebase);

    if (Capacitor.isNativePlatform()) {
      initializeAuth(firebaseApp, {
        persistence: indexedDBLocalPersistence
      });
    }

    this.database = getDatabase(firebaseApp);
    this.auth = getAuth(firebaseApp);
  }

  connectFirebase(firebaseToken) {
    return from(signInWithCustomToken(this.auth, firebaseToken));
  }

  disconnectFirebase() {
    return from(this.auth.signOut());
  }

  getObject<T>(path: string): Observable<T> {
    return new Observable((observer: Observer<T>) => {
      const dbRef = ref(this.database, path);
      const listener = onValue(dbRef, snapshot => {
        const data = snapshot.val();
        observer.next(data);
      });

      return {
        unsubscribe() {
          listener();
        }
      };
    });
  }

  public list<T>(path: string, orderChildBy?: string): Observable<Array<T>> {
    return new Observable<Array<T>>((observer: Observer<Array<T>>) => {
      const dbRef = ref(this.database, path);
      const dbReference = !orderChildBy ? dbRef : query(dbRef, orderByChild(orderChildBy));

      const listener = onValue(dbReference, snapshot => {
        const data = Object.values<T>(snapshot.val() || {});
        console.log(path, data);
        observer.next(data);
      });

      return {
        unsubscribe() {
          listener();
        }
      };
    });
  }
}

For those who can't see the error message thrown by firebase try the following command in your Safari console to see the error.

window.location.reload()
SeppeDev
  • 2,252
  • 2
  • 13
  • 26
0

Try to downgrade your angularfire to v7.0 it might work with firebase v9.

0

in my case i folow this link: https://github.com/angular/angularfire/issues/3087#issuecomment-990599459

I was also having this issue when building for an iOS emulator and actual iOS device, but adding this to the app.component.ts worked for me.

import { Component } from '@angular/core';
import { Capacitor } from '@capacitor/core';
import { initializeApp } from 'firebase/app';
import { indexedDBLocalPersistence, initializeAuth } from 'firebase/auth';
import { environment } from 'src/environments/environment';

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss'],
})
export class AppComponent {
  constructor() {
    const app = initializeApp(environment.firebase);
    if (Capacitor.isNativePlatform) {
      initializeAuth(app, {
        persistence: indexedDBLocalPersistence
      });
    }
  }
}

This is where I found the fix and a sample code