Search code examples
xcodeios11ios12

Unrecognised selector +[AFAnalytics sharedAnalytics]?


I am currently getting my app ready for iOS 12 however whenever I tap on any UITextField or UITextView the app crashes and I get this unrecognised selector error.

What I've tried

  • They're delegates are linked to the Files Owner (yes I know - the old term) but have unliked everything and stopped referencing it in the UIViewController however still get the same crash and error message.
  • Added a brand new UITextView/UITextField but- again same crash error.
  • Searched everywhere online but there has been nothing not anything useful.
  • Only crashes on iOS 12. iOS 11 and lower work perfect, no issues.
  • App uses Firebase, Crashlytics/Fabric and some other third-party libraries which are all using latest SDK/API version.

Closest thing I've found is that AFAnalytics.h is part of the AssistantServices.framework that I can't find in Xcode 10 Beta 6 nor in the public Xcode 9??

Honestly I'm starting to run out of ideas so any help to try and resolve this would be a massive help.

Im writing in Objective-C.

Full stacktrace: http://crashes.to/s/dd22fb06f7b


UPDATE - 2/09/2018 - Weirdly, setting the Keyboard Type to E-mail Address in interface builder the field works perfectly fine. Setting it to anything else crashes the app.


UPDATE - 14/9/2018 Another crash log seems to suggest that the error revolves around [UIDictationConnection analytics]?

Does this make any sense to anyone? - This is from a crash report by Apple. enter image description here


UPDATE - 2/10/2018 I have discovered this error message:

Class AFAnalytics is implemented in both /Users/ashleyrichards/Library/Developer/CoreSimulator/Devices/C155EF28-3C0B-4AFF-9EF6-0235295A26DC/data/Containers/Bundle/Application/562B100D-F657-424E-8B77-99D0325F6035/Social Dummy.app/Social Dummy (0x10a33d610) and /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/AssistantServices.framework/AssistantServices (0x13654d178). One of the two will be used. Which one is undefined.

I've search my entire project but haven't found any class relating to AFAnalytics. For the record, I don't want to use AFAnalytics. I don't even know what it does.. How do I get rid of it?


Solution

  • I've found a workaround that prevents crash. We can use iOS runtime to swizzle class methods. The main idea is to redirect message from +[AFAnalytics sharedAnalytics] to +[iOS12AFAnalyticsBug newSharedAnalytics]. Class method "newSharedAnalytics" intentionally returns nil and messages to nil won't cause a crash. But use this workaround carefully since some code in your app uses AFAnalytics for some purposes.

    AppDelegate.m

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        [iOS12AFAnalyticsBug fix];
        //your code
    }
    

    iOS12AFAnalyticsBug.h

    @interface iOS12AFAnalyticsBug : NSObject
    
    + (void)fix;
    
    @end
    

    iOS12AFAnalyticsBug.m

    #import "iOS12AFAnalyticsBug.h"
    #include <objc/message.h>
    
    void SwizzleClassMethod(Class originClass, SEL originSelector, Class destClass, SEL newSelector) {
    
        Method originMethod = class_getClassMethod(originClass, originSelector);
        Method newMethod = class_getClassMethod(destClass, newSelector);
    
        originClass = object_getClass((id)originClass);
    
        if (class_addMethod(originClass, originSelector, method_getImplementation(newMethod), method_getTypeEncoding(newMethod))) {
            class_replaceMethod(originClass, newSelector, method_getImplementation(originMethod), method_getTypeEncoding(originMethod));
        } else {
            method_exchangeImplementations(originMethod, newMethod);
        }
    }
    
    @implementation iOS12AFAnalyticsBug
    
    + (instancetype)newSharedAnalytics {
    
        return nil; //All messages to nil won't cause a crash
    
    }
    
    + (void)fix {
    
        Class originClass = NSClassFromString(@"AFAnalytics");
        SEL originSelector = NSSelectorFromString(@"sharedAnalytics");
    
        SwizzleClassMethod(originClass, originSelector, self.class, @selector(newSharedAnalytics));
    }
    
    @end