Solution to Crash when upgrading IOS 17 version in ReactNative
-
- Crash solution when upgrading IOS 17 version in ReactNative
-
-
- 1. Problem description
- 2. Cause analysis
- 3. Solution decision-making
-
- 3.1 Set width and height to non-zero values
- 3.2 Use the new UIGraphicsImageRenderer to replace the old version of UIGraphicsBeginImageContext
- 4. Third-party libraries that may use this API
-
- 4.1 react-native-fast-image
- 4.2 react-native-linear-gradient
- 4.3 There are also the following third-party libraries that use `UIGraphicsBeginImageContextWithOptions`:
- 5. Reference address
-
1. Problem description
When using screenshots related to business, UIGraphicsBeginImageContextWithOptions
& amp; & amp; UIGraphicsEndImageContext
will report Assert.
The error message will be as follows:
- UIGraphicsBeginImageContext() failed to allocate CGBitampContext: size={382, 0}, scale=3.000000, bitmapInfo=0x2002. Use UIGraphicsImageRenderer to avoid this assert.
Or it would be like this
- *** Assertion failure in void _UIGraphicsBeginImageContextWithOptions(CGSize, BOOL, CGFloat, BOOL)(), UIGraphics.m:410
2. Cause analysis
After checking the API, I found that UIGraphicsBeginImageContext
has been deprecated on iOS 17. Click here to see the official documentation https://developer.apple.com/documentation /uikit/1623922-uigraphicsbeginimagecontext
Can clearly see the deprecation for the following versions
- iOS 2.0–17.0 Deprecated
- iPadOS 2.0–17.0 Deprecated
- Mac Catalyst 13.1–17.0 Deprecated
- tvOS 9.0–17.0 Deprecated
- watchOS 2.0–10.0 Deprecated
- visionOS 1.0–1.0 Deprecated
3. Solution decision-making
3.1 Set width and height to non-zero values
When we ensure that the width and height of the api are not zero, it can be used normally. There are many places that need to be changed. It may be necessary to check every place in the business that is set to zero attributes.
3.2 Use the new UIGraphicsImageRenderer to replace the old version of UIGraphicsBeginImageContext
The changes are relatively small. You only need to change the native content in the third-party library. There is no need to verify every element involved in the business. You only need to verify that some pages are displayed normally.
4. Third-party libraries that may use this API
4.1 react-native-fast-image
Solution: react-native-fast-image official solution
Modify the node_modules file path: ios/FastImage/FFFastImageView.m
- (UIImage*) makeImage: (UIImage*)image withTint: (UIColor*)color {<!-- --> UIImage* newImage = [image imageWithRenderingMode: UIImageRenderingModeAlwaysTemplate]; UIGraphicsImageRendererFormat *format = [UIGraphicsImageRendererFormat defaultFormat]; UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:image.size format:format]; UIImage *resultImage = [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) {<!-- --> CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height); [color set]; [newImage drawInRect:rect]; }]; return resultImage; }
4.2 react-native-linear-gradient
Official solution: react-native-linear-gradient official solution
According to the official solution, a new version package has been provided in the npm warehouse. At this time, we can update the source code or directly update the version:
-
Download the latest version
Download the latest version address: https://github.com/react-native-linear-gradient/react-native-linear-gradient/releases/tag/v2.8.3
You can also go directly to the npm repository. -
Update source code directly
If you want to update the source code, update the display function in the file path/node_modules/react-native-linear-gradient/ios/BVLinearGradientLayer.m.
- (void)display {<!-- --> [super display]; // short circuit when height or width are 0. Fixes CGContext errors throwing if (self.bounds.size.height == 0 || self.bounds.size.width == 0) {<!-- --> return; } BOOL hasAlpha = NO; for (NSInteger i = 0; i < self.colors.count; i + + ) {<!-- --> hasAlpha = hasAlpha || CGColorGetAlpha(self.colors[i].CGColor) < 1.0; } if (@available(iOS 10.0, *)) {<!-- --> UIGraphicsImageRendererFormat *format; if (@available(iOS 11.0, *)) {<!-- --> format = [UIGraphicsImageRendererFormat preferredFormat]; } else {<!-- --> format = [UIGraphicsImageRendererFormat defaultFormat]; } format.opaque = !hasAlpha; UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:self.bounds.size format:format]; UIImage *image = [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull ref) {<!-- --> [self drawInContext:ref.CGContext]; }]; self.contents = (__bridge id _Nullable)(image.CGImage); self.contentsScale = image.scale; } else {<!-- --> UIGraphicsBeginImageContextWithOptions(self.bounds.size, !hasAlpha, 0.0); CGContextRef ref = UIGraphicsGetCurrentContext(); [self drawInContext:ref]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); self.contents = (__bridge id _Nullable)(image.CGImage); self.contentsScale = image.scale; UIGraphicsEndImageContext(); } }
The crash in my project is a problem with this library. When the gradient text has content, the display is normal, but when the text content does not exist, a crash occurs, which is very strange.
4.3 There are also the following third-party libraries that use UIGraphicsBeginImageContextWithOptions
:
- React native itself draws borders
- react-native itself image processing /node_modules/react-native/Libraries/Image/RCTImageUtils.m
- react-native-camera
- react-native-view-shot
- The react-native-svg file contains the address: node_modules/react-native-svg/apple/RNSVGRenderable.mm
- TZImagePickerController in react-native-syan-image-picker
Other third-party libraries are not listed. You can search for UIGraphicsBeginImageContextWithOptions
in Xcode to check whether it is used and verify whether the display is normal. If there is a problem with the display, you can go to the official Github corresponding to the third-party library to find a solution or replace it yourself.
5. Reference address
Apple official question: https://developer.apple.com/forums/thread/733326
Apple official question: https://developer.apple.com/forums/thread/731385
github issue: https://github.com/react-native-linear-gradient/react-native-linear-gradient/issues/637
github: https://github.com/ibireme/YYText/issues/984
github:https://github.com/muntius/react-native-fast-image/commit/fc2b8acd97f07989e312f5cbd61d2e541fda3611
github:https://github.com/DylanVann/react-native-fast-image/issues/1002