How to get rid of nullability warning in an objective c typedef? - objective-c

This code produces a "pointer is missing a nullability type specifier" warning in XCode and I can't guess how to silence the warning.
NS_ASSUME_NONNULL_BEGIN
#interface MyClass : NSObject
typedef id (^MyBlock)(id object);
#end
NS_ASSUME_NONNULL_END
The following don't silence the warning:
typedef __nonnull id (^MyBlock)(__nonnull id object);
typedef nonnull id (^MyBlock)(nonnull id object);
I would appreciate any suggestions.
Thank you.

typedef types don’t usually have an inherent nullability—they can
easily be either nullable or non-nullable depending on the context.
Therefore, typedef types are not assumed to be nonnull, even within
audited regions.[1]
Below syntax is working fine
typedef __nonnull id (^MyBlock)(__nonnull id object);

Related

Checking whether an ObjC property is nullable at runtime

I'm trying to figure out at runtime whether a property of a class is nullable. For example:
#interface A : NSObject
+ (NSSet<NSString *> *)nullableProperties;
#property (readonly, nonatomic) NSString *description;
#property (readonly, nonatomic, nullable) NSError *error;
#end
#implementation A
+ (NSSet<NSString *> *)nullableProperties {
// Code that identifies nullable properties.
}
#end
nullableProperties should in this case return an NSSet with #"error".
property_getAttributes function can provide information of some of the attributes (more info here). Unfortunately, it doesn't provide information on whether the property is declared as nullable.
I would like to avoid implementing nullableProperties for every class that I need to know the nullable properties for.
Every Objective-C pointer or object property is technically nullable at runtime. The nullability specifiers are simply compiler hints that don't affect the actual built binary [edit: by which I mean, since this is apparently unclear, the 1s and 0s that get written to the disk in either Mach-O or some other comparable binary format by the compiler and linker, and which contain the machine instructions that represent the program logic along with other information and metadata]. Therefore, there's no way to detect at runtime which properties are nullable and which are not.

NSError, Swift, and nullability

I'm writing a set of tools in Objective-C that will be used by Swift at some point so I'm using generics and nullability. What am I supposed to do in this situation?
- (NSArray<MyObj *> * __nullable)foo:(NSError **)error;
Currently I'm getting a warning: Pointer is missing a nullability type specifier... for both pointers! I'm almost certain that I'm NOT to supposed to do:
- (NSArray<MyObj *> * __nullable)foo:(NSError * __autoreleasing __nullable * __nullable)error;
Am I?
The Swift blog entry Nullability and Objective-C states:
The particular type NSError ** is so often used to return errors via
method parameters that it is always assumed to be a nullable pointer
to a nullable NSError reference.
However, this remark is listed as an exception to the rules
of "Audited Regions", and it seems that it applies only within
an audited region:
NS_ASSUME_NONNULL_BEGIN
#interface MyClass : NSObject
- (NSArray<MyObj *> * _Nullable)foo:(NSError **)error;
#end
NS_ASSUME_NONNULL_END
Within an audited region, any simple pointer type will be assumed to be nonnull (with some exceptions as the above-mentioned for NSError).
Outside of an audited region, you actually have to write explicitly
- (NSArray<MyObj *> * _Nullable)foo:(NSError * _Nullable * _Nullable)error;
to avoid warnings about missing nullability type specifiers.
(_Nullable is the newer syntax used in Xcode 7 and replaces __nullable.)

typedef in cocoa blocks

I have a simple Blocks and typedef doubt.
Consider the following codes, I've some typedef and two methods, second one is commented out. My doubt is regarding the first one. Should I use this one? Any issues or something that may arise in future?
typedef void (^MySuccessBlock)(MyServiceResponse *response);
typedef void (^MyFailureBlock)(NSError *errorObject);
#property (nonatomic, copy)MySuccessBlock mySuccessBlock;
#property (nonatomic, copy)MyFailureBlock myFailureBlock;
//SHOULD I USE THIS?
- (void)myServiceWithCompletion:mySuccessBlock
failure:myFailureBlock;
//- (void)myServiceWithCompletion:(void (^)(MyServiceResponse *response))completion
// failure:(void (^)(NSError *errorObject))failure;
In Implementation file:
//If 1st one is used:
- (void)myServiceWithCompletion:aSuccessBlock
failure:aFailureBlock{
self.mySuccessBlock = aSuccessBlock;
self.myFailureBlock = aFailureBlock;
....
}
You should use this:
- (void)myServiceWithCompletion:(MySuccessBlock)successBlock
failure:(MyFailureBlock)failureBlock;
Note the capitals at the beginning of MySuccessBlockand MyFailureBlock as in your typedef.
In fact, when you declare:
- (void)myServiceWithCompletion:mySuccessBlock
failure:myFailureBlock;
the problem comes from the fact that you don't specify the type of your parameters 'mySuccessBlock' and 'myFailureBlock'. So they are treated as default type id because:
If a return or parameter type isn’t explicitly declared, it’s assumed
to be the default type for methods and messages—an id.
It is like if you write:
- (void)myServiceWithCompletion:(id)mySuccessBlock
failure:(id)myFailureBlock;
id type is a pointer, and blocks are pointers, so there is no compile problem. But you can have execution problem because of black's parameters and return value!
The typedef declaration provides a way to create an alias that can be used anywhere in place of a (possibly complex) type name. See
You should use the typedef in the following way.
- (void)myServiceWithCompletion:(MySuccessBlock)aSuccessBlock
failure:(MyFailureBlock)aFailureBlock;

ObjC category on typedef class: "cannot find interface declaration for 'typedefname'"

This code gives me the error Cannot find interface declaration for 'OGWView':
typedef SKNode OGWView;
#interface OGWView (Category)
#end
Why? Shouldn't the category work just as well with a typedef name?
PS: I know I can fix this with a #define (or by using the original class name) but I'm really more interested in understanding why it isn't possible to create a category on a typedef class.
I believe the answer to this question is that you have 2 different kinds of symbol. I believe the typedef is an object and you are trying to use it as a class symbol.
depending on the order of declaration you get different warnings suggesting as much:
typedef NSObject Foo;
#class Foo;
yields:
Redefinition of forward class 'Foo' of a typedef name of an object type is ignored
#class Foo;
typedef NSObject Foo;
yields:
Redefinition of 'Foo' as different kind of symbol
Replace typedef with #compatibility_alias
#compatibility_alias SKNode OGWView;

iOS 4 - Using blocks as a member of a class

I was hoping someone could help me understand the syntax of blocks when used as members of a class. I have some code that's actually working just fine:
#class Structure;
typedef void (^StructureDeleteCallback)(Structure *);
#interface StructureListDelegate : NRFCTableDelegate
{
StructureDeleteCallback _structureDeleteCallback;
}
#property (nonatomic, copy) StructureDeleteCallback structureDeleteCallback;
#end
This works, but I would like to understand the syntax of the typedef statement; and whether or not it's actually required to use typedef.
What I've read says that using typedef in this situation is recommended because it makes the code a lot clearer; but I've been unable to get it to compile at all when trying to do this without typedef. My understanding of typedef was that the syntax was basically:
typedef [actual type] [new name for type];
Such as:
typedef double CLLocationDegrees;
But the syntax of my typedef statement doesn't match this. So my questions are:
How can the syntax of my typedef
statement be so different from other
typedef statements / what does the syntax I'm using actually mean to the compiler?
Is it possible to
have a block as a member of a class
without using typedef?
I myself have asked a question along the lines of yours here: Block references as instance vars in Objective-C
See my answers here and here.