diff --git a/packages/core/application/index.android.ts b/packages/core/application/index.android.ts
index 5184e2220..cd6617697 100644
--- a/packages/core/application/index.android.ts
+++ b/packages/core/application/index.android.ts
@@ -29,6 +29,10 @@ const ActivityBackPressed = 'activityBackPressed';
const ActivityNewIntent = 'activityNewIntent';
const ActivityRequestPermissions = 'activityRequestPermissions';
+export function setMaxRefreshRate(options?: { min?: number; max?: number; preferred?: number }): void {
+ // ignore on android, ios only
+}
+
export class AndroidApplication extends Observable implements AndroidApplicationDefinition {
public static activityCreatedEvent = ActivityCreated;
public static activityDestroyedEvent = ActivityDestroyed;
diff --git a/packages/core/application/index.d.ts b/packages/core/application/index.d.ts
index 37c63cbba..066b0460e 100644
--- a/packages/core/application/index.d.ts
+++ b/packages/core/application/index.d.ts
@@ -76,6 +76,19 @@ export function setAutoSystemAppearanceChanged(value: boolean): void;
*/
export function systemAppearanceChanged(rootView: View, newSystemAppearance: 'dark' | 'light'): void;
+/**
+ * iOS Only
+ * Dynamically change the preferred frame rate
+ * For devices (iOS 15+) which support min/max/preferred frame rate you can specify ranges
+ * For devices (iOS < 15), you can specify the max frame rate
+ * see: https://developer.apple.com/documentation/quartzcore/optimizing_promotion_refresh_rates_for_iphone_13_pro_and_ipad_pro
+ * To use, ensure your Info.plist has:
+ * CADisableMinimumFrameDurationOnPhone
+ *
+ * @param options { min?: number; max?: number; preferred?: number }
+ */
+export function setMaxRefreshRate(options?: { min?: number; max?: number; preferred?: number }): void;
+
/**
* Event data containing information for the application events.
*/
diff --git a/packages/core/application/index.ios.ts b/packages/core/application/index.ios.ts
index d06766c3a..1022a004e 100644
--- a/packages/core/application/index.ios.ts
+++ b/packages/core/application/index.ios.ts
@@ -88,6 +88,44 @@ class CADisplayLinkTarget extends NSObject {
};
}
+export function setMaxRefreshRate(options?: { min?: number; max?: number; preferred?: number }) {
+ const adjustRefreshRate = function () {
+ if (displayedLink) {
+ const minFrameRateDisabled = NSBundle.mainBundle.objectForInfoDictionaryKey('CADisableMinimumFrameDurationOnPhone');
+ if (minFrameRateDisabled) {
+ let max = 120;
+ const deviceMaxFrames = UIScreen.mainScreen?.maximumFramesPerSecond;
+ if (options?.max) {
+ if (deviceMaxFrames) {
+ // iOS 10.3
+ max = options.max <= deviceMaxFrames ? options.max : deviceMaxFrames;
+ } else if (displayedLink.preferredFramesPerSecond) {
+ // iOS 10.0
+ max = options.max <= displayedLink.preferredFramesPerSecond ? options.max : displayedLink.preferredFramesPerSecond;
+ }
+ }
+
+ if (iOSNativeHelper.MajorVersion >= 15) {
+ const min = options?.min || max / 2;
+ const preferred = options?.preferred || max;
+ displayedLink.preferredFrameRateRange = CAFrameRateRangeMake(min, max, preferred);
+ } else {
+ displayedLink.preferredFramesPerSecond = max;
+ }
+ }
+ }
+ };
+ if (!displayedOnce) {
+ displayedLinkTarget = CADisplayLinkTarget.new();
+ displayedLink = CADisplayLink.displayLinkWithTargetSelector(displayedLinkTarget, 'onDisplayed');
+ adjustRefreshRate();
+ displayedLink.addToRunLoopForMode(NSRunLoop.mainRunLoop, NSDefaultRunLoopMode);
+ displayedLink.addToRunLoopForMode(NSRunLoop.mainRunLoop, UITrackingRunLoopMode);
+ } else {
+ adjustRefreshRate();
+ }
+}
+
/* tslint:disable */
export class iOSApplication implements iOSApplicationDefinition {
/* tslint:enable */
@@ -179,12 +217,7 @@ export class iOSApplication implements iOSApplicationDefinition {
@profile
private didFinishLaunchingWithOptions(notification: NSNotification) {
- if (!displayedOnce) {
- displayedLinkTarget = CADisplayLinkTarget.new();
- displayedLink = CADisplayLink.displayLinkWithTargetSelector(displayedLinkTarget, 'onDisplayed');
- displayedLink.addToRunLoopForMode(NSRunLoop.mainRunLoop, NSDefaultRunLoopMode);
- displayedLink.addToRunLoopForMode(NSRunLoop.mainRunLoop, UITrackingRunLoopMode);
- }
+ setMaxRefreshRate();
this._window = UIWindow.alloc().initWithFrame(UIScreen.mainScreen.bounds);
// TODO: Expose Window module so that it can we styled from XML & CSS
diff --git a/packages/core/index.d.ts b/packages/core/index.d.ts
index 212b44862..4d3b0a309 100644
--- a/packages/core/index.d.ts
+++ b/packages/core/index.d.ts
@@ -8,7 +8,7 @@
export type { NativeScriptConfig } from './config';
export { iOSApplication, AndroidApplication } from './application';
export type { ApplicationEventData, LaunchEventData, OrientationChangedEventData, UnhandledErrorEventData, DiscardedErrorEventData, CssChangedEventData, LoadAppCSSEventData, AndroidActivityEventData, AndroidActivityBundleEventData, AndroidActivityRequestPermissionsEventData, AndroidActivityResultEventData, AndroidActivityNewIntentEventData, AndroidActivityBackPressedEventData, SystemAppearanceChangedEventData } from './application';
-import { AndroidApplication, iOSApplication, systemAppearanceChanged, getMainEntry, getRootView, _resetRootView, getResources, setResources, setCssFileName, getCssFileName, loadAppCss, addCss, on, off, notify, hasListeners, run, orientation, getNativeApplication, hasLaunched, systemAppearance, setAutoSystemAppearanceChanged } from './application';
+import { AndroidApplication, iOSApplication, systemAppearanceChanged, getMainEntry, getRootView, _resetRootView, getResources, setResources, setCssFileName, getCssFileName, loadAppCss, addCss, on, off, notify, hasListeners, run, orientation, getNativeApplication, hasLaunched, systemAppearance, setAutoSystemAppearanceChanged, setMaxRefreshRate } from './application';
export declare const Application: {
launchEvent: string;
displayedEvent: string;
@@ -22,6 +22,7 @@ export declare const Application: {
systemAppearanceChangedEvent: string;
fontScaleChangedEvent: string;
systemAppearanceChanged: typeof systemAppearanceChanged;
+ setMaxRefreshRate: typeof setMaxRefreshRate;
getMainEntry: typeof getMainEntry;
getRootView: typeof getRootView;
resetRootView: typeof _resetRootView;
diff --git a/packages/core/index.ts b/packages/core/index.ts
index c84bb8296..ac43c40c3 100644
--- a/packages/core/index.ts
+++ b/packages/core/index.ts
@@ -5,7 +5,7 @@ import './globals';
export { iOSApplication, AndroidApplication } from './application';
export type { ApplicationEventData, LaunchEventData, OrientationChangedEventData, UnhandledErrorEventData, DiscardedErrorEventData, CssChangedEventData, LoadAppCSSEventData, AndroidActivityEventData, AndroidActivityBundleEventData, AndroidActivityRequestPermissionsEventData, AndroidActivityResultEventData, AndroidActivityNewIntentEventData, AndroidActivityBackPressedEventData, SystemAppearanceChangedEventData } from './application';
-import { fontScaleChangedEvent, launchEvent, displayedEvent, uncaughtErrorEvent, discardedErrorEvent, suspendEvent, resumeEvent, exitEvent, lowMemoryEvent, orientationChangedEvent, systemAppearanceChanged, systemAppearanceChangedEvent, getMainEntry, getRootView, _resetRootView, getResources, setResources, setCssFileName, getCssFileName, loadAppCss, addCss, on, off, notify, hasListeners, run, orientation, getNativeApplication, hasLaunched, android as appAndroid, ios as iosApp, systemAppearance, setAutoSystemAppearanceChanged, ensureNativeApplication } from './application';
+import { fontScaleChangedEvent, launchEvent, displayedEvent, uncaughtErrorEvent, discardedErrorEvent, suspendEvent, resumeEvent, exitEvent, lowMemoryEvent, orientationChangedEvent, systemAppearanceChanged, systemAppearanceChangedEvent, getMainEntry, getRootView, _resetRootView, getResources, setResources, setCssFileName, getCssFileName, loadAppCss, addCss, on, off, notify, hasListeners, run, orientation, getNativeApplication, hasLaunched, android as appAndroid, ios as iosApp, systemAppearance, setAutoSystemAppearanceChanged, ensureNativeApplication, setMaxRefreshRate } from './application';
export const Application = {
launchEvent,
displayedEvent,
@@ -19,6 +19,7 @@ export const Application = {
systemAppearanceChangedEvent,
systemAppearanceChanged,
fontScaleChangedEvent,
+ setMaxRefreshRate,
getMainEntry,
getRootView,