Подтвердить что ты не робот

Какая условная компиляция используется для переключения между конкретным кодом Mac и iPhone?

Я работаю над проектом, который включает приложение Mac и приложение iPad, совместно использующее код. Как я могу использовать условные компиляционные ключи для исключения кода для Mac из проекта iPhone и наоборот? Я заметил, что TARGET_OS_IPHONE и TARGET_OS_MAC равны 1, и поэтому оба они всегда верны. Есть ли другой переключатель, который я могу использовать, который вернет true только при компиляции для определенной цели?

По большей части, я получил файлы к сотрудничеству, переместив #include <UIKit/UIKit.h> и #include <Cocoa/Cocoa.h> в заголовки precompile для двух проектов. Я делюсь моделями и некоторым кодом утилиты, который извлекает данные из RSS-каналов и Evernote.

В частности, функция [NSData dataWithContentsOfURL:options:error:] принимает другую константу для параметра параметров iOS 3.2 и более ранних версий и Mac OS 10.5 и ранее, чем для iOS 4 и Mac OS 10.6. Условие, которое я использую, следующее:

#if (TARGET_OS_IPHONE && (__IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_3_2)) || (TARGET_OS_MAC && (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5))

Это похоже на работу, но я хочу убедиться, что это пуленепробиваемый. Я понимаю, что если версия Mac установлена ​​в 10.6, но версия iOS установлена ​​на 3.2, она все равно будет использовать новые константы, даже если она компилирует для iOS 3.2, что кажется неправильным.

Заранее благодарим за помощь!

4b9b3361

Ответ 1

Вы сделали ошибку в своих наблюдениях.:)

TARGET_OS_MAC будет составлять 1 при создании приложения Mac или iPhone. Вы правы, это совершенно бесполезно для такого рода вещей.

Тем не менее, TARGET_OS_IPHONE равно 0 при создании приложения Mac. Я использую TARGET_OS_IPHONE в своих заголовках все время для этой цели.

Вот так:

#if TARGET_OS_IPHONE
// iOS code
#else
// OSX code
#endif

Здесь отличный график: http://sealiesoftware.com/blog/archive/2010/8/16/TargetConditionalsh.html

Ответ 2

"Правильная вещь - просто использовать новые константы, потому что если вы посмотрите на заголовок, вы увидите, что они объявлены эквивалентными старым в перечислении, что означает, что новые константы будут работать даже на старых версиях (обе константы компилируются в одно и то же, а так как перечисления скомпилированы в приложение, которое они не могут изменить, не нарушая двоичную совместимость). Единственная причина, по которой это не делать, - это продолжить восстановление старых SDK (это отличная от поддержки старых версий, которые вы можете выполнять при компиляции с новыми SDK).

Если вы действительно хотели использовать разные флаги на основе версии ОС (потому что новая версия фактически добавила новые функции, а не просто переименование константы), то есть две разумные вещи, которые вы можете сделать, ни один из которых ваш макрос выше выполняет:

  • Чтобы всегда использовать старые флаги, если только разрешенная версия min больше версии, они были введены в (что-то вроде этого):

    #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060)
      NSDataReadingOptions  options = NSDataReadingMapped;
    #else
      NSDataReadingOptions  options = NSMappedRead;
    #end
    
  • Условно использовать только новые значения в сборках, которые могут только для новых версий, и компилировать код для определения флагов во время выполнения для сборок, поддерживающих обе версии:

    #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060)
      NSDataReadingOptions  options = NSDataReadingMapped;
    #else
      NSDataReadingOptions  options;
      if ([[UIDevice currentDevice] systemVersion] compare:@"4.0"] != NSOrderedAscending) {
         options = NSDataReadingMapped;
      } else {
        options = NSMappedRead;
      }
    #end
    

Обратите внимание, что если вы действительно делали это сравнение, вы бы хотели где-то спрятать результат [[UIDevice currentDevice] systemVersion] compare:@"4.0"]. Вы также обычно хотите явно тестировать функции, используя такие вещи, как слабое связывание, а не сравнение версий, но это не вариант для перечислений.

Ответ 3

Используемые макросы определены в файле заголовка SDK TargetConditionals.h. Взято из SDK 10.11:

TARGET_OS_WIN32           - Generated code will run under 32-bit Windows
TARGET_OS_UNIX            - Generated code will run under some Unix (not OSX) 
TARGET_OS_MAC             - Generated code will run under Mac OS X variant
   TARGET_OS_IPHONE          - Generated code for firmware, devices, or simulator 
      TARGET_OS_IOS             - Generated code will run under iOS 
      TARGET_OS_TV              - Generated code will run under Apple TV OS
      TARGET_OS_WATCH           - Generated code will run under Apple Watch OS
   TARGET_OS_SIMULATOR      - Generated code will run under a simulator
   TARGET_OS_EMBEDDED       - Generated code for firmware

Так как здесь все "вариант Mac OS X", TARGET_OS_MAC в этом случае не пригодится. Для компиляции специально для macOS, например:

#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR && !TARGET_OS_EMBEDDED
    // macOS-only code
#endif

Ответ 4

В набор используемых макросов теперь входит TARGET_OS_OSX:

    TARGET_OS_WIN32           - Generated code will run under 32-bit Windows
    TARGET_OS_UNIX            - Generated code will run under some Unix (not OSX) 
    TARGET_OS_MAC             - Generated code will run under Mac OS X variant
       TARGET_OS_OSX          - Generated code will run under OS X devices
       TARGET_OS_IPHONE          - Generated code for firmware, devices, or simulator
          TARGET_OS_IOS             - Generated code will run under iOS 
          TARGET_OS_TV              - Generated code will run under Apple TV OS
          TARGET_OS_WATCH           - Generated code will run under Apple Watch OS
             TARGET_OS_BRIDGE          - Generated code will run under Bridge devices
       TARGET_OS_SIMULATOR      - Generated code will run under a simulator
       TARGET_OS_EMBEDDED       - Generated code for firmware

Кажется, работает нормально для условной компиляции кода macOS.