Условная компиляция для платформы перед импортом - программирование
Подтвердить что ты не робот

Условная компиляция для платформы перед импортом


Я ищу способ проверить, существует ли среда и/или если ее классы определены, перед импортом и использованием этой структуры. В частности, основой является библиотека активов.

В настоящее время я могу сделать это с базой данных Core Data, поскольку в этой структуре есть файл CoreDataDefines.h, который предоставляет директиву препроцессора _COREDATADEFINES_H. Это позволяет мне просто проверить, что такое defintion:

#ifdef _COREDATADEFINES_H
#import <CoreData/CoreData.h>

// do something with Core Data

#else

// do something without using Core Data

#endif


К сожалению, в библиотеке ресурсов не содержится явный заголовочный файл определений, поэтому я ищу способ написать свой собственный оператор #define, который может проверить существование фреймворка перед импортом, так же как у меня есть сделано для данных ядра выше.

Я пробовал это:

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
// import assets library if defined !
#define ASSETSLIBRARY_DEFINE    (NSClassFromString(@"ALAsset") != nil)
#if ASSETSLIBRARY_DEFINE
#import <AssetsLibrary/AssetsLibrary.h>
#endif
#endif

... но не повезло.
Компилятор говорит мне, что" токен не является допустимым двоичным оператором в подвыражении препроцессора".


Любая помощь всегда приветствуется.

4b9b3361

Ответ 1

Если вы знаете, какой класс должен быть импортирован с помощью фреймворка, вы можете проверить, загружен ли он:

BOOL isFrameworkLoaded = (NSClassFromString(@"MyClassNameFromTheFramework") != nil);

Ответ 2

То, что вы здесь делаете, очень неправильно. Определение _COREDATADEFINES_H, которое вы видите в CoreDataDefines.h, известно как исходное значение, старый метод C, чтобы избежать множественных включений одного и того же заголовочного файла.

Вы, конечно, не должны использовать это в своем собственном коде, а присутствие sentinal только сообщает вам, что заголовок уже включен в другое место. Если sentinal не определен, это просто означает, что заголовок не был включен, а не тот, что сама структура не является несуществующей.

Я не уверен точно, что вы пытаетесь сделать, но похоже, что вы хотите использовать макросы для выбора между кодом, который использует фреймворк, и кодом, который не использует фреймворк. Если вы хотите сделать это во время компиляции, ваш единственный выбор - определить свои собственные макросы и настроить их в своей целевой среде с помощью некоторых параметров компилятора. Например, чтобы включить код, который использует библиотеку ресурсов, вы можете определить это в настройке сборки "Другие C флаги":

-DUSE_ASSETS_FRAMEWORK

И затем используйте это в своем коде:

#ifdef USE_ASSETS_FRAMEWORK
    #import <AssetsLibrary/AssetsLibrary.h>
    // code that uses assets framework
#else
    // code that does not use assets framework
#endif

Если вы хотите во время выполнения определять, связано ли приложение с фреймворком и что инфраструктура существует в текущей версии iOS, вы должны использовать стандартный подход, который Apple рекомендует, чтобы проверить существование любых классов или функций, которые вам нужны:

if (NSClassFromString(@"ALAsset")) {
    // ALAsset is available }
} else {
    // ALAsset not available
}

Ответ 3

У меня есть несколько трюков для такого рода вещей... Хотя последующее не может ТОЧНО решить проблемы, которые вы подробно описали, это может помочь вам найти окончательное решение... Первая "стратегия" может быть вызвана в "Script Фаза сборки". Это можно использовать разными способами, но в этом примере оно ИСПЫТАНИЕ, что Framework действительно, (согласно otool, а затем выполняет некоторую "пост-обработку" соответственно.., а затем снова проверяет его и т.д..

function test { "[email protected]";   status=$?;
    if [ $status -ne 0 ]; then
       echo "error with $1"; fi 
    return $status
}
  PRODUCT_PATH="${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}"
        BINARY="$PRODUCT_PATH/${PRODUCT_NAME}"
           MAC="/Library/Frameworks/"
SYSTEM_PRODUCT="$MAC/${WRAPPER_NAME}"

test otool -l "$BINARY" #/Library/Frameworks/AtoZ.framework/AtoZ
if [ $status -ne 0 ]; then
   sudo rm -r "$SYSTEM_PRODUCT"
   sudo cp -r "$PRODUCT_PATH" "$SYSTEM_PRODUCT"
test otool -l "$BINARY" 
if [ $status == 0 ]; then
   cd "${PRODUCT_PATH}"
   ln -sF Versions/Current/Frameworks Frameworks
fi

Следующая рука в этой мудрости бесплатно для всех - это сексуальный и метко названный метод NSBundle.. preflightAndReturnError

NSBundle *b = [NSBundle bundleWithPath:path];
NSError *e  = nil;
BOOL okdok  = [b preflightAndReturnError:&e];
if  (okdok)  
     okdok  = [b load];
if (!okdok) { [self jumpOffABridge:nil]; goto hell; }

Скорее всего,... вы будете... OK DOK, к моменту завершения load.