I wonder if I'm doing something completely stupid here... I'm clearly missing something. I've gotten used to the pattern of defining properties of a custom class, however I seem to be hitting a point where extended classes do not recognize new properties. Case of point, here's my header file:
#import <UIKit/UIKit.h>
#import "MyTableViewController.h"
#interface MyRootController : MyTableViewController {
NSMutableArray *sectionList;
}
#property (nonatomic, retain) NSMutableArray *sectionList;
#end
Now, for some reason that "sectionList" property is not turning green within my interface file (ie: it's not being recognized as custom property it seems). As a result, I'm getting all kinds of errors down in my implementation. The first is right at the top of my implementation where I try to synthesize the property:
#import "MyRootController.h"
#implementation MyRootController
#synthesize sectionList;
That synthesize line throws the error "No declaration of property 'sectionList' found in the interface". So, this is really confusing. I'm clearly doing something wrong, although I can't put my finger on what.
One thought: I am extending another custom class of my own. Do I need to specify some kind of super-class declaration to keep the architecture from getting sealed one level up?
Drat, it was a pathing issue. I still haven't figured out quite how XCode decides what folder to place new files into... and when two joined files end up in different folders, things don't work. Thanks for the reply, fbrereto.
Related
I have subclass of UIViewController called FullScreenViewController which has a property of type ImageScrollView which is subclassed UIScrollView object. The implementation and interface look as follows:
FullScreenViewController.h
#import <UIKit/UIKit.h>
#class ImageScrollView;
#interface FullScreenViewController : UIViewController
{
ImageScrollView *_scrollView;
}
#property(nonatomic, retain) ImageScrollView *scrollView;
#end
FullScreenViewController.m
#import "FullScreenViewController.h"
#import "ImageScrollView.h"
#implementation FullScreenViewController
#synthesize scrollView = _scrollView;
...
#end
now I subclass FullScreenViewController, and I try to access any properties from the ImageScrollView property and I keep getting the error message: "Property cannot be found". When I add ImageScrollView.h to the subclass, it works, but I'm not understanding this. I've already added ImageScrollView.h in FullScreenViewController, why should I have to add it again?
UPDATE: Rather than using a forward class declaration, I've included ImageScrollView.h in FullScreenViewController.h. I'm a little confused as to why I've ever use a forward declaration versus just including the .h file?
The reason you need to add it is you only have a #class declaration in your FullScreenViewController.h file. That only declares variable of type ImageScrollView* as pointers to object of class ImageScrollView. It does not give you access to the properties of ImageScrollView. To get access to methods and properties specific to ImageScrollView, you need to include the #interface declaration of ImageScrollView, which I assume is in your ImageScrollView.h file.
Given the header:
#interface FullScreenViewController : UIViewController
{
ImageScrollView *_scrollView;
}
#property(nonatomic, retain) ImageScrollView *scrollView;
#end
a forward declaration #class ImageScrollView is all that's needed. This tells the compiler that there is an objc class named ImageScrollView.
Of course, with a forward declaration, the interface is not visible where you need to use it unless you also #import ImageScrollView where you use it.
now I subclass FullScreenViewController, and I try to access any properties from the ImageScrollView property and I keep getting the error message: "Property cannot be found". When I add ImageScrollView.h to the subclass, it works, but I'm not understanding this. I've already added ImageScrollView.h in FullScreenViewController, why should I have to add it again?
ImageScrollView's declaration is not visible to the subclass FullScreenViewControllerSubclass. ImageScrollView.h is visible only where #imported. FullScreenViewController.m is not visible to FullScreenViewControllerSubclass.m. Therefore, you must write another #import in FullScreenViewControllerSubclass.m to use ImageScrollView there.
UPDATE: Rather than using a forward class declaration, I've included ImageScrollView.h in FullScreenViewController.h. I'm a little confused as to why I've ever use a forward declaration versus just including the .h file?
Use forwards for fast build times and sane, controlled dependency structures. This is a very time consuming problem to undo. And this problem gets much worse as the size of your programs and libraries increase:
Would you prefer a change to a header in a medium sized project to require recompilation of 50 sources with an average preprocessed input of 150,000 lines per translation, or would you favor that change to affect 6 sources with an average preprocessed input of 40,000 lines per translation? The difference here is that small change takes the incremental rebuild from seconds to minutes to complete, depending on how you have structured your dependencies and imports.
Have you tried accessing it using the alias _scrollView or scrollView.you should access it using _scrollView and see if u have imported the file in .m or .h as #class won't suffice.
I am working on an iPhone game using the cocos2d framework, and recently encountered a problem I can't seem to solve. After adding a new class to my project and doing some work in it, I tried to compile my code and several of the classes I hadn't even touched broke. It seems like those classes just forgot how import external classes. I am getting the error up there in several of my classes, but here is one example:
#import "cocos2d.h"
#import "XZombie.h"
#import "WayPoint.h"
#import "XBuilding.h"
//#class XBuilding;
#interface Hoarde : CCNode
{
float _spawnRate;
int _totalXombies;
NSMutableArray *_path;
XBuilding *_target;
NSMutableArray *_zombies;
bool _zombiesReset;
}
#property (nonatomic) float spawnRate;
#property (nonatomic) int totalXombies;
#property (nonatomic, retain) NSMutableArray *path;
#property (nonatomic, retain) XBuilding *target;
#property (nonatomic, retain) NSMutableArray *zombies;
#property (nonatomic, assign) bool zombiesReset;
- (id) initWithZombieCount:(int)totalXombies Target:(XBuilding *) target SpawnRate:(float)spawnrate;
- (void) resetZombies;
#end
I get the error on the line that reads XBuilding *_target;
If I uncomment the #class XBuilding;, the error goes away, so while that doesn't really solve my problem, it gives me a tool to work around it.
If I do the #class trick for all the files I am having a problem with, I can work around that. The thing is, I get a new - but similar - error besides the specifier-qualifier-list one. Some lines of code give me Expected a ')' before *token or Expected a ';' before *token. Those lines usually gave me the previous error as well, so the #class trick worked as well, but I haven't the slightest idea why this stuff is doing what it's doing. I read somewhere (the cocos2d forums, I think) that renaming the .m files to .mm might do the trick, but it didn't for me.
So, while I can continue working on my project, I would really like to know how on Earth to avoid stuff like that in the future...
Please check whether there is circular dependency, for example, importing ClassB.h in ClassA.h and vice versa. This is the typical scenario where "Expected specifier-qualifier-list before..." error occurs.
I suggest to use only #class in your headers files except:
#importing the super class
#importing the protocols your class implements
The header files should be #imported in your implementation files.
"The Objective-C Programming Language" says:
The #class directive minimizes the amount of code seen by the compiler and linker, and is therefore the simplest way to give a forward declaration of a class name. Being simple, it avoids potential problems that may come with importing files that import still other files. For example, if one class declares a statically typed instance variable of another class, and their two interface files import each other, neither class may compile correctly.
More reference:
#class vs. #import
http://www.iphonedevsdk.com/forum/iphone-sdk-development/54417-expected-specifier-qualifier-list-before-xxxappdelegate-error.html
Say we have parent class
ParentViewController.h
#interface ParentViewController
....
#end
ParentViewController.m
#interface ParentViewController()
- (NSArray *)selectedItems;
#end
#implementation ParentViewController
.....
#end
And then we subclass it
ChildViewController.h
#interface ChildViewController : ParentViewController
....
#end
ChildClassViewController.m
#implementation ChildViewController
- (void)doSomething
{
// XCode Warning Flag on this line
NSUInteger count = [self selectedItems];
.....
}
XCode will set Warning flag at the commented line and says that "Instance method '-selectedItems' not found (return type defaults to 'id').
Yes I know that in ObjC there is no such thing as private methods, but using an empty category kind of gives the ability to do so. But somehow it does not get inherited by subclasses.
I usually fix it by moving the method from ParentViewController.m to ParentViewController.h. This feels weird, I loose the ability to make the method private just because I need to subclass it.
Now my question is:
Why does the parent subclass cannot find those methods that is declared in its category at the .m file?
Is there a way to remove the Warning Flag but without losing the ability to keep the method private.
Hopefully someone with more experience will be able to help explain this annoying issue.
First, note that your "empty category" isn't a Category at all, it's a Class Extension. Class Extensions very similar to categories but they're new in Objective C 2.0, and they differ slightly in their use. Primarily, the compiler will warn you if you don't implement a method in a Class Extension, but it won't with a Category. Anyways, on to the issue at hand...
Privacy in Objective-C is all about visibility. If the compiler can't see see the declaration of a method that's being used, you'll get a warning. Note that if you were to implement your subclass in the same file as your Class Extension, the compiler won't warn you because it can see the declaration.
Therefore, If you want to use "private" methods in subclasses, you just need some way of showing the compiler that those methods exist. My favorite pattern is to declare the private methods in a Category in a separate file (like MyClass_private.h). You then only import that interface into the implementation files of the base class and any derived classes that need to see it.
I have a solution, but generally I would advise against it. if you compile the file with -w (suppress all warnings), the warning goes away. I do not know if there is a specific warning flag for this message, if there was, you could use #pragma GCC diagnostic ignored "-Winstance-method-not-found", but I can't find it, sorry.
I've gotten to a point where I'm starting to think this is may actually be a bug in Xcode, but to be sure, I'm asking it here. I was working on my app that uses MapKit and CoreLocation, but at some point I started getting the warning "Property 'coordinate' requires method '-coordinate'". At first I thought I was doing something wrong, as I did use the property coordinate for an MKPointAnnotation, but after I commented that out, the warning remained.
In fact, after I've commented out pretty much everything, I still get the warning. It tells me the file name and line number (the line with #end), but if I search for coordinate in that file, there aren't any results. The .h doesn't declare the property either, so I'm really lost as to where this error is coming from... I can provide you with code, of course, but I've commented so much stuff out that it doesn't really make any sense to post it here. Just a few memory management methods without any actual content other than sending a message to super...
Xcode is correct in telling you that you're required to implement -coordinate. This is a non-optional method of the MKAnnotation protocol.
http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MKAnnotation_Protocol/Reference/Reference.html
coordinate The center point (specified
as a map coordinate) of the
annotation. (required) (read-only)
#property (nonatomic, readonly)
CLLocationCoordinate2D coordinate
I believe the reason you can't synthesize coordinate is not because you didn't declare the property, but because you haven't told the compiler what storage to use.
Adding
CLLocationCoordinate2D coordinate;
to the fields (variables) section of your class interface will give the compiler the storage it is looking for.
Or you can point the compiler to other storage using this syntax:
#synthesize coordinate=myCoordinateVariable;
But none of that really matters, because you don't have to use synthesize.
Just implement the method yourself! The required part is readOnly so you only need to implement the getter.
-(CLLocationCoordinate2D)coordinate {
return myCoordinate;
}
#property and #synthesize are primarily shortcuts. #synthesize just says to the compiler - "Implement these accessors if I haven't". But normally you declare a property like this, right?
#implementation MyClass : NSObject {
NSString *someString;
}
#property (nonatomic, retain) NSString *someString;
and then you synthesize it. #synthesize creates the appropriate implementations for the declarations implied by #property:
-(NSString *)someString;
-(void)setSomeString:(NSString *);
and uses the storage you provided when you declared the instance variable, NSString *someString.
Incidentally, in Xcode 4 #synthesize automatically creates storage for you if it doesn't already exist.
I've had the same problem for over a year on one of my apps. Nobody has ever been able to offer an explanation. I just got to the point of adding a mapview to my latest app and had only gotten as far as adding the MapKit Framework to the project, declaring support for the MKMapViewDelegate and MKAnnotation protocols then I did the #imports for MapKit/MapKit.h and MapKit/MKAnnotation.h. Build the app and Bang! there's the warning.
So, I commented out the MKAnnotation protocol declaration and like magic the warning went away. The only conclusion I can come to is that this is an Xcode issue.
Very strange this problem. I just added the following line as Ball suggested and my warning disappeared.
#synthesize coordinate=myCoordinateVariable;
Thanks Ball for the info.
I've been working on an iOS project for some time but now I have an error which really confuses me and as long as I can't fix it I can't even compile the project so I need some serious help!
It all began with an:
error: expected '=', ',', ';', 'asm' or 'attribute' before 'protocol'
in PHCluesListViewController.h. The class had not been changed for a long time and what I was working on at the moment of the error had nothing to do with that particular class.
This is what it looks like:
#import <UIKit/UIKit.h>
#protocol PHCluesListViewControllerDelegate;
#class PHClueListTableViewController;
#interface PHCluesListViewController : UIViewController {
IBOutlet PHClueListTableViewController *clueListTableViewController;
id <PHCluesListViewControllerDelegate> delegate;
}
- (void)mapDelegate;
#property (nonatomic, assign) id <PHCluesListViewControllerDelegate> delegate;
#end
#protocol PHCluesListViewControllerDelegate
- (void)mapUp:(PHCluesListViewController *)controller;
#end
There are no syntax errors and there is nothing wrong with the code in it's context either. Later I would learn that if you were to take away all the code from the header file the error would move to a another random header file or if you were to import another header the error would move to this header.
I've tried to restart xcode, to move the project to a new one, to rewrite the code to a new file and to move the project to another computer with another version of xcode - but with no luck.
I am able to run other xcode-projects on my computer.
It seems to me that xcode are trying to compile my headers in this specific project in some unwanted fashion.
Help would be highly appreciated, thanks on before hand!
---------- EDIT!!! ----------
Thanks for the fast respond!! Although I've found the answer.
The error was a "d" written out of bounds of the implementation in a totally different file/class. Found it by chance...
If something similar would happen to anyone else; check for something like a letter written after #end or before #interface/#implementation or anything else that would "cut the edges" of the common syntax.
It's difficult to find the reason for an error like this and I'm a little bit surprised that I found it so quickly among 80 files (only 4.5 hours).
Good luck!!
You're defining #protocol PHCluesListViewControllerDelegate twice. Also, if mapUp is required to be implemented, you might want to add the #required keyword.