У указателя отсутствует спецификатор типа nullability
В Xcode 7 GM я начал получать это предупреждение:
У указателя отсутствует спецификатор типа nullability (_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;
Почему это предупреждение отображается и как его исправить?
Ответы
Ответ 1
Вы должны указать 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
Ответ 2
Вы можете использовать следующие макросы вокруг блоков деклараций (функций и переменных) в объектных заголовках 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, который должен быть совместим с быстрым, вам нужно объявить значение nullability, чтобы компилятор знал, что свойства обрабатываются как быстрые или нет. Неверные объектные свойства c известны как опции в swift, и использование этих макросов в сочетании с объявляемыми с нулевым объявлением объявлениями свойств позволяет компилятору относиться к ним как к опциям (опции - monads - объект, который обертывает либо объект, либо nil).
Ответ 3
Правильное объявление рабочего метода, принятое компилятором:
- (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;
Ответ 4
Я отправляю этот ответ, чтобы сказать, зачем добавлять _Nonnull
или nullable
.
Согласно этому блогу: https://developer.apple.com/swift/blog/?id=25
Одна из замечательных особенностей Swift заключается в том, что он прозрачно взаимодействует с кодом Objective-C, как существующими фреймворками, написанными в Objective-C, так и кодом в вашем приложении. Однако в Swift существует сильное различие между необязательными и необязательными ссылками, например. NSView
vs. NSView?
, а Objective-C представляет обе эти два типа как NSView *
. Поскольку компилятор Swift не может определить, является ли конкретный NSView *
необязательным или нет, тип вводится в Swift как неявно развернутый необязательный, NSView!
.
все это для Swift.
Ответ 5
Чтобы отключить это предупреждение для всего вашего проекта
Перейти в настройки сборки
Убедитесь, что вы просматриваете вкладку "Все", а не "Основные" или "Индивидуальные"
Поиск поля Other Warning Flags
Добавьте следующий флаг: -Wno-nullability-completeness
.
Теперь очистите и соберите (cmd + shift + k, затем cmd + r)
Выйдите из xCode и снова откройте (Не пропустите этот шаг!)
--note, может пройти несколько секунд, чтобы предупреждения исчезли, даже после того, как вы закончите сборку и перезапуск xCode, для меня это займет около 15 секунд для полного обновления xCode
Ответ 6
Удалите приведенный ниже макрос из вашего файла .h, и предупреждение исчезнет
NS_ASSUME_NONNULL_BEGIN
NS_ASSUME_NONNULL_END