UIimage init crash for old Xcode

We have found some recent crashes that only appear on iOS 18 iPad OS 18, these crashes only appear in apps packaged in August 2022 and earlier and affect about 200 users per day, the same method calls have not had the same crashes in any of the subsequent Xcode build, here's the code in question.

public class FeedComponentResource: NSObject {
    static func bundle() -> Bundle? {
        let path = (Bundle(for: FeedComponentResource.self).resourcePath! as NSString).appendingPathComponent("ResourceBundle.bundle")
        let bundle = Bundle(path: path)
        return bundle
    }

    public static func image(_ id: String) -> UIImage {
        var image = UIImage()
        if let bundle = self.bundle() {
            // crashed in this line
            image = UIImage(named: id, in: bundle, compatibleWith: nil)!
        }
        return image
    }

and here is the call stack

EXC_BREAKPOINT 0x000000010302b328
Crashed: com.apple.main-thread
0  NewsBreak                      0x60b328 closure #1 in FeedComponentHeader.authorIconView.getter + 3256176 (FeedComponentResource.swift:3256176)
1  NewsBreak                      0x6081b0 FeedComponentHeader.authorIconView.getter + 3243512
2  NewsBreak                      0x6086ac FeedComponentHeader.init(frame:) + 94 (FeedComponentHeader.swift:94)
3  NewsBreak                      0x609550 @objc FeedComponentHeader.init(frame:) + 3248536 (<compiler-generated>:3248536)
4  NewsBreak                      0x241c00 closure #1 in FeedNewsRedesignBaseCell.header.getter + 17 (FeedNewsRedesignBaseCell.swift:17)
5  NewsBreak                      0x241134 FeedNewsRedesignBaseCell.header.getter + 4332327220
6  NewsBreak                      0x2452a0 FeedNewsRedesignBaseCell.init(frame:) + 160 (FeedNewsRedesignBaseCell.swift:160)
7  NewsBreak                      0x245618 @objc FeedNewsRedesignBaseCell.init(frame:) + 4332344856 (<compiler-generated>:4332344856)
8  NewsBreak                      0x249350 FeedNewsRedesignBigCell.init(frame:) + 16 (FeedNewsRedesignBigCell.swift:16)
9  NewsBreak                      0x24a5b0 @objc FeedNewsRedesignBigCell.init(frame:) + 4332365232 (<compiler-generated>:4332365232)
10 UIKitCore                      0x82110 __88-[UICollectionView _dequeueReusableViewOfKind:withIdentifier:forIndexPath:viewCategory:]_block_invoke + 40
11 UIKitCore                      0x7ff30 +[UIView(Animation) performWithoutAnimation:] + 76
12 UIKitCore                      0x27a180 -[UICollectionView _dequeueReusableViewOfKind:withIdentifier:forIndexPath:viewCategory:] + 956
13 UIKitCore                      0x279d48 -[UICollectionView dequeueReusableCellWithReuseIdentifier:forIndexPath:] + 84
14 NewsBreak                      0x6f1e8 -[FeedViewController collectionView:cellForItemAtIndexPath:] + 1951 (FeedViewController.m:1951)
15 UIKitCore                      0x9f6340 __112-[UICollectionView _createPreparedCellForItemAtIndexPath:withLayoutAttributes:applyAttributes:isFocused:notify:]_block_invoke.394 + 52
16 UIKitCore                      0x7ff30 +[UIView(Animation) performWithoutAnimation:] + 76
17 UIKitCore                      0x2782d4 -[UICollectionView _createPreparedCellForItemAtIndexPath:withLayoutAttributes:applyAttributes:isFocused:notify:] + 1208
18 UIKitCore                      0x2779b0 -[UICollectionView _createVisibleViewsForSingleCategoryAttributes:limitCreation:fadeForBoundsChange:] + 524
19 UIKitCore                      0x3a2aa8 -[UICollectionView _createVisibleViewsForAttributes:fadeForBoundsChange:notifyLayoutForVisibleCellsPass:] + 300
20 UIKitCore                      0x1acf18 -[UICollectionView _updateVisibleCellsNow:] + 3092
21 UIKitCore                      0x3057c4 -[UICollectionView layoutSubviews] + 288
22 UIKitCore                      0xd688 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2424
23 QuartzCore                     0x78c28 CA::Layer::layout_if_needed(CA::Transaction*) + 496
24 UIKitCore                      0x50138 -[UIView(Hierarchy) layoutBelowIfNeeded] + 312
25 UIKitCore                      0xde5a4 -[UICollectionView _performBatchUpdates:completion:invalidationContext:tentativelyForReordering:animator:animationHandler:] + 288
26 NewsBreak                      0x6db5c -[FeedViewController updateCollection:updates:completion:] + 1791 (FeedViewController.m:1791)
27 NewsBreak                      0x112348 -[FeedProvider startUpdateCollection:] + 1067 (FeedProvider.m:1067)
28 libdispatch.dylib              0x2370 _dispatch_call_block_and_release + 32
29 libdispatch.dylib              0x40d0 _dispatch_client_callout + 20
30 libdispatch.dylib              0x129e0 _dispatch_main_queue_drain + 980
31 libdispatch.dylib              0x125fc _dispatch_main_queue_callback_4CF + 44
32 CoreFoundation                 0x56204 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 16
33 CoreFoundation                 0x53440 __CFRunLoopRun + 1996
34 CoreFoundation                 0x52830 CFRunLoopRunSpecific + 588
35 GraphicsServices               0x11c4 GSEventRunModal + 164
36 UIKitCore                      0x3d2eb0 -[UIApplication _run] + 816
37 UIKitCore                      0x4815b4 UIApplicationMain + 340
38 NewsBreak                      0xa6dc main + 17 (main.m:17)

Looking forward to the subsequent iOS version can fix this problem can reduce the impact on online users, thank you!

Still crashes if you do not force unwrapping? Was it working previously of iOS 18?

It seems like you are forcing an unwrap image = UIImage(named: id, in: bundle, compatibleWith: nil)! in case the name isn't there? What about using if let instead?

public static func image(_ id: String) -> UIImage {
            var image = UIImage()
            if let bundle = self.bundle() {
                // crashed in this line
                if let imageNamed = UIImage(named: id, in: bundle, compatibleWith: nil)
                {
                    return imageNamed
                }
                    
            }
            return image
        }

Issue, will return a blank image if the named does not exist.

I would recommend to make the return optional and check for nil and avoid creating a blank image

 public static func image(_ id: String) -> UIImage? {

Like:

 public static func image(_ id: String) -> UIImage? {
        
            if let bundle = self.bundle() {
           
                if let imageNamed = UIImage(named: id, in: bundle, compatibleWith: nil)
                {
                    return imageNamed
                }
                    
            }
            return nil
        }

Albert Pascual
  Worldwide Developer Relations.

However, the same code has no problem in the App by the Xcode version, and the image is saved locally, and the image passed in by the code calling this function exists. I think there should be no crash here under any force unwrapping, so the forced unwrapping should be safe here.

UIimage init crash for old Xcode
 
 
Q