mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
perf(ios): UIImage memory leaks (#9783)
This commit is contained in:
committed by
Nathan Walker
parent
f37b0160ed
commit
988f372788
@@ -28,10 +28,16 @@ export abstract class ImageBase extends View implements ImageDefinition {
|
||||
this.style.tintColor = value;
|
||||
}
|
||||
|
||||
public disposeImageSource() {
|
||||
// override in subclass
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public _createImageSourceFromSrc(value: string | ImageSource | ImageAsset): void {
|
||||
this.disposeImageSource();
|
||||
|
||||
const originalValue = value;
|
||||
const sync = this.loadMode === 'sync';
|
||||
if (typeof value === 'string' || value instanceof String) {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { ImageBase, stretchProperty, imageSourceProperty, tintColorProperty, src
|
||||
import { ImageSource } from '../../image-source';
|
||||
import { Color } from '../../color';
|
||||
import { Trace } from '../../trace';
|
||||
import { layout } from '../../utils';
|
||||
import { layout, queueGC } from '../../utils';
|
||||
|
||||
export * from './image-common';
|
||||
|
||||
@@ -24,21 +24,28 @@ export class Image extends ImageBase {
|
||||
this._setNativeClipToBounds();
|
||||
}
|
||||
|
||||
public disposeNativeView(): void {
|
||||
super.disposeNativeView();
|
||||
public disposeImageSource() {
|
||||
if (this.nativeViewProtected?.image === this.imageSource?.ios) {
|
||||
this.nativeViewProtected.image = null;
|
||||
}
|
||||
|
||||
if (this.imageSource?.ios) {
|
||||
this.imageSource.ios = null;
|
||||
// causes crash currently:
|
||||
// release the native UIImage
|
||||
// CFRelease(this.imageSource.ios);
|
||||
}
|
||||
|
||||
this.imageSource = null;
|
||||
|
||||
queueGC();
|
||||
}
|
||||
|
||||
public disposeNativeView(): void {
|
||||
super.disposeNativeView();
|
||||
|
||||
if (this.nativeViewProtected?.image) {
|
||||
this.nativeViewProtected.image = null;
|
||||
}
|
||||
|
||||
this.disposeImageSource();
|
||||
}
|
||||
|
||||
private setTintColor(value: Color) {
|
||||
@@ -46,15 +53,23 @@ export class Image extends ImageBase {
|
||||
if (value && this.nativeViewProtected.image && !this._templateImageWasCreated) {
|
||||
this.nativeViewProtected.image = this.nativeViewProtected.image.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate);
|
||||
this._templateImageWasCreated = true;
|
||||
queueGC();
|
||||
} else if (!value && this.nativeViewProtected.image && this._templateImageWasCreated) {
|
||||
this._templateImageWasCreated = false;
|
||||
this.nativeViewProtected.image = this.nativeViewProtected.image.imageWithRenderingMode(UIImageRenderingMode.Automatic);
|
||||
queueGC();
|
||||
}
|
||||
this.nativeViewProtected.tintColor = value ? value.ios : null;
|
||||
}
|
||||
}
|
||||
|
||||
public _setNativeImage(nativeImage: UIImage) {
|
||||
if (this.nativeViewProtected?.image) {
|
||||
this.nativeViewProtected.image = null;
|
||||
|
||||
queueGC();
|
||||
}
|
||||
|
||||
if (this.nativeViewProtected) {
|
||||
this.nativeViewProtected.image = nativeImage;
|
||||
}
|
||||
@@ -169,6 +184,10 @@ export class Image extends ImageBase {
|
||||
}
|
||||
|
||||
[imageSourceProperty.setNative](value: ImageSource) {
|
||||
if (value !== this.imageSource) {
|
||||
this.disposeImageSource();
|
||||
}
|
||||
|
||||
this._setNativeImage(value ? value.ios : null);
|
||||
}
|
||||
|
||||
|
||||
5
packages/core/utils/index.d.ts
vendored
5
packages/core/utils/index.d.ts
vendored
@@ -187,6 +187,11 @@ export namespace ad {
|
||||
*/
|
||||
export function GC();
|
||||
|
||||
/**
|
||||
* An utility function that queues a garbage collection, subseqent calls will be throttled and only one gc will be executed.
|
||||
*/
|
||||
export function queueGC();
|
||||
|
||||
/**
|
||||
* Releases the reference to the wrapped native object
|
||||
* @param object The Java/Objective-C object to release.
|
||||
|
||||
@@ -3,6 +3,8 @@ import { dispatchToMainThread, isMainThread } from './mainthread-helper';
|
||||
import { sanitizeModuleName } from '../ui/builder/module-name-sanitizer';
|
||||
import * as layout from './layout-helper';
|
||||
|
||||
import { GC } from './index';
|
||||
|
||||
export { layout };
|
||||
export * from './mainthread-helper';
|
||||
export * from './macrotask-scheduler';
|
||||
@@ -129,3 +131,17 @@ export function mainThreadify(func: Function): (...args: any[]) => void {
|
||||
executeOnMainThread(() => func.apply(this, argsToPass));
|
||||
};
|
||||
}
|
||||
|
||||
let hasQueuedGC = false;
|
||||
export function queueGC() {
|
||||
if (hasQueuedGC) {
|
||||
return;
|
||||
}
|
||||
|
||||
hasQueuedGC = true;
|
||||
|
||||
setTimeout(() => {
|
||||
hasQueuedGC = false;
|
||||
GC();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user