Unrecognised selector +[AFAnalytics sharedAnalytics]?

Viewed 386

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?

1 Answers

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
Related