it-swarm.com.ru

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

В 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;

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

56
kelin

Вы должны указать 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

53
Ares

Вы можете использовать следующие макросы вокруг блоков объявлений (функций и переменных) в заголовках Objective 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, вам нужно объявить обнуляемость, чтобы компилятор знал, обрабатывать свойства как Swift как опциональные или нет. Обнуляемые свойства Objective C известны как дополнительные в Swift, и использование этих макросов в сочетании с обнуляемыми объявлениями для свойств позволяет компилятору рассматривать их как дополнительные (необязательные - монады - объект, который заключает в себе либо объект, либо ноль).

52
Kevin

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

- (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;
14
kelin

Я публикую этот ответ, чтобы рассказать, почему следует добавить _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!.

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

9
fishtrees