Type arguments cannot be applied to non-class type 'id' - objective-c

I am new to ObjectiveC and have been working for few years in Swift. Therefore, I don't understand the below explained error in Xcode:
Type arguments cannot be applied to non-class type 'id'
My Protocol:
#protocol ExampleProtocol<NSObject>
#required
-(NSString *)title;
-(NSString *)album;
#end
My implementation in the MyService.h file:
#interface MyService : NSObject
#property (nonatomic, assign, readwrite) id<ExampleProtocol> delegate;
#end
The error occurs in the line:
> #property (nonatomic, assign, readwrite) id<ExampleProtocol> delegate;
Additionally:
I have imported the required file .h in which the ExampleProtocol code is located in the MyService.m file
Added the #class ExampleProtocol; in my MyService.h file at the top.
Also tried:
Creating a Swift protocol with #objc and : class imported over the app-Bridging.h gives me the same result with the same error message.
Clean build
Clean build folder (removed derived data)
The only thing that did work was to remove the line from the public interface to the private. This doesn't make sense. I wan't to set the delegate from another class and creating a public setter which set the private delegate is ugly workaround.
Any suggestion would be helpfull. I would like to understand why this happens. There are a lot of other protocols in my project written in ObjectiveC which work fine.

ExampleProtocol is a protocol, not a class. You don't need it if you import the header. If you don't import the header, it should be #protocol ExampleProtocol;

Related

"property has a previous declaration" error in class extension: bug or feature?

In Objective-C you can generally re-declare a readonly property as readwrite in a class extension like this:
#interface PubliclyImmutablePrivatelyMutableClass : NSObject
#property (readonly, nonatomic) SomeStateEnum someState;
#end
// In "PubliclyImmutablePrivatelyMutableClass+Private.h"
// or "PubliclyImmutablePrivatelyMutableClass.m"
#interface PubliclyImmutablePrivatelyMutableClass()
#property (readwrite, nonatomic) SomeStateEnum someState;
#end
// In "PubliclyImmutablePrivatelyMutableClass.m"
#implementation PubliclyImmutablePrivatelyMutableClass #end
If, however, I introduce a property in a class extension as readonly and try to re-declare it as readwrite in a second one, Xcode 10’s Clang gives me a compiler error:
#interface ClassWithPrivateImmutableInternallyMutableProperty : NSObject
// any public API
#end
// In "ClassWithPrivateImmutableInternallyMutableProperty+Private.h"
#interface ClassWithPrivateImmutableInternallyMutableProperty()
#property (readonly, nonatomic) SomePrivateStateEnum somePrivateState;
#end
// In "ClassWithPrivateImmutableInternallyMutableProperty.m"
#interface ClassWithPrivateImmutableInternallyMutableProperty()
#property (readwrite, nonatomic) SomePrivateStateEnum somePrivateState; // error: property has a previous declaration
#end
#implementation ClassWithPrivateImmutableInternallyMutableProperty
// other API
#end
Now I wonder:
Is the compiler error a bug/regression in Clang or a deliberate feature?
If it’s a bug, is there another workaround than manually implementing the setter?
I believe that this is correct behavior from the compiler.
In the second example you are using two class continuation categories with the same name () to declare the same property on two occasions. It is effectively the same as declaring the same property name twice in the same extension.
Note that this differs from the first example, in which the property is declared first in the header and then re-declared in a single class continuation category named ().
If I am right, then the answer is to mark the '+private' class extension with a name like (Private) instead of ():
#interface ClassWithPrivateImmutableInternallyMutableProperty(Private)
And also if you have any implementation for the private extension:
#implementation ClassWithPrivateImmutableInternallyMutableProperty(Private)
I hope that helps!

Why do I have to declare a property specified by a protocol in the header, and not the class extension (implementation)

So I have a protocol, which requires a property to be declared:
#protocol MyProtocol <NSObject>
#property MyView *myView;
#end
and an object who conforms to it:
#interface MyViewController : NSViewController <MyProtocol>
#end
However, if I declare the property (specified in the protocol) inside of the implementation file (the class extension):
#interface MyViewController()
#property MyView *myView;
#end
I get this error:
Illegal redeclaration of property in class extension
'MyViewController' (attribute must be 'readwrite', while its primary
must be 'readonly')
There appear to be two main SO threads that address this:
attribute must be readwrite while its primary must be read only
and
Can't declare another window
The first answer doesn't explain anything
The second answer says that you can actually circumvent this error by declaring the property inside of the header; and alas
Header
#interface MyViewController : NSViewController <MyProtocol>
#property MyView *myView;
#end
Implementation
#interface MyViewController()
#end
This builds with no errors.
I also know that when you declare a #property inside of a protocol, it doesn't automatically get synthesized.
So if I wanted to keep the #property declaration inside of the implementation, I would have to #synthesize it. And this also works.
So my question is, why does declaring the #property inside of the header vs the implementation file matter if the #property was initially declared inside of a protocol?
Without the protocol, I thought the only difference was making the #property public or private. But clearly there are other things that happen/don't happen if you declare a #property in the header vs the implementation file
Don't declare there property anywhere in your class. It's already declared in the protocol.
Don't put #property MyView *myView; in either the MyViewController.m or MyViewController.h files.
To fix the warning about "auto property synthesis", you simply add:
#synthesize myView = _myView;
to the MyViewController implementation or add explicit getter and setter methods as needed.

Error in protocol declaration

I am getting an error as:
protocol declaration not found
I couldn't find out what's the reason. Now I am using ARC. I doubt that the issue is due to that. Here is the code I am using for protocol declaration
//This is the first page we are declaring the Delegate
.h
#protocol ImageDelegate
#optional
-(void)ImageSelected:(UIImage *)ImageName;
#end
#interface GetAddedMovieList : UIViewController<UITableViewDataSource,UITableViewDelegate>{
id<ImageDelegate> delegate;
}
#property(nonatomic, strong)id<ImageDelegate> delegate;
#end
.m
#synthesize delegate;
//This is page in which i tried to set delegate. Here I am getting the error.
#interface ImageEnlarge : UIViewController<ImageDelegate>{
IBOutlet UIImageView *imgEnlarge;
NSString *stgImageName;
}
I see several (possible) issues in your code.
#property(nonatomic, strong)id<ImageDelegate> delegate;
delegates should be weak. GetAddedMovieList do now own the delegate by any mean and therefore shouldn't have an impact on its life cycle.
#synthesize delegate = delegate;
By default #synth uses either ivar_ or _ivar lately. With the latest LLVM #synth aren't necessary anymore btw, neither ivars.
#synthesize outside an #implementation ?
Have you checked your #imports?
It's probably an import loop. Do you #import the correct file for where you are using the protocol? And are you importing that file in the protocol file? If so then you have an import loop. Use forward declaration in the protocol's header instead and that should solve it. (#class)
You are putting an #interface on a .m file, are you trying to create a private #interface? With an IBOutlet declared there?
After seeing your edit, I am guessing there is only missing an import on the .h of your ImageEnlarge class.
Try like it.
#protocol ImageDelegate<NSObject>
#optional
-(void)ImageSelected:(UIImage *)ImageName;
#end
And also add this property.
#property(nonatomic,assign)id<ImageDelegate> delegate;
I think it will be helpful to you.

"Expected a type" error pointing to the return type of a method

I've attempted to compile, but every time I do, one method throws a strange "expected a type" error. I have a method in the header:
-(ANObject *)generateSomethingForSomethingElse:(NSString *)somethingElse;
The error points at the return type for this method. I've imported ANObject into the header using #import "ANObject.h" and ANObject is compiling fine..
Why is this happening?
This is to do with the order that the source files are compiled in. You are already probably aware that you can't call a method before it is defined (see below pseudocode):
var value = someMethod();
function someMethod()
{
...
}
This would cause a compile-time error because someMethod() has not yet been defined. The same is true of classes. Classes are compiled one after the other by the compiler.
So, if you imagine all the classes being put into a giant file before compilation, you might be able to already see the issue. Let's look at the Ship and BoatYard class:
#interface BoatYard : NSObject
#property (nonatomic, retain) Ship* currentShip;
#end
#interface Ship : NSObject
#property (nonatomic, retain) NSString* name;
#property (nonatomic, assign) float weight;
#end
Once again, because the Ship class has not yet been defined, we can't refer to it yet. Solving this particular problem is pretty simple; change the compilation order and compile. I'm sure you're familliar with this screen in XCode:
But are you aware that you can drag the files up and down in the list? This changes the order that the files will be compiled in. Therefore, just move the Ship class above the BoatYard class, and all is good.
But, what if you don't want to do that, or more importantly, what if there is a circular relationship between the two objects? Let's increase the complexity of that object diagram by adding a reference to the current BoatYard that the Ship is in:
#interface BoatYard : NSObject
#property (nonatomic, retain) Ship* currentShip;
#end
#interface Ship : NSObject
#property (nonatomic, retain) BoatYard* currentBoatYard;
#property (nonatomic, retain) NSString* name;
#property (nonatomic, assign) float weight;
#end
Oh dear, now we have a problem. These two can't be compiled side-by-side. We need a way to inform the compiler that the Ship* class really does exist. And this is why the #class keyword is so handy.
To put it in layman's terms, you're saying, "Trust me man, Ship really does exist, and you'll see it really soon". To put it all together:
#class Ship;
#interface BoatYard : NSObject
#property (nonatomic, retain) Ship* currentShip;
#end
#interface Ship : NSObject
#property (nonatomic, retain) BoatYard* currentBoatYard;
#property (nonatomic, retain) NSString* name;
#property (nonatomic, assign) float weight;
#end
Now the compiler knows as it compiles BoatYard, that a Ship class definition will soon appear. Of course, if it doesn't, the compilation will still succeed.
All the #class keyword does however is inform the compiler that the class will soon come along. It is not a replacement for #import. You still must import the header file, or you will not have access to any of the class internals:
#class Ship
-(void) example
{
Ship* newShip = [[Ship alloc] init];
}
This cannot work, and will fail with an error message saying that Ship is a forward declaration. Once you #import "Ship.h", then you will be able to create the instance of the object.
I found this error hapenning when there is circular dependency on the headers. Check if the .h file where you declare this method is imported in ANObject.h
You basically add
#class ANObject;
before #interface!
So, for some reason I was getting this error while trying to set a method with an enum type in the parameters. Like so:
- (void)foo:(MyEnumVariable)enumVariable;
I had previously used it like this and never had an issue but now I did. I checked for circular dependency and could find none. I also checked for typos multiple times and no dice. What ended up solving my issue was to adding 'enum' before I wanted to access the variable. Like so:
- (void)foo:(enum MyEnumVariable)enumVariable;
{
enum MyEnumVariable anotherEnumVariable;
}
Usually when I see an error like this it's because I have a typo on a previous line, such as an extra or missing parenthesis or something.
It may sound stupid, but wrong shelling or wrong use of uppercase/lowercase letterwrong case this.
I got this message, when the variable type was misspelled. See below this below
e.g.
-(void)takeSimulatorSafePhotoWithPopoverFrame:(GCRect)popoverFrame {
instead of.....
-(void)takeSimulatorSafePhotoWithPopoverFrame:(CGRect)popoverFrame {
Strangely enough, changing the order of my imports has fixed this in the past... Try moving the import to the bottom after all your other imports.
I solved it by adding #class class_name to the .h file

Error with #synthesize'd property

I have two classes, GameCharacter and Skeleton. One of the properties on GameCharacter is a delegate of type id:
#interface GameCharacter : GameObject
#property (nonatomic, retain) id<GameplayLayerDelegate> delegate;
#end
In the implementation, I have delegate synthesized.
The Skeleton class is pretty straightforward:
#import "GameCharacter.h"
#interface Skeleton : GameCharacter
#end
However, I am unable use delegate in Skeleton without declaring it separately. I receive an error from the compiler. As I understand it, it should inherit it from GameCharacter. What's the problem?
It will inherit from GameCharacter just like any other property or method just make sure you are using self.delegate since using delegate by itself will attempt to access a private ivar (which would be generated in your case).