Note: This is similar to this question but it is not the same. I promise.
I have a series of table views that call upon a modal view for sorting the table's contents. To do this, I set up a simple protocol in one table view controller's header file and it worked great. I then copied this protocol over to my other table view controllers and got this warning:
Duplicate protocol definition of 'ModalViewDelegate' is ignored
Now I realize it is just a warning, but I would rather not see it every time I compile. To get rid of the warnings, I imported the header file in which the protocol was originally defined. Once again, I was not completely satisfied. It seems sloppy to import the header file to every table view just so I can use the protocol without warnings.
If you have read this far, I thank you. My questions are 'Why is this happening? Is there a better way of getting rid of this warning while still using the same protocol?'
Is there a better way of getting rid of this warning while still using the same protocol?
The compiler needs to know about the protocol in order for you to refer to it. There's two ways you can make that happen: import the header where the protocol is declared into the files where you're using it, or make a forward declaration of the protocol in those files: #protocol MyProtocol;. The second is really only useful when protocols need to refer to each other (to avoid circular imports); if a class needs to adopt the protocol, it needs to see the declarations of the methods in the protocol, which means it needs to see the protocol declaration itself, i.e., the header.
It seems sloppy to import the header file to every table view just so I can use the protocol without warnings.
This is not sloppy, it's the way things work. It sounds like it may make sense for you to put the protocol declaration into its own header and import that wherever it's needed.
I discovered a similar warning where a #protocol was defined within the header of a class. Breaking that protocol out into its own .h and importing it elsewhere fixed it.
Related
So I am using the new #import module syntax introduced with the latest Xcode - I still wonder where the best place is to put them. Before, I would place library imports and very important categories in the .pch file, but now that's not necessary anymore (at least not for the native frameworks). My first idea was to create a modules.h file and do all the imports there, then include that modules.h file in the AppDelegate - but this doesn't seem right. Also, importing in the first place you need it doesn't make sense either, since you might use it in different places.
This is in fact a question about "best practices" which is - of course - a little subjective. But I think this affects a lot of people and the overall project structure. So please share your solution to this.
it sounds like you weren't doing it the best way before, In general you want as few symbols available at any one time. For a few different reasons:
less likely to make a mistake with symbols that have the same name but different values, or types... and for reasons that the compiler has to import less crap into each compilation unit.
I am not an expert on how #import has changed the compiler semantics of preprocessing and compiling, but I suspect you should still basically import things as close to the point that they will be used as possible.
I generally will not generally import any class's headers into another class's .h file.
in a .h I will forward declare any classes with #class SomeCLass and only include enough headers to satisfy the c/c++ types that I use as ivar/properties. The only exception to that being if I need to include a superclass's header or another .h for a protocol.
the rest of the includes go into the .m
I like to keep my pch pretty spartan, but if you have some utility categories or a widely used library you could include stuff in there, I tend not to... but in a smaller project you probably wont run into problems... you will run into indexing problems in projects with hundreds of source files, especially if you have some Objective-C++ units. That will end up hurting code completion and live syntax checking.
Screenshots
I'm having quite a hard time setting up a category on a class I made. From what I've read, Objective-C allows you to create a category on any class, not just closed-source ones. (It honestly wouldn't make sense any other way.)
Of course I can add the category messages to the actual class file, but I want to keep them separate (as the category is an uncommonly special use of a class that can be used very generally). I want to share the class, but keep the category private... anyway.
I've stripped down the category to just show the issue at hand. I (currently) get four errors on the first category message. The number of errors I receive on that line is directly proportional to how many times it is references, but it is not an even rise. Does anyone know what could be causing this?
Your Resources.h file, which is imported by ByteCollection.h, imports ByteCollection+words.h. So when ByteCollection+words.h imports ByteCollection.h, this results in a circular dependency†. The simplest way to break a circular dependency is to move one of the imports to the implementation file rather than the header. It looks like this should be possible with Resources.h.
† You might be wondering, why is it a problem if you have a circular dependency? Well, the #import directive literally just textually includes the file you specify, just like if you copy-pasted. It also intelligently doesn't include a file twice, because that would create duplicate code. But this means that when File A says "I want File B to go before me" and File B says "I want File A to go before me," one of them is going to be disappointed, and that leads to errors like the one you're getting here.
I am implementing a action sheet and found that the code works even without including the protocol in the header file. Is there a impact in no including it?
Thanks
Zhen
There is no runtime impact*, but including the protocol specification:
allows the compiler to verify that you have implemented all required methods (e.g. forgetting implementing -tableView:cellForRowAtIndexPath: with a UITableViewDataSource will give a warning), and
allows the library writer to restrict types to delegates that can surely respond to the expected methods (e.g. assigning a non-UIActionSheetDelegate to an id<UIActionSheetDelegate> will give a warning)
(*: Technically the list of protocols can be queried in runtime, so including it may change some runtime behavior, but this situation is rare.)
After several months of coding in Objective-C, I completely understand when I need an #import, how import statements cascade (ripple?), and when to use forwarding classes. I do not know how to aggregate imports to get them inside of <> instead of in quotes (although maybe that's just for frameworks)...
The problem is that I'm making a huge mess. I come from Java (and the heavy-handed IDE), so I just add imports as I see fit. Sometimes I add them to the interface, but since that's usually not necessary, I just add them to the top of the .m in question.
Today I started thinking: there must be some rules of thumb on how to organize this stuff. In fact, since Objective-C is a C superset, there are rules of thumb for everything, but I don't know them. How should I organize my imports? Particularly:
When should I import in the .m?
When should I import in the .h?
Should I create .h files just for the sake of importing them (i.e., header files that just have imports in them)? If so, any hints on organizing that?
This is just a general idea of what I'm trying to figure out.
The <....> syntax is indeed just for frameworks. That doesn't mean you shouldn't create a framework to contain the core logic of your application though. Often this is a useful thing to do if you:
a) Need to provide support for loadable bundles that want to invoke aspects of your application logic (the bundle links to the framework, so does your application)
b) Write multiple apps that share the same core logic
Your question is somewhat subjective and you will get developers who argues both ways, but a convention I follow is:
Never import class definitions in the .h file, unless you are subclassing it. Use forward #class directives for everything in the .h.
Only import class definitions into a .m as you find you need to use that class in the implementation.
Generally speaking, the .h does not need access to the class definition of its ivars, method arguments or return values. It only needs to know that they are classes, which is what #class allows you to do. It does need access to the class definition of anything you're subclassing, adding a category to, or (obviously) implementing a protocol for.
Forget about whether <...> is for frameworks or what. <...> checks the system header search path, while "..." checks the current dir in addition to. One thing to remember however, is that the <CoreFoo/CoreFoo.h> declaration is handled a little differently on the apple platform, but only as it relates to apple frameworks: CoreFoo.framework/Headers/CoreFoo.h is matched to CoreFoo/CoreFoo.h
When imports are inside <> instead of quotes, all this means is that you are importing something from a framework. In fact, when doing this, the import is typically in the style
#import <Foundation/Foundation.h>
The first Foundation, before the slash, is the name of the framework in question, and the second one is just a header file in that framework. That header file is just something like
#import <Foundation/NSObjCRuntime.h>
#import <Foundation/NSArray.h>
#import <Foundation/NSAutoreleasePool.h>
...
#import <Foundation/NSURLHandle.h>
including every file from that framework. You can do this too, and isn't a bad idea for components that need multiple imports (although in that scenario, you may want a separate public interface)
For the other stuff, following the rule of thumb that you want stuff to know about as little as possible, you only want to put the import in the header file if it's necessary (like for an ivar or superclass) but really it's a matter of taste.
I have an idea on how to do this, but I want to make sure I do it right....
I have five data classes. When I use one I typically use all of them (but not always).
Each class has a separate header file. I am getting sick of linking in each header file separately.
What is the best way resolve this issue?
Create a new header file called "DataFiles.h". Inside that, have your five #import statements. Then whenever you need the file classes, just #import "DataFiles.h".
Beware of circular dependencies.
(This is how Cocoa, Foundation, UIKit, CoreData, etc all behave. Notice that you just #import <Cocoa/Cocoa.h>, which imports everything else. Open up Cocoa.h and take a look)