"UITextInputMode" doesn't work on IOS13.1

Hi.

I am using "UITextInputMode" to fix the language mode.

But "UITextInputMode" doesn't work on IOS13.1.

"UITextInputMode" works until "IOS13.0".

Please tell me the workaround.

Is this an OS-dependent bug?


    override var textInputMode: UITextInputMode? {
        if toriTapp {
            if let language = getKeyboardLanguage() {
                toriTapp = false


                for tim in UITextInputMode.activeInputModes {
                    if tim.primaryLanguage!.contains(language) {
                        return tim
                    }
                }
            }
            return super.textInputMode
        }
        return super.textInputMode
    }


    private func getKeyboardLanguage() -> String? {
        return "en"
    }

Replies

"UITextInputMode" doesn't work on IOS13.1.


What do you get ? Error message ? Wrong result ?

What did you expect ?


Have you checked

UITextInputMode.activeInputModes

is not empty ?

Thank you for your comment.


>"UITextInputMode" doesn't work on IOS13.1.

>What did you expect ?

I expect fixed language mode.

Is there a way to fix the mode on IOS13.1?


It does not raise any error messages.

Primary language is available for "en-US".

And "return tim" appears to be working properly.

But, it will not be in "en-US" mode.

Could you add some prints to understand what happens:


    override var textInputMode: UITextInputMode? {
        if toriTapp {
            if let language = getKeyboardLanguage() {
                toriTapp = false
                print("language", language)

                for tim in UITextInputMode.activeInputModes {
                    if tim.primaryLanguage!.contains(language) {
                        print("tim", tim)
                        return tim
                    }
                }
            }
            return super.textInputMode
        }
        return super.textInputMode
    }


Please tell what you get on log.

- for iOS 13.1

- for iOS 13.0

thank you for your comment


It is the result.


IOS13: language en

tim <UIKeyboardInputMode: 0x6000011d10e0>


IOS13.1:language en

tim <UIKeyboardInputMode: 0x6000011b5720>

We need more detail in line 9 print.


                        print("tim", tim, tim.primaryLanguage)


Thanks to retest.

thank you for your comment.


It is the result.


Although 'primaryLanguage' is recognized by 'en-US',

But it does not appear to be reflected on the keyboard.



IOS13:language en

tim <UIKeyboardInputMode: 0x6000023b45a0> Optional("en-US")


IOS13.1:language en

     tim <UIKeyboardInputMode: 0x6000039ddfe0> Optional("en-US")

Could you explain what does not work ?


>"UITextInputMode" doesn't work on IOS13.1.

>What did you expect ?

I expect fixed language mode.

Is there a way to fix the mode on IOS13.1?


It does not raise any error messages.

Primary language is available for "en-US".

And "return tim" appears to be working properly.

But, it will not be in "en-US" mode.


What do you mean I expect fixed language mode andit will not be in "en-US" mode.



Is it a decimal keyboard ?

If so, there seems to be an issue:

https://stackoverflow.com/questions/58590996/uitextinputmode-doesnt-work-for-english-decimal-pad-in-ios-13

I arrived here after wasting an entire day chasing the same problem. Basically, overriding (in my case, swizzling) an implementation of textInputMode no longer has the expected behavior. iOS will call your implementation but then ignore the return value. Therefore, the keyboard remains with whatever language the user last selected rather than the language you return from textInputMode.


I was debugging with iOS 13.3.1 all day before a gut feeling made me try an older 12.4.5 device, where it works perfectly.


Here's the relevant code (just a hack at this stage):


void swizzle(Class thisClass, Class targetClass) {
    SEL originalSelector = @selector(textInputMode);
    SEL swizzledSelector = @selector(replacementTextInputMode);
    
    Method originalMethod = class_getInstanceMethod(targetClass, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(thisClass, swizzledSelector);
    
    BOOL didAddMethod = class_addMethod(targetClass, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));

    if (didAddMethod) {
        class_replaceMethod(targetClass, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class thisClass = [self class];
        swizzle(thisClass, [UIView class]);
    });
    
  [GeneratedPluginRegistrant registerWithRegistry:self];
  // Override point for customization after application launch.
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

NSString* langFromLocale(NSString* locale) {
    NSRange r = [locale rangeOfString:@"_"];
    if (r.length == 0) r.location = locale.length;
    NSRange r2 = [locale rangeOfString:@"-"];
    if (r2.length == 0) r2.location = locale.length;
    return [[locale substringToIndex:MIN(r.location, r2.location)] lowercaseString];
}

UITextInputMode* getTextInputModeForLanguage(NSString* language) {
    for (UITextInputMode *tim in [UITextInputMode activeInputModes]) {
        NSString* languageLocale = langFromLocale(language);
        NSString* primaryLanguageLocale = langFromLocale(tim.primaryLanguage);
        
        if ([languageLocale isEqualToString:primaryLanguageLocale]) {
            return tim;
        }
    }
    
    return nil;
}

- (UITextInputMode*)replacementTextInputMode {
    NSLog(@"Swizzled called!");
    NSObject* obj = (NSObject*)self;
    NSLog(@"DEBUG DESCRIPTION: %@", obj.debugDescription);
    
    UITextInputMode* forcedLanguage = getTextInputModeForLanguage(@"th-TH");
    
    return forcedLanguage;
}


With iOS 13, the keyboard will remain on English (or whatever language the user last selected). With iOS 12, it will switch to (in this case) Thai.