Как определить код для разных версий iOS

Я работаю над приложением для iOS. Я хочу, чтобы оно поддерживало iOS 7 и 8. Все идет хорошо, однако есть много разных частей приложения, которые используют Apple API. Некоторые из этих API работают как в iOS 8, так и в 7. Однако некоторые из них устарели в iOS 8. Поэтому я зашел на сайт разработчиков Apple, чтобы посмотреть, чем их заменить (новые методы/и т. д.).

Однако теперь у меня есть проблема, что приложение будет работать на iOS 8 нормально, но некоторые его части не работают должным образом на iOS 7, так как я пытаюсь использовать API iOS 8...... (смеется) .

Поэтому я просто хотел узнать, как лучше всего реализовать код, который работает на iOS 8 и 7. У меня было несколько идей (ниже), но я не уверен, что лучше:

ИДЕЯ 1

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

if (SYSTEM_VERSION_LESS_THAN(@"8.0")) {
    // iOS 7 device. Use iOS 7 apis.
}

else {
   // iOS 8 (or higher) - use iOS 8 apis.
}

ИДЕЯ 2

Я думал об использовании определений ifdef во всем приложении, например:

#ifdef __IPHONE_8_0
     // iOS 8 code here....
#else
     // iOS 7 code here....
#endif

Какой способ лучше? Я бы подумал, что вторая идея намного быстрее и использует меньше ресурсов, верно?

Или обе мои идеи ерунда? Есть ли лучший способ решения этой проблемы?

Спасибо за ваше время, Дэн.


person Supertecnoboff    schedule 10.01.2015    source источник
comment
Не проверяйте версию для iOS. Проверка доступности API во время выполнения. Прочтите Руководство по совместимости SDK в документации.   -  person rmaddy    schedule 10.01.2015
comment
К вашему сведению. Если API поддерживается в iOS 7 и устарел в iOS 8, вам вообще ничего не нужно делать. API iOS 7 — это то, что вы должны использовать. Он по-прежнему будет работать под iOS 8.   -  person rmaddy    schedule 10.01.2015
comment
@rmaddy Ты уверен в этом? Я выполнял некоторую работу с чтением простого файла XML Plist. В iOS 8 мой код, используемый для чтения XML-файла, перестал работать. Как только я протестировал его с API iOS 8, он снова начал работать в обычном режиме. Также говорят, что нужно просто придерживаться устаревших API... это звучит опасно, наверняка может привести к утечке памяти или неожиданным сбоям.   -  person Supertecnoboff    schedule 10.01.2015
comment
Я на 100% уверен в этом. Если у вас возникли проблемы с определенным API, опубликуйте вопрос, относящийся к этой проблеме. Этот вопрос слишком общий, чтобы предоставлять конкретные детали.   -  person rmaddy    schedule 10.01.2015
comment
Устаревший API не означает, что вы не должны использовать его в текущей версии. Это означает, что он не будет работать со следующей версии и будет работать только до текущей версии.   -  person Midhun MP    schedule 10.01.2015
comment
@MidhunMP Хорошо, хорошо. Спасибо за ваше объяснение, действительно полезно.   -  person Supertecnoboff    schedule 10.01.2015
comment
@MidhunMP Устаревшие API не означают, что они перестают работать. API, устаревшие в iOS 3, все еще работают за редкими исключениями. И да, это означает, что вы не должны использовать его в версии, в которой он устарел, если вы также все еще не поддерживаете версии до устаревания. Другими словами, устаревшее в iOS 8 означает, что если вы поддерживаете только iOS 8, вам следует перейти на новый API сейчас. Но если вы также поддерживаете iOS 7, можно продолжать использовать устаревший API.   -  person rmaddy    schedule 10.01.2015


Ответы (2)


Я не предлагаю проверять версию и писать код на ее основе. Вместо этого вам нужно проверить, доступен ли этот API или нет.

Для проверки доступности класса или нет:

Class checkClass = NSClassFromString(@"CheckingClass");

if (checkClass)
{
   // Available
}
else
{
  // Not Available
}

Если вам нужно проверить доступную функцию/функцию;

if ([checkClass respondsToSelector:@selector(yourMethod:)])
{
   // Feature/ Method Available
}
else
{
   // Feature/ Method Not Available
}

ПРИМЕЧАНИЕ:

Устаревший API не означает, что вы не должны использовать его в текущей версии. Это означает, что он не будет работать со следующей версии и будет работать только до текущей версии.

person Midhun MP    schedule 10.01.2015
comment
Хорошо, спасибо за ваш ответ и пример. Кажется, это лучший способ подойти к проблеме. Еще раз спасибо. - person Supertecnoboff; 10.01.2015
comment
Примечание в конце этого ответа неверно. Устаревшие API очень редко перестают работать. - person rmaddy; 10.01.2015
comment
@rmaddy: я не понял, что ты имеешь в виду. Я знаю множество устаревших API в iOS 6, которые не работают в iOS 8. - person Midhun MP; 10.01.2015
comment
Возможно, я немного преувеличил. Это зависит от класса и API. Я знаю API, которые были объявлены устаревшими в iOS 3.0, но все еще работают в iOS 8. Но вы правы, есть фрагменты некоторых устаревших API, которые быстро перестали работать, но это не всегда так. - person rmaddy; 10.01.2015
comment
@rmaddy: Да, ты прав. Вы можете использовать устаревшие API, пока они существуют (нет барьера версии) - person Midhun MP; 10.01.2015
comment
@rmaddy Но все же API устаревает по какой-то причине. Если он устарел, то вы не должны его использовать. Вам нужно использовать API, предоставленный для этой конкретной версии ОС. В противном случае, какой смысл осуждать что-либо в первую очередь...? - person Supertecnoboff; 10.01.2015
comment
@Supertecnoboff Устаревший означает, что его поддержка может быть прекращена в будущем, возможно, в конце концов. Это не значит, что вы не можете продолжать использовать его в данный момент. Если вы поддерживаете iOS 7 и 8, то нет ничего плохого в использовании API, который был активен в iOS 7, но устарел в iOS 8. У меня есть приложения в магазине приложений, полные такого кода. Когда я прекращу поддержку iOS 7 в будущем, я заменю эти устаревшие API. - person rmaddy; 10.01.2015

Способ ifdef не будет работать, потому что операторы препроцессора оцениваются во время компиляции; но только во время выполнения мы знаем, с какой ios-версией нам предстоит иметь дело.

Вы бы использовали макросы, например, если хотите поддерживать Mac OS X и iOS с одним и тем же кодом, потому что во время компиляции вы знаете, будет ли двоичный файл для Mac OS или iOS.

Таким образом, в этом случае вам нужен подход 1 - или, что еще лучше, вы должны использовать respondsToSelector: для проверки доступности вместо тестирования версии iOS, если это возможно.

Однако, поскольку вы имеете дело только с предупреждениями об устаревании, вам не нужно ничего делать и следует просто продолжать использовать устаревшие API до тех пор, пока приложению больше не потребуется поддержка ios7.

person stefreak    schedule 10.01.2015
comment
Спасибо за Ваш ответ. Звучит хорошо, но я думаю, что выберу ответ @MidhunMP. Поскольку использование устаревших API не дает мне уверенности в том, что мое приложение будет работать без сбоев. - person Supertecnoboff; 10.01.2015
comment
Устаревание на самом деле является только объявлением о том, что Apple удалит его в будущем (ios9) — это не означает, что оно нестабильно или больше не поддерживается! - person stefreak; 10.01.2015