failure is not a function. (In 'failure(status)', 'failure' is undefined)
3rror404 opened this issue · 2 comments
Your Environment
- Plugin version: 1.8.0
- Platform: iOS
- OS version: 10.3.2
- Device manufacturer / model: iPhone 6
- Nativescript version (
tns info
):
┌──────────────────┬─────────────────┬────────────────┬──────────────────┐
│ Component │ Current version │ Latest version │ Information │
│ nativescript │ 3.4.2 │ 3.4.3 │ Update available │
│ tns-core-modules │ 3.4.1 │ 3.4.1 │ Up to date │
│ tns-android │ 3.4.1 │ 3.4.1 │ Up to date │
│ tns-ios │ 3.4.1 │ 3.4.1 │ Up to date │
└──────────────────┴─────────────────┴────────────────┴──────────────────┘
I've had few crashes reported on iOS since updating my app. All seem to happen as soon as the app opens - this is when the plugin is configured.
I managed to briefly get hold of one of the devices that is crashing and it looks like it's something to do with the background-fetch plugin.
This is the error displayed in XCode's console:
JavaScript stack trace:
1 @file:///app/tns_modules/nativescript-background-fetch/background-fetch.js:16:24
2 UIApplicationMain@[native code]
3 start@file:///app/tns_modules/tns-core-modules/application/application.js:258:26
4 anonymous@file:///app/app.js:37:18
5 evaluate@[native code]
6 moduleEvaluation@[native code]
7 @[native code]
8 promiseReactionJob@[native code]
JavaScript error:
file:///app/tns_modules/nativescript-background-fetch/background-fetch.js:16:24: JS ERROR TypeError: failure is not a function. (In 'failure(status)', 'failure' is undefined)
I initialise background fetch in the same way as your demo app:
app.ts
if (application.ios) {
class MyDelegate extends UIResponder implements UIApplicationDelegate {
public static ObjCProtocols = [UIApplicationDelegate];
public applicationPerformFetchWithCompletionHandler(application: UIApplication, completionHandler:any) {
BackgroundFetch.performFetchWithCompletionHandler(application, completionHandler);
}
}
application.ios.delegate = MyDelegate;
}
view model
BackgroundFetch.status((status) => {
//console.log('- BackgroundFetch status: ', status);
});
// Listen to iOS-only BackgroundFetch events.
BackgroundFetch.configure({ stopOnTerminate: false }, () => {
//console.log('[event] BackgroundFetch');
BackgroundFetch.finish(UIBackgroundFetchResult.NewData);
});
Strangely this does not happen on every device. I've never experienced it myself but for those that do, it happens every single time they open the app. I've had reports on iOS 10.x and 11.x and devices ranging from iPhone 6 to iPhone X.
Any ideas?
Figured out why this is happening. If "Background App Refresh" is disabled in iOS settings the app will crash. The same happens in your demo app.
I guess the view model code should be something like this:
BackgroundFetch.status((status) => {
console.log('- BackgroundFetch status: ', status);
if(status == 2) {
// Listen to iOS-only BackgroundFetch events.
BackgroundFetch.configure({ stopOnTerminate: false }, () => {
//console.log('[event] BackgroundFetch');
BackgroundFetch.finish(UIBackgroundFetchResult.NewData);
});
}
});
After re-reading the documentation you state:
Actually implementing background-fetch in your application code is optional -- background-geolocation uses it automatically under-the-hood for its own purposes
I don't (knowingly) use background fetch in my app so I'm able to simply remove the above block from my view model entirely?
Is the plugin able to function correctly if background fetch is not available?
The plugin is able to function without background-fetch yes. BackgroundGeolocation
uses fetch events internally for a number of things, including evaluating schedules (if you're using the scheduler). The plugin will also sample the motion API during a fetch event to assist with triggering tracking.
It looks like you could solve your issue simply by providing a failureFn
to BackgroundFetch#configure
The #configure
method should be initializing failure
like so:
public static configure(config:Object, callback:Function, failure?:Function) {
failure = failure || emptyFn
.
.
.
}
Just as the #start
method does.
Simply provide a failureFn
to #configure
and all your problems are solved.