在iOS12中找不到ASIdentifierManager

时间:2018-11-14 10:30:51

标签: ios objective-c frameworks ios12 idfa

我在这里写cos,因为我真的被卡住了,找不到答案。

我们有一个小的框架,可以在其中收集IDFA。 对于IDFA收集,我们首先检查NSClassFromString(@"ASIdentifierManager")

问题是:

想象一下,我们有一个客户端,并且该客户端发布了iOS10-iOS12版本。 该客户端获得了适用于iOS10和iOS11的IDFA,但对于所有iOS12而言,根本没有IDFA!检查日志后,我们发现NSClassFromString(@"ASIdentifierManager")仅对iOS12为零。

客户端如何为iOS10(11)添加框架,但不能为iOS12添加框架?

另一方面,另一个客户端在iOS12上运行良好。

1 个答案:

答案 0 :(得分:2)

这可能无法完全回答您的问题,仅发送我所知道的和我的猜测即可。

首先,除非您使用,否则动态框架将不会加载到您的应用程序流程中,例如目录中的框架,可在iOS模拟器中找到设备。

> cd /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks
> # Now there are plenty of frameworks here.
> file  AdSupport.framework/AdSupport
Mach-O 64-bit dynamically linked shared library x86_64

如何使用? TLDR,可以在您的应用程序中的任何地方使用[ASIdentifierManager sharedManager]进行调用,当然,首先链接该框架并成功进行编译即可。

第二,直接使用NSClassFromString()和在任何地方调用[ASIdentifierManager sharedManager]有什么区别?

对于前一种情况,您的应用程序将不会加载AdSupport框架捆绑包,因为当os内核加载您的程序时,您的可执行程序中没有名为ASIdentifierManager的符号。打印您的应用程序主捆绑包路径并找到应用程序可执行文件,尝试进行nm <path/to/executable_app> | grep "ASIdentifierManager",因为您没有使用它,结果中什么也找不到。

对于后一种,请尝试在可执行程序中grep相同的符号。

  

注意:这不是操作系统通过nm结果列表加载框架,而是内核加载包含符号的框架,请查看有关动态加载器dyld的更多信息。

第三NSClassFromString仅检查已加载的类,如果未加载AdSupport框架,则它返回nil而不尝试加载包含目标类的框架

第四,除非您在项目中粘贴有关IDFA和AdSupport框架用法的更多上下文,否则无法回忆起iOS 10/11和iOS 12之间的区别。这是我的一个猜测,在早期版本中某些依赖库使用使用AdSupport框架,但iOS 12必须在iOS 11和iOS 12之间尝试转储符号列表。并比较结果。

第五,我不确定您想要什么,也许您正试图避免显式导入AdSupport框架,如何通过框架路径初始化NSBundle和调用-(BOOL)load类的NSBundle,则可以使用Class获取NSClassFromString对象。

更新:

NSString *strFrameworkPath = nil;

#if TARGET_OS_SIMULATOR
strFrameworkPath = [[NSProcessInfo processInfo] environment][@"DYLD_FALLBACK_FRAMEWORK_PATH"];
#else
// Assume that the AdSupport and Foundation framework are in the same directory.
strFrameworkPath = [NSBundle bundleForClass:NSPredicate.class].bundlePath;
strFrameworkPath = [strFrameworkPath stringByDeletingLastPathComponent];
#endif

strFrameworkPath = [strFrameworkPath stringByAppendingPathComponent:@"AdSupport.framework"];
NSAssert([[NSFileManager defaultManager] fileExistsAtPath:strFrameworkPath], @"Invalid framework bundle path!");

NSBundle *bundle = [NSBundle bundleWithPath:strFrameworkPath];

if (!bundle.isLoaded) {
    NSError *error = nil;

    if (![bundle loadAndReturnError:&error]) {
        DDLogError(@"Load framework bundle %@ with error %@", bundle, error);
    }
}

DDLogDebug(@"bundle: %@", bundle.bundlePath);
DDLogDebug(@"class: %@", NSClassFromString(@"ASIdentifierManager"));

您可能需要增强产品所用设备的兼容性,有关NSBundle使用的更多详细信息,请查看the official documentation here