Я пишу сюда, потому что я действительно застрял и не могу найти ответа.
У нас есть небольшой фреймворк, который может собирать IDFA внутри.
Для сбора IDFA сначала проверяем NSClassFromString(@"ASIdentifierManager").
Проблема в:
Представьте, что у нас есть клиент, и этот клиент выпустил версию для iOS10-iOS12.
И этот клиент получает IDFA для iOS10 и iOS11, но для всех iOS12 вообще нет IDFA! После проверки журналов мы обнаружили, что NSClassFromString(@"ASIdentifierManager") равен нулю только для iOS12 ..
Как клиент мог добавить фреймворк для iOS10, 11, но не для iOS12?
С другой стороны, другой клиент хорошо справляется с iOS12.
У нас есть #include <AdSupport/AdSupport.h>. И снова - такая же сборка работает для iOS10,11. Но не для iOS12. Похоже, клиент каким-то образом исключает привязку именно для iOS12 - но как





Это может не дать полного ответа на ваш вопрос, просто напишите, что я знаю и мои предположения.
Первый, динамические фреймворки не будут загружены в процесс вашего приложения, пока вы не использовать его, например фреймворки в каталоге, которые доступны в 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
Как это использовать? TL; DR, вызовите его с помощью [ASIdentifierManager sharedManager] в вашем приложении где угодно, сначала свяжите его с фреймворком и, конечно же, успешно скомпилируйте.
Второй, какая разница между использованием NSClassFromString() напрямую и вызовом [ASIdentifierManager sharedManager] где угодно?
В первом случае ваше приложение не будет загружать пакет фреймворка AdSupport, поскольку в вашей исполняемой программе нет символа с именем ASIdentifierManager, когда ядро ОС загружает вашу программу, это можно доказать, распечатав путь к основному пакету вашего приложения и найдите исполняемый файл приложения. файл, попробуйте nm <path/to/executable_app> | grep "ASIdentifierManager", в результате ничего не будет найдено, так как вы его не использовать.
Для последнего попробуйте найти тот же символ в исполняемой программе, вот и он.
Note: it's not os kernel loads the frameworks by
nmresult list but the kernel loads the frameworks containing the symbols, check out more info about the dynamic loader dyld.
Третий, NSClassFromString проверяет только загруженные классы, если фреймворк AdSupport не загружен, он возвращает ноль, не пытаясь загрузить фреймворк, содержащий целевой класс.
Четвертый, невозможно вспомнить разницу между iOS 10/11 и iOS 12, пока вы не вставите больше контекста об использовании фреймворка IDFA и AdSupport в свой проект. Вот моя единственная догадка, некоторые из зависимых библиотек использовать фреймворка 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 ознакомьтесь с официальная документация здесь.
Мужик, большое тебе спасибо за этот ответ! Я очень ценю это. Не могли бы вы указать пример кода с NSBundle и -(BOOL)load?
NSBundle * b = [NSBundle bundleWithPath: @ "/ System / Library / Frameworks / AdSupport.framew ork"]; BOOL success = [b load];
Обновлено, возможно, потребуется повысить совместимость типов устройства с продуктами.
Вы пробовали
@import AdSupport;или ссылку на фреймворк в проекте?