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

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;

Related

What is proper way to forward declare NS_OPTIONS in Objective-C\C++

I'm generating bridges from cpp to swift using cpp-objcpp-objc chain and I need to generate NS_OPTIONS.
In ObjC I have it as follows:
#import <Foundation/Foundation.h>
typedef NS_OPTIONS(NSInteger, PhonebookPhoneOptions)
{
PhonebookPhoneOptionsOpt1 = 1 << 0,
PhonebookPhoneOptionsOpt2 = 1 << 1,
PhonebookPhoneOptionsOpt3 = 1 << 2,
PhonebookPhoneOptionsOpt4 = 1 << 3,
};
It is forward-declared in my another header
#import <Foundation/Foundation.h>
typedef NS_OPTIONS(NSInteger, PhonebookPhoneOptions);
//typedef NS_ENUM(NSInteger, PhonebookPhoneOptions);
#protocol PhonebookDataRefreshedCallback
- (void)onEvent:(PhonebookPhoneOptions)param;
When I use NS_OPTIONS forward declaration I'm getting following error:
With NS_ENUM forward it is as folows:
subprojects/controller/service-sbis-phonebook/phonebook/djinni/objc/phonebook/PhonebookDataRefreshedCallback.h:5:53:
error: unnamed enumeration must be a definition typedef
NS_OPTIONS(NSInteger, PhonebookPhoneOptions);
subprojects/controller/service-sbis-phonebook/phonebook/djinni/objc/phonebook/PhonebookDataRefreshedCallback.h:5:9:
error: declaration does not declare anything
[-Werror,-Wmissing-declarations] typedef NS_OPTIONS(NSInteger,
PhonebookPhoneOptions);
With NS_ENUM it is as follows:
subprojects/controller/service-sbis-phonebook/phonebook/djinni/objc/phonebook/PhonebookPhoneOptions.h:6:31:
error: typedef redefinition with different types ('NSInteger' (aka
'long') vs 'enum PhonebookPhoneOptions') typedef NS_OPTIONS(NSInteger,
PhonebookPhoneOptions)
subprojects/controller/service-sbis-phonebook/phonebook/djinni/objc/phonebook/PhonebookDataRefreshedCallback.h:5:28:
note: previous definition is here typedef NS_ENUM(NSInteger,
PhonebookPhoneOptions);
When it was used solely as structure field I got some combination of NS_ENUM\NS_OPTIONS in ObjC\ObjC++ that was working, but when I try to use it as a function argument - it doesn't compile in any of the variants. What is the correct way to do such forward declaration?
I don't think there's a way to forward declare these sensibly. Can't you simply pack the definition into a header file with no other content so it can be #included from just about anywhere? So, have a header file that contains nothing other than your enum, then include/import that from anything that needs it without pulling in any transitive dependencies.
If your problem is that NS_ENUM/NS_OPTIONS isn't available in pure C++, or rather, that #include <Foundation/Foundation.h> does not work there, try CF_ENUM/CF_OPTIONS instead, which are equivalent and defined in <CoreFoundation/CFAvailability.h>, which can be used from any of the C/C++/ObjC/ObjC++.
If that doesn't help you, please update your question to explain in more detail why you are trying to forward declare your enum type. As in, what specific problem arises as a result of not forward declaring the type? (provide minimal repro code)

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

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

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;

using #property for a class I implemented

I created two classes in objective c and I would like to use one of them as a property of the other. To be more concrete, one of the classes is a 'term' that contains an integer variable and an nsstring that acts as the variable. The other class is an 'expression' that has an nsmutable array as an instance variable that contains 'terms' as its objects. What I want to do is have add the possibility of having one of the terms have an 'expression' as a property to implement something like distributing over parentheses and substituting an expression for a variable. However, Xcode is telling me that 'expression' is not an acceptable type name despite the fact that I have imported my expression header file. I think I may have read somewhere that only foundation classes are available to use as properties. What can I do to add this class as an instance variable?
I suspect you have an import cycle, like this:
Expression.h
#import "Term.h"
#interface Expression : NSObject
...
Term.h
#import "Expression.h"
#interface Term : NSObject
...
Notice how each file imports the other? That won't work. Instead, you need to use forward declarations:
Expression.h
#class Term; // tell the compiler that Term is a class name
#interface Expression : NSObject
...
Term.h
#class Expression; // tell the compiler that Expression is a class name
#interface Term : NSObject
...
Then, in your .m files, you can safely import both .h files:
Expression.m
#import "Expression.h"
#import "Term.h"
#implementation Expression
...
Term.m
#import "Term.h"
#import "Expression.h"
#implementation Term
...
Although the above answers are also correct, in my case the problem which occured was "#end" was missing in prototype/interface declaration.

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.