Почему objective-c не имеет проверки доступности API?
Swift 2 имеет API проверку доступности.
Компилятор даст вам ошибку при использовании API, слишком нового для вашего минимальная целевая ОС
Почему компилятор objective-c не может использовать эквивалент?
Я тестировал проверку доступности API в googled, и были получены только быстрые результаты 2, поэтому я предполагаю, что компилятор для объективного c не может этого сделать.
Ответы
Ответ 1
Предупреждение (Swift делает ошибку) просто не было реализовано в компиляторе Clang уже много лет, но это не присущее ограничение Objective-C (хотя из-за его динамического характера вы не сможете поймать все случаи), или терминология Свифт.
Макросы Apple (например, NS_CLASS_AVAILABLE
) и исходные атрибуты (__attribute__((visibility(...)))
, __attribute__((availability(...)))
) для аннотирования заголовков с информацией о доступности были в течение многих лет, и они широко используются в Apple SDK. Макросы определяются в Foundation
NSObjCRuntime.h
и заголовках системы Availability.h
/AvailabilityMacros.h
, и компилятор может (и делает) читать их.
В начале 2015 года добавлено предупреждение -Wpartial-availability
в ветвь Clang master
, но это предупреждение/фиксация не было сделано его путь в версию Apple Clang до (включая) Xcode 7.2. Вы получите журнал unknown warning option
при добавлении флага предупреждения в проект в Xcode 7.2, но флаг доступен в Xcode 7.3. В настоящее время для него нет предопределенных настроек, но вы можете добавить флаг в Other Warning Flags
в разделе "Настройки сборки".
Существуют и другие инструменты, которые используют библиотеки LLVM для обнаружения частично доступных API, например Deploymate. Для моей дипломной работы я разработал инструмент, который интегрируется непосредственно в Xcode и основан на модификации компилятора Clang. Код по-прежнему онлайн, но я не справился с общей разработкой Clang, поэтому он не будет очень полезен, кроме обучения цели. Однако "официальный" код (связанный выше) намного чище и лучше.
Изменить: Начиная с Xcode 9, проверка доступности будет работать и для Objective-C (и C). Вместо использования вышеупомянутого предупредительного флага, который не поддерживает временное/локальное развертывание цели развертывания и, следовательно, вызывает множество ложных срабатываний, там -Wunguarded-availability
и if (@available(iOS 11, *)) {...}
для проверки и повышения цели развертывания для следующего блока код. По умолчанию он отключен, но -Wunguarded-availability-new
будет включен по умолчанию и начнет проверять что-либо за пределами iOS/tvOS 11, watchOS 4 и High Sierra. Более подробную информацию об этом можно найти в Xcode 9 бета-версиях, которая в настоящее время требует входа в систему с учетной записью разработчика.
Ответ 2
Xcode 9.0 выводит синтаксис проверки доступности во время выполнения от Swift до Objective-C:
if (@available(macOS 10.9, *))
{
// call 10.9+ API
}
else
{
// fallback code
}
в комплекте с предупреждениями для вызова API, которые новее, чем ваш целевой объект развертывания (если эти вызовы не завернуты в проверки).
finally;)
Ответ 3
Объект C не имеет проверки доступности как часть языка, так как тот же результат доступен через препроцессор Objective C.
Это "традиционный" способ сделать это на языках C.
Хотите узнать, скомпилированы ли в режиме отладки?
#ifdef DEBUG
// code which will be inserted only if compiled in debug mode
#endif
Хотите проверить во время компиляции для минимальной версии?
Используйте заголовок Availability.h в iOS и аналогичные заголовки для Mac OS X.
Этот файл находится в каталоге /usr/include.
просто проверьте __IPHONE_OS_VERSION_MAX_ALLOWED с препроцессором, например:
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert) categories:nil]];
}else{
[[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert)];
}
#else
[[UIApplication sharedApplication] registerUserNotificationSettings: (UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert)];
#endif
Поскольку у Swift нет препроцессора, им приходилось изобретать способ делать такие проверки внутри самого языка.
Если вы хотите проверить доступность метода во время выполнения, обратите внимание, что подходящим способом является метод отвечаетSoSelector: или экземплярыRespondToSelector: (последний на класс).
Обычно вы хотите комбинировать оба подхода, компилировать условную компиляцию и проверку времени выполнения.
Проверка наличия метода Objective C, например. на уровне класса:
if ([UIImagePickerController instancesRespondToSelector:
@selector (availableCaptureModesForCameraDevice:)]) {
// Method is available for use.
// Your code can check if video capture is available and,
// if it is, offer that option.
} else {
// Method is not available.
// Alternate code to use only still image capture.
}
Если вы хотите проверить, существует ли функция C во время выполнения, это еще проще: если она существует, сама функция не равна нулю.
Вы не можете использовать одинаковый подход на обоих языках.
Ответ 4
Конечно, вы получите ошибки в коде Objective-C. Но вы не найдете результатов в google для Objective-C, если вы используете термин, определенный для Swift, поскольку вы не найдете сайт kisuaheli в google, если вы ищете немецкое слово.; -)
Вы получите сообщение об ошибке, связывающее код Objective-C со слишком старым SDK. Это просто потому, что используемый метод или класс или $все не определены в заголовке для этого SDK. Опять же, конечно.
Это типичный быстрый маркетинг Apple: из-за неспособности Swift им нужно расширить язык, чтобы получить что-то, что довольно легко в Objective-C. Вместо того, чтобы пояснить, что это результат плохой работы Свифта, они говорят вам, что это отличная особенность Свифта. Это как вырезать пальцы, а затем сказать: "У нас отличная штукатурка!!!!!!!!" И вам нужно подождать только несколько дней, и один приходит на SO с Q: "Почему Objective-C не обладает великолепной штукатуркой?" Простой ответ: он не режет пальцы.
Проблема заключается не в том, чтобы генерировать ошибки. Проблема состоит в том, чтобы иметь один исходный код для всех версий, поэтому вы можете просто изменить версию SDK и получить новый код (или ошибки). Это необходимо для упрощения обслуживания.
В Objective-C вы просто можете использовать ответ, найденный здесь:
Условно скрыть код из компилятора или вы можете сделать это во время выполнения, как указано в комментариях к Q. (Но это другое решение проблемы по своей природе, потому что это динамический подход вместо статического, как вам нужно делать в Swift.)
Причина наличия языковой функции в Swift заключается в том, что у Swift нет препроцессора, поэтому решение Objective-C не работает в Swift. Поэтому условный код был бы невозможен в Swift, и им пришлось добавить функцию штукатурки, а также язык.