В указателе отсутствует спецификатор типа обнуляемости

В Xcode 7 GM я начал получать это предупреждение:

В указателе отсутствует спецификатор типа обнуляемости (_Nonnull, _Nullable или _Null_unspecified)

В следующем объявлении функции (расширение NSUserDefaults)

- (void)setObject:(nullable id)value
           forKey:(NSString *)defaultName
    objectChanged:(void(^)(NSUserDefaults *userDefaults, id value))changeHandler
    objectRamains:(void(^)(NSUserDefaults *userDefaults, id value))remainHandler;

Почему отображается это предупреждение и как мне это исправить?

7 ответов

Решение

Вам необходимо указать nullable также для обработчиков / блоков

- (void)setObject:(nullable id)value
           forKey:(nonnull NSString *)defaultName
    objectChanged:(nullable void(^)(NSUserDefaults *userDefaults, id value))changeHandler
    objectRamains:(nullable void(^)(NSUserDefaults *userDefaults, id value))remainHandler;

Зачем? Это из-за Свифта. Swift допускает необязательные параметры (?), Чего нет у Objective-C. Это делается как мост между ними для того, чтобы компилятор Swift знал, что эти параметры являются необязательными. "Nonnull" сообщит компилятору Swift, что аргумент является обязательным. Обнуляемый, что это необязательно

Для получения дополнительной информации читайте: https://developer.apple.com/swift/blog/?id=25

Вы можете использовать следующие макросы вокруг блоков объявлений (функций и переменных) в заголовках target c:

NS_ASSUME_NONNULL_BEGIN 

NS_ASSUME_NONNULL_END

Затем вам нужно добавить аннулируемые аннотации для ссылок, которые могут быть нулевыми в этом блоке. Это относится как к параметрам функции, так и к объявлениям переменных.

Как в:

@interface SMLBaseUserDetailsVC : UIViewController < UICollectionViewDelegate>
NS_ASSUME_NONNULL_BEGIN

@property (nonatomic, readonly) IBOutlet UIScrollView *detailsScrollView;
@property (nonatomic, readonly) IBOutlet UICollectionView *photoCV;
@property (nonatomic, weak, readonly) SMLUser *user;
- (IBAction)flagUser:(id)sender;
- (IBAction)closeAction:(nullable id)sender;
- (void) prefetchPhotos;

NS_ASSUME_NONNULL_END

@end

Редактировать * Почему??? Это связано с тем, что для того, чтобы класс Objective-C мог взаимодействовать со Swift, вам нужно объявить обнуляемость, чтобы компилятор знал, обрабатывать ли свойства как быстрые опции или нет. Обнуляемые свойства объекта c известны как дополнительные функции в swift, и использование этих макросов в сочетании с обнуляемыми объявлениями свойств позволяет компилятору обращаться с ними как с дополнительными (необязательные объекты - это монады - объект, заключающий в себе либо объект, либо ноль).

Чтобы отключить это предупреждение для всего вашего проекта

  1. Перейти в настройки сборки

  2. Убедитесь, что вы просматриваете вкладку "Все", а не "Основные" или "Индивидуальные"

  3. Поиск поля Other Warning Flags

  4. Добавьте следующий флаг: -Wno-nullability-completeness,

  5. Теперь очистите и соберите (cmd+shift+k, затем cmd + r)

    - примечание: предупреждение может исчезнуть через несколько секунд, даже после того, как вы закончите сборку, для меня полное обновление xCode занимает около 15 секунд

Правильная, рабочая декларация метода, принятая компилятором:

- (void)setObject:(nullable id)value
           forKey:(nonnull NSString *)defaultName
    objectChanged:(nullable void(^)(NSUserDefaults *_Nonnull userDefaults, id _Nullable value))changeHandler
    objectRamains:(nullable void(^)(NSUserDefaults *_Nonnull userDefaults, id _Nullable value))remainHandler;

Я публикую этот ответ, чтобы сказать, почему следует добавить _Nonnull или же nullable,

Согласно этому блогу: https://developer.apple.com/swift/blog/?id=25

Одна из замечательных особенностей Swift заключается в том, что он прозрачно взаимодействует с кодом Objective-C, как с существующими средами, написанными на Objective-C, так и с кодом в вашем приложении. Однако в Swift существует сильное различие между необязательными и необязательными ссылками, например NSView против NSView?в то время как Objective-C представляет оба этих двух типов как NSView *, Поскольку компилятор Swift не может быть уверен, является ли конкретный NSView * является необязательным или нет, тип вводится в Swift как неявно развернутый необязательный, NSView!,

это все для Свифта.

Удалите макрос из вашего.h файла, и предупреждение исчезнет.

NS_ASSUME_NONNULL_BEGIN 

NS_ASSUME_NONNULL_END

Удалите из /usr/local/include все заголовочные файлы, на которых есть ярлыки. Сработал как постоянное исправление для меня.

Другие вопросы по тегам