В указателе отсутствует спецификатор типа обнуляемости
В 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, и использование этих макросов в сочетании с обнуляемыми объявлениями свойств позволяет компилятору обращаться с ними как с дополнительными (необязательные объекты - это монады - объект, заключающий в себе либо объект, либо ноль).
Чтобы отключить это предупреждение для всего вашего проекта
Перейти в настройки сборки
Убедитесь, что вы просматриваете вкладку "Все", а не "Основные" или "Индивидуальные"
Поиск поля
Other Warning Flags
Добавьте следующий флаг:
-Wno-nullability-completeness
,Теперь очистите и соберите (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 все заголовочные файлы, на которых есть ярлыки. Сработал как постоянное исправление для меня.