About .h and .m files (how to manage) [closed] - ios

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
Hey experienced programmers!
Id like to ask you something about clean code :)
Id like to keep my code clean and make it nice, so thats my questions:
1)Where should I put #imports?
My principles: (and i dont think that they are good)
#import Frameworks should be always in .h
#import .h files should be always in .m
.h files should have only #class, not imports (excluding frameworks like UIKit, etc)
Delegates should be in .m
#interface ViewController() <UIAlertViewDelegate>
#end
2)Where should I put my instance variables?
Private and Protected variables must be in .m
Public must be in .h
3)Where should I put my methods?
Public in .h
Private in .m
(And yeah I know that my "Private methods" are not really private, just hidden)
(btw thats pretty obvious)
4)What about #defines?
Global - always in .h
Used only in that class - always in .m
5)Where should I put NSNotification global identifiers and how to organize them
#define NSNotificationDataSourceDidLoadData #"NSNotificationDataSourceDidLoadData" in .h file in the class that will send this notification
But ....
Apple has a lot of private things in .h file
In most cases my .h files are just.. EMPTY :)
A year ago I had another situation - everything was in .h, but I think it is bad also
What to do? What principles are you using?
Thank you!
Thats a questions about coding style, not about "how to make it compilable"

Here's how I do it:
The usual #import <Foundation/Foundation.h> or #import <UIKit/UIKit.h> go into the .pch file. No header or implementation file is doing these imports again (makes sharing code between iOS and Mac OS X a tiny bit easier).
In .h files:
Other .h files are only imported if absolutely necessary, for example because they define types other than classes (enums, structs, everything with a typedef) which are then used in the current .h file.
Classes are forward declared (#class Foo;) to avoid pulling in other .h files.
Interfaces only contain stuff that other classes may access! No private stuff here!
In .m files:
Include all the .h files you need. But not more ;-)
Private instance variables and properties are defined in a class extension (#interface Foo ()).
Private methods don't need to be "forward declared" any more, so don't do that.
In the rare case that a class has some stuff that a few classes should access but the "normal" users shouldn't, I create foo_protected.h headers with a class category that defines the "protected" methods.
A word on #defines: avoid them if possible. Use const variables or enums instead if possible, as the additional type information can help the compiler catch more mistakes this way. For example, using enums has the nice advantage that you get a warning if you've got a switch but didn't handle all the values of the enum. If you add a new value you'll get warnings everywhere you forgot to handle them which is something you don't get with #defines.

Personally, I think the answer is pretty simple. Now that instance variables can be declared in the #implementation, and properties and protocol adoptions can be declared in a class extension in the .m file, I don't put anything in a .h file that I don't absolute have to put there.

import Frameworks should be always in .h
No, why?
import .h files should be always in .m
That's pretty vague. And what if you need to import something in a header file? You want to subclass a class, what you do? #import "SomeClass.h" in the header.
.h files should have only #class, not imports (excluding frameworks like UIKit, etc)
Brainless. (Sorry, it really is. See the reasoning above.)
2)Where should I put my instance variables?
Since other classes really aren't supposed to access ivars (i. e. it is recommended not to make your ivars public), you can put them anywhere: the header is fine (and it's useful for compatibility with the v1.0 fragile runtime API), but you can get away with placing everything in the class extension as well.
3)Where should I put my methods?
You got this one right, pretty much.
4)What about #defines?
This is good too, as far as I'm concerned. Basically, put defines and enums to the place where they need to be visible.
Apple has a lot of private things in .h file
In most cases my .h files are just.. EMPTY :)
Well, even Apple isn't very consistent with their style. Be consistent.
Empty headers? If you don't need a header, don't use one. Use headers to provide interface for your classes, functions and type declarations.

Related

Correct way to include multiple header in Objective C

So far I have been importing the required .h files in the .h files of class where it is required.
I had read yesterday that this is the incorrect way to do it and I should forward declare the class in .h and then import it in .m However, I am confused what is the correct way to do this when it comes to large projects?
Since I will have a lot of imports in lots of files, this way it will make the code long in my opinion. Someone suggested me to create a BaseViewController class which subclasses UIViewController and add all my imports there, and all the UIViewController's that I will create will subclass BaseViewController and not UIViewController directly. This works, however I just want to know the correct way to do it.
Thanks in advance.
你可以这样做.为每一个模块创建一个.h文件,把需要用到的类导入到里面,需要引用时直接引入这个模块的.h文件使用就好.这样不用写过多的.h文件,也避免了pch的导入文件过多的情况.
you can do like this. Creat one .h fiel for everyModuel,and import you want .h file to this .h . And import this .h file to where if you want . But if something .h file is base,please import they to .pch file.
In fact, I find it a little too rampant. But, hopefully useful to you.
Simplest way to import header files in project is to create .pch file.
Create .pch and add classes header in .pch file which you want to import most frequently. Then there is no need to import those headers any of the .h and .m. They will available for them automatically.
Please refer this for how to create .pch file.
In Xcode, when you create a class, by default it will make .h and .m files of that class.
These two files are used to separate between the public and private parts of the class.
The .h file is a header file for public declarations of your class like an API, while the .m file is the private implementation.
You have to import somefile.h in somefile.m
Standard best practice for Objective-C is to forward declare classes in your .h header files and #import them in your .m implementation files. This reduces compile times and forces you to move dependencies to where they are actually required. The exception are base classes and protocols that your class inherits from. These need #imports in the header.
The Google Style Guide for Objective-C specifies a recommended order in which headers should be included in a .m implementation file. This is partly to stop headers from depending on other headers being included before them. The order goes:
Related header (e.g. MyClass.h)
Operating system headers (e.g. Foundation/Foundation.h)
Language library headers (e.g. stdlib.h)
Groups of headers for other dependencies
In general, many #imports and/or forward declarations making your code too long may be an indication that you should refactor to reduce dependencies between classes. Ideally the number of dependencies should be low, though ultimately this depends on the situation.

What is the difference between the #import "" (embedded header file) in the .h and .m files?

This is an interview.
There are some answers existing:
Uses #Class in .h file is enough, and using #import "" in .m file .
In header files referenced header file will at compile time is completely known file header information for all interface introduced, such as imported medical in A.H was future if import in the SubA.h A.h was, implicitly imported medical and increase unnecessary compilation, cohesion is low;
In the implementation file header files, the compiler will only need to know the type of interface information, will reduce the compile time, and the degree of coupling between the classes will be reduced.
Can and how does one ask about this issue and What is the definitely guidelines ?
The (maybe simplified) version goes like this:
If you import the header/interface file, it is like including the whole other file at that place. So typically all of your interface code is known at that place. When you are working with some classes/objects, the compiler needs to know what they are and how they are called exactly: what arguments/parameters do the methods need, what do the methods return? To answer these questions, the header files are usually included in the implmentation (.m) file.
As the implementation imports its own header file, you can often put the other imports just there. But when do you need the import in the header file? When you are declaring your interface, you often mention other types/classes, i.e. you say #proerty (strong) SomeClass *element;. Now the compiler needs to know something about SomeClass, but not all. If the compiler knows that it is another class, that will be ok at this time. In the header file, no more information is needed, so the "forward declaration" of #class SomeClass may suffice. Importing the complete header file for your other class works as well.
So where's the downside of import? There's mainly two arguments: compile time and import cycles. Consider the little example - whenever SomeClass.h changes, everything that includes it must be recompiled as well. This easily cascades through the complete code. Also, obviously, any code that imports your header file will import all their imports etc. The cycles arguments works like this. A.h imports B.h, B.h imports A.h. Depending on what's in them, one should be known before the other...
(I'd like to mention that the problems are a bit more relaxed with latest compilers but the basic argumentation still holds).
Some more notes: The #class forward declaration may be needed when you declare two types that relate to each other, i.e. a protocol that uses some class which you declare just below:
#class SomeClass;
#protocol SomeProtocol
-(void)doSomethingWith:(SomeClass *)object;
#end;
#interface SomeClass
#end
Forward declaration doesn't work for protocols the class implements or parent classes.

what is #class in Objective C and when to use this directive? [duplicate]

This question already has answers here:
#class vs. #import
(16 answers)
Closed 7 years ago.
I am so confused what is #class ? What does it when i am using this directive?
when to use this directive and why? I did not get any link proper that tells why,what and when to use? Please tell me with an example?
If you say #class MyClass, the compiler knows that it may see something like:
MyClass *myObject;
It doesn't have to worry about anything other than MyClass is a valid class, and it should reserve room for a pointer to it (really, just a pointer). Thus, in your header, #class suffices 90% of the time.
However, if you ever need to create or access myObject's members, you'll need to let the compiler know what those methods are. At this point (presumably in your implementation file), you'll need to #import "MyClass.h", to tell the compiler additional information beyond just "this is a class".
It tells the compiler that the specified class exists so that it won't complain about the use of an unknown type.
A declaration of a delegate protocol might demonstrate this:
#class SomeClass;
#protocol SomeClassProtocol <NSObject>
#optional
- (void)someClass:(SomeClass *)someClass didSomethingSpecial:(int)specialThing;
#end
#interface SomeClass: NSObject
...
#end
Now without the use of the #class keyword the compiler would complain about the use of the type SomeClass in the protocol method, as it hadn't been declared yet.
However a major gotcha is that it will only work for object references (i.e. SomeClass *) as a pointer-to-type doesn't require the compiler to know anything else about the use of the type; it would not work for subclassing, for example:
This is illegal:
#class SomeClass;
#interface SomeOtherClass: SomeClass
...
#end
In easiest words:
You use #class to define there exists a class named like this one. The compiler don't show an error that there is no such class. You should use it to import as few files in your header file as possible (good practice). This way, you can have a property / ivar in your header file without importing the class clearly in your header (you probably want to do it in your implementation file). This way when importing this header file from another files, you won't include extra and often spare header files.
This is what is known as a Forward Class Declaration
It's to tell the compiler "I know about this class, so you don't need to complain".
It's useful to place in headers to increase performance with compilation time. Oh and you will get less chance of cyclical references too; so start using these if you are not already!
There is an abundance of resource available, check some out:
https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/HeaderDoc/tags/tags.html
http://nshipster.com/at-compiler-directives/
http://www.learn-cocos2d.com/2011/10/complete-list-objectivec-20-compiler-directives/#class

"Header File "Only able to be read in one class and other init methods won't work in other files

I have been stumped on this for awhile. I have asked multiple developers I know and they think I have forgotten to "#import the .h file". But I know I have, I have tested the class in more than one file in my project. It only works in the "VNDecalLevelListViewController.h" ( which I will post its implementation if a picture). When I try and call my "initForNewDecal" method for my "VNDecalCreatorViewController.h" class in my "VNAdminViewController.h" class I received the error that this method has not been declared in "VNDecalCreatorViewController.h". But when I call it in my "VNDecalLevelListViewController.h" class it works.
I am able to allocate and use "init" to create the object and it loads with a work around I made. But I am new to programming and I can tell there is definitely a better solution.
As you will soon see as i got to allocate the VNDecalCreatorViewController in the " VNAdminViewController" the option to initialize VNDecalCreatorViewController with the proper initializer "initForNewDecal" isn't even a option.
Anyone know why this is happening ? I want to write the code right I am trying to figure out why my header file is only being read in one class.
I guess this is because you mutually imported between the two class Creator and Level. I mean you may have #include "VNDecalCreatorViewController.h" in VNDecalLevelListViewController.h and vice versa. The solution is to use #class to forward declare any classes you may need to reference instead of #import'ing the header.
Make sure that the method is declared in the header file and implemented in the .m file.

Using Categories in Objective C

I have a file called ViewMessages.m which is becoming quite verbose. I'd like to refactor and put part of my methods into a separate file. It seems that Categories are the right way to go, so I've created a Category on ViewMessages called DataEngineViewMessages
It created 2 files, DataEngineViewMessages.h and DataEngineViewMessages.m
My Question: Do I need to #import "DataEngineViewMessage.h" in my original ViewMessage.h or .m in order to access my new methods?
Not into the .h file. The category header should import ViewMessages.h, and if required the category header should be imported into ViewMessages.m. This prevents any kind of circularity.
Usually you want to differentiate between category methods that should be public (defined in a header perhaps like ViewMessages+DataEngine.h) and category methods that are for internal use (defined in a header perhaps like ViewMessages+Private.h). The former shouldn't be included by ViewMessages and the latter should (again, in the .m file).
Any code that calls the methods will raise a compiler warning if the compiler can't see the method definition. They may also raise an error if the compiler can't figure out exactly what to do about the return type and you're expecting it to be an atomic C type.
In terms of keeping the external interface untouched, you can probably just add a #import for your category methods at the bottom of the main class's header file.

Resources