Ionic4 - Problems with PDF since iOS 13 and latest xCode

I had an app that was working fine but needed to have a few things updated. Yesterday, I made the changes - which work in the emulator up until the point where the cordova plugin takes over. It also still works on Android. However, when I generate the app in xCode and push it out to testflight, it now crashes everytime I load a PDF. This worked days ago, before iOS 13 and before the latest version of xCode.

Anyone know why my code might stop working? I’m using a version of the PDF viewer from the PDF tutorial at Ionic Academy. And it WAS working for the last month.

HTML file - basically, I display a list of items from a JSON file. This part at least still works.

<ion-header>
  <ion-toolbar>
    <ion-buttons slot="start">
      <ion-back-button defaultHref="/"></ion-back-button>
    </ion-buttons>
    <ion-title>References</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content padding color="primary">
  <ion-searchbar placeholder="Search by Name" [(ngModel)]="searchTerm" (ionChange)="filterMe()" color="light"></ion-searchbar>
  <ion-list *ngIf="references" class="ionListREF" color="primary">
    <ion-item button *ngFor="let item of (references | async)" color="primary" class="{{getClass(item.type)}}" [detail]="false" (click)="doAction(item.pdf, item.name, item.type)">

      <ion-button *ngIf="item.type === 'Page'" color="dark" expand="full" fill="clear" class="theButtons">
        <span class="buttonTextColor">{{ item.name }}</span>
      </ion-button>
      <ion-button *ngIf="item.type === 'PDF'" color="dark" expand="full" fill="clear" class="theButtons">
        <span class="buttonTextColor">{{ item.name }}</span>
      </ion-button>
      <ion-label text-wrap *ngIf="item.type === 'S'">
        <h3 class="divTextColor">{{ item.name }}</h3>
      </ion-label>
      <ion-icon *ngIf="item.type === 'PDF'" name="arrow-dropright" slot="end" ></ion-icon>
      <ion-icon *ngIf="item.type === 'Page'" name="arrow-dropright" slot="end" ></ion-icon>
    </ion-item>
  </ion-list>

</ion-content>

TS file - I’m running DoAction when they click an item, which in turn calls openLocalPDF if the item is a PDF. Again, this WAS working before last Thursday and still works in Android.

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { MenuController, NavController } from '@ionic/angular';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { ReferenceService } from '../../services/reference.service';
import { Platform } from '@ionic/angular';
import { File } from '@ionic-native/File/ngx';
import { FileOpener } from '@ionic-native/file-opener/ngx';
import { DocumentViewer, DocumentViewerOptions } from '@ionic-native/document-viewer/ngx';
import { FileTransfer } from '@ionic-native/file-transfer/ngx';
import { GoogleAnalytics } from '@ionic-native/google-analytics/ngx';

@Component({
  selector: 'app-references',
  templateUrl: './references.page.html',
  styleUrls: ['./references.page.scss'],
})
export class ReferencesPage implements OnInit {
  analyticsPage = 'References';
  searchTerm = '';
  searchText = '';
  found = false;

  data: any;
  references: Observable<any[]>;
  results: Observable<any[]>;
  constructor(private activatedRoute: ActivatedRoute, private referenceService: ReferenceService, private router: Router,
              private platform: Platform, private file: File, private ft: FileTransfer, public navCtrl: NavController,
              private fileOpener: FileOpener, private document: DocumentViewer, private ga: GoogleAnalytics) { }

  ngOnInit() {
    console.log('references ngOnInit enter');
    this.analyticsStart(this.analyticsPage);
    this.analyticsTrack('Page', 'View');
    this.references = this.referenceService.getReferences();
    this.results = this.references;

  }

  filterMe() {
    console.log('searchterm', this.searchTerm);
    this.searchText = '';
    if (this.searchTerm != null) {
      this.searchText = this.searchTerm.toLowerCase();
    } else {
      this.searchText = '';
    }

    this.references = this.results.pipe(
        map((reports: any[]) => reports.filter(p => {
          this.found = false;
          if (p.name.toString().toLowerCase().indexOf(this.searchText) > -1) {this.found = true; }
          if (this.found) {return p; }
        }))
    );

    console.log('results - after', this.references);

  }

  getClass(someType: string) {
    if (someType === 'P') {
      return 'normalItem';
    } else {
      return 'divItem';
    }
  }

  doAction(theFileName: string, theName: string, theType: string) {
    if (theType === 'PDF') {
      console.log('open pdf', theFileName);
      this.openLocalPdf(theFileName, theName);
    }
    if (theType === 'Page') {
      // this.navCtrl.push('/' + theFileName + '/');
      this.navCtrl.navigateForward('/' + theFileName );
    }
  }
  // ------------------------------------------------------------------
  // Open PDF in Native
  // ------------------------------------------------------------------
  openLocalPdf(theFileName: string, theName: string) {
    const filePath = this.file.applicationDirectory + 'www/assets/pdf';
    this.analyticsTrack(theName, 'View');

    if (this.platform.is('android')) {
      const fakeName = Date.now();
      this.file.copyFile(filePath, theFileName, this.file.dataDirectory, `${fakeName}.pdf`).then(result => {
        this.fileOpener.open(result.nativeURL, 'application/pdf')
            .then(() => console.log('File is opened'))
            .catch(e => console.log('Error opening file', e));
      });
    } else {
      // Use Document viewer for iOS for a better UI
      const options: DocumentViewerOptions = {
        title: theName
      }
      this.document.viewDocument(filePath + '/' + theFileName, 'application/pdf', options);
    }
  }
  // ---------------------------------------------------------------
  // ---------------------------------------------------------------
  // GOOGLE ANALYTICS
  // ---------------------------------------------------------------
  // ---------------------------------------------------------------
  analyticsStart(value) {
    this.ga.startTrackerWithId('UA-142662811-2')
        .then(() => {
          console.log('Google analytics is ready now');
          this.ga.trackView(value + ' Screen');
          // Tracker is ready
          // You can now track pages or set additional information such as AppVersion or UserId
          this.analyticsTrack('Page', 'View');
        })
        .catch(e => console.log('Error starting GoogleAnalytics', e));
  }
  analyticsTrack(event, label) {
    this.ga.trackEvent(this.analyticsPage, event, label, 1);
  }
}

Any help would be greatly appreciated as I am unable to update the app on iOS until I can resolve this issue.

1 Like

It crashes only on devices with iOS 13. On devices with older versions of iOS, it still works.

I have the same reported issue caused by the document viewer.

I have FileOpen as an alternative, but it generates the sharing options. And I have some pages that cannot be shared

I ended up using the fileopen alternative as well. So far, it’s working for me, but I had to copy the files to the main app directory before opening them.