Crash triggered by custom font action

In iOS14 Beta, A crash will triggered when we use keyboard to input text. After checking our code , we found that it's related with custom font action.

In our APP, we allow users to select different font according to their reading habit.

We want to know:
  1. Will this crash be fixed in release version?

  2. Is there any other suggested ways to set custom fonts?

custom font code:
Code Block Objc
+ (void)load
{
  Method original = class_getClassMethod(self, NSSelectorFromString(@"systemFontOfSize:"));
   Method swizzled = class_getClassMethod(self, @selector(xxxx_systemFontOfSize:));
   method_exchangeImplementations(original, swizzled);
}
+ (UIFont *)xxxx_systemFontOfSize:(CGFloat)fontSize
{
  return [UIFont fontWithName:@"FZYaSongS-R-GB" size:fontSize];
}

The crash stack is as follow:
Code Block
2020-06-24 11:57:03.781098+0800 XXXXX[83196:2361602] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSCache setObject:forKey:cost:]: attempt to insert nil value (key: 0)'
* First throw call stack:
(
0 CoreFoundation 0x00007fff20434f16 exceptionPreprocess + 242
1 libobjc.A.dylib 0x00007fff2017454e objc_exception_throw + 48
2 CoreFoundation 0x00007fff20460566 -[NSCache removeObjectForKey:] + 0
3 UIKitCore 0x00007fff23eb2694 +[UISegmentedControl _fontForTraitCollection:size:selected:] + 339
4 UIKitCore 0x00007fff23ea0559 -[UISegment _attributedTextForState:selected:forceSelectedAppearance:] + 502
5 UIKitCore 0x00007fff23ea0229 -[UISegment _updateTextColors] + 107
6 UIKitCore 0x00007fff23ea3132 -[UISegment setObjectValue:] + 2061
7 UIKitCore 0x00007fff23e9c0cf -[UISegment initWithInfo:size:barStyle:tintColor:appearanceStorage:position:autosizeText:adjustsForContentSizeCategory:] + 412
8 UIKitCore 0x00007fff23eb29c7 -[UISegmentedControl _createSegmentAtIndex:position:withInfo:] + 178
9 UIKitCore 0x00007fff23eb2a3a -[UISegmentedControl _createAndAddSegmentAtIndex:position:withInfo:] + 36
10 UIKitCore 0x00007fff23eb2e0a 55-[UISegmentedControl _insertSegment:withInfo:animated:]_block_invoke + 66
11 UIKitCore 0x00007fff24a677d1 +[UIView(Animation) performWithoutAnimation:] + 84
12 UIKitCore 0x00007fff23eb2c31 -[UISegmentedControl _insertSegment:withInfo:animated:] + 376
13 TextInputUI 0x00007fff35673eb2 -[TUICandidateSortControl setTitles:] + 433
14 TextInputUI 0x00007fff3564d57f -[TUICandidateView updateSortControlTitlesIfNeeded] + 215
15 TextInputUI 0x00007fff3564d417 -[TUICandidateView setCandidateResultSet:] + 100
16 UIKitCore 0x00007fff2416bfae -[UIKeyboardCandidateController setCandidateResultSet:] + 515
17 UIKitCore 0x00007fff2416c3ff -[UIKeyboardCandidateController setCandidates:type:inlineText:inlineRect:maxX:layout:] + 117
18 UIKitCore 0x00007fff2432824d -[UIKeyboardImpl updateTextCandidateView] + 3335
19 UIKitCore 0x00007fff2432514c -[UIKeyboardImpl setCandidates:] + 396
20 UIKitCore 0x00007fff24323e28 -[UIKeyboardImpl updateCandidateDisplayAsyncWithCandidateSet:] + 1193
21 UIKitCore 0x00007fff2431533d -[UIKeyboardImpl inputManagerDidGenerateCandidatesForRequest:resultSet:] + 697
22 UIKitCore 0x00007fff24314d5b __78-[UIKeyboardImpl generateCandidatesAsynchronouslyWithRange:selectedCandidate:]_block_invoke_3 + 94
....
)

  1. Since you're swizzling, I'd say "no". :)

  2. UIAppearance provides this functionality: https://developer.apple.com/documentation/uikit/uiappearance. You will have to configure appearance for all relevant controls, though.

Hi,

Swizzling is one of the most straightforward ways to replace fonts in the whole application seamlessly. Is there a chance Apple will provide an API for replacing system fonts?
same problem..
On Xcode 12.0 beta 2 (12A6163b) it seems that initializing a segmented control with an arbitrary string once before swizzling the UIFont selectors fixes the crash.

Code Block
private var isAppFontSetUp = false
func setUpAppFont() {
guard !isAppFontSetUp else {
return
}
+
+ let _ = UISegmentedControl(items: ["foo"])
swizzle()
}


However, I am unsure if this fixes the crash for good since the root cause seems to lie in a cache (which might get purged again at some point).
It is fixed in iOS 14 beta 3, right?
I see crashes only in beta 1 and 2
Crash triggered by custom font action
 
 
Q