What is the empty #interface declaration in .m files used for? - objective-c

I've started a new iOS 5 project and noticed something new at the top of each .m file
#import "HomeViewController.h"
#interface HomeViewController ()
#end
#implementation HomeViewController
#synthesize ...
Is this extra #interface ... required if I have a separate .h file?
Why did this not show up in pre iOS 5 projects?
Can I use this instead of having a separate .h file?
What is the best practice for this going forward?

That's a class extension. You can use it to make declarations that you don't want to be in the .h file.
This was used by many developers, even before, who manually added the extension in the .m file. So I guess Apple included this in the template because it is widely used and is considered a good practice.
In fact, the .h file should only be used to make declarations that are going to be used from other files. You may have to declare some properties, methods or constants that will only be used inside the .m file. For those declarations, it is better to make them in the class extension.
So to answer your questions:
Is this extra #interface ... required if I have a separate .h file?
No, it is not required but is a best practice.
Why did this not show up in pre iOS 5 projects?
Even if this was a commonly used practice, it was not included in the template.
Can I use this instead of having a separate .h file?
No. The class extension doesn't replace the .h file where you have to declare the "public" interface of your class.
What is the best practice for this going forward?
You should put in the class extension all the declarations that don't need to be visible outside of the .m file.

The interface section in the implementation file allows you to declare variables, properties, and methods that are private, meaning that they won't be seen by other classes.
No, it's not required at all. But I use it as much as possible and only make public those things that other classes need to see.

Related

Are #interface and #end always necessary in .h file?

I noticed a strange thing in sample code downloaded from apple dev center. the sample code is Footprint: Indoor Positioning with Core Location. There is no #interface and #end in AAPLMKMapRecRotated.h file. But it works well in simulator. Can anyone explain why? Thanks!
"#interface" and "#end" are necessary wherever you want to declare the interface to an Objective-C class. If you don't declare the interface of an Objective-C class in your header, it's obviously not needed. If you declare interfaces of three Objective-C classes in your header, you'll need it three times. If you declare the interface of an Objective-C class in a .m file, so nobody outside that file can see it, then you put it into the .m file.
#interface ... #end declare a ObjC class.. Not all .h file nor all Apple API rely on ObjC, a lot of C is used thorough their framework (CoreAudio, CoreMidi, CoreGraphic, GrandCentralDispatch...) in those framework .h file are classic C header used as such and therefore no #interface .. #end...

Objective-C | Take properties and protocols declared and implemented from .m and expose publicly in .h interface

I need to refactor an existing code to have certain behavior. In order to achieve that I'd have to take some properties declared inside of the interface block in the .m file and pass it to the .h file (for accessing it publicly from other classes). Also, there are some methods declared and implemented in the .m file that I'd have to declare in the .h file.
Are there any issues in doing this?
Finally, some of those methods make use of a protocol declared and implemented in the .m file.
Can I take this protocol, put it in its own protocol file, and make use of it with an import <blabla.h> statement?
In case I can do this, does this .h file need to have the according .m implementation file?
• No need to create an .m file for a protocol since there's no implementation. Once you did that you can move the code to the new .h file and import it using import "file.h" and not <file.h>, this is reserved for frameworks.
• Moving properties from .h to .m file should definitely not be a problem.
• The other way around might produce some compile time errors - You have to make sure non of these properties is accessed outside of the .m file. The compiler will let you know once you make the change and try to build your project.
I'm really new to objective-c, just a few weeks. I need to refactor an existing code to have certain behavior. In order to achieve that I'd have to take some properties declared inside of the interface block in the .m file and pass it to the .h file (for accessing it publicly from other classes). Also, there are some methods declared and implemented in the .m file that I'd have to declare in the .h file.
In most cases there should be no problems with moving the property declarations from the extension to the interface in the header. The only difference should be scope. For the methods in the .m, just add a declaration to the .h and they'll be available to whatever imports it.
Finally, some of those methods make use of a protocol declared and
implemented in the .m file.
Can I take this protocol, put it in its own protocol file, and make
use of it with an import statement? In case I can do this, does this
.h file need to have the according .m implementation file?
You can just take the protocol definition and move it to a header file. It doesn't need a .m. Anything that needs to implement the protocol can import the .h and implement whatever is required to conform in their own .m. If the only classes that need to know about the protocol are ones that would import the .h of the class the .m with the protocol currently belongs to, you could also just move the protocol from the .m to that class's .h rather than make a separate .h for it.

What is the purpose of a class extension without any content?

According to developer documentation, a class extension is implemented by declaring an #interface in the implementation file, and it can also be used to redeclare instance variables to be private. However, I frequently see the code below that does not declare new methods or instance variables. What is its purpose?
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
...
There is no purpose behind such code. The only reason it is there is that it is part of the standard template for creating .m files in Xcode.
With this said, such class extensions are entirely harmless, so keeping them in case you need to add private methods or variables does not hurt performance of your app. In the end, it is a matter of personal taste: for example, I remove such unused template-generated artifacts from my code, but I can accept an argument in favor of keeping them as well.
If you do not wish to have these class extensions generated by default, clone and modify Xcode template for new Objective-C classes (here is a Q&A explaining how to do it).

Multiple #interface declarations generated by Xcode for NSViewController?

I am making a Cocoa application, and using Xcode for various code-generation. Works fine for generating .h and .m files for subclassing UIView, but when i subclass UIViewController i get an #interface declaration identical in both files, except that in the .m file it has ( ) at the end:
//in MyViewController.h
#interface MyViewController : NSViewController <MyViewDelegate>
#end
but also
//in MyViewController.m
#interface MyViewController ()
#end
#implementation MyViewController
#end
Yet it compiles fine. So, assuming this is normal behavior, the two-parts of question are:
(A) Why does this happen, and
(B) What are the results -- especially in terms of compile order?
Thanks!
when i subclass UIViewController i get an #interface declaration identical in both files, except that in the .m file it has ( )
As you noticed, the two interface blocks are not identical -- the () is important. The one with the () is a class extension, which is similar to a category without a name. The two important differences between a category and a class extension are:
You can declare instance variables in a class extension, but you can't in a category.
A class extension must appear in the same file as the implementation block.
Class extensions are useful for declaring instance variables and methods that you don't want to expose in the header file, such as methods or variables that are specific to the implementation and shouldn't be relied upon by users of the class.
Are you familiar with Categories? What you are observing is similar, but has important distinctions from Categories. The distinction here is that it is anonymous (hence the empty parens) and compiled at the same time the original class is compiled. That later part is an important part: it means you can add instance properties (storage). This is most commonly used to declare "internal only" or "private" methods and properties. But keep in mind that at runtime there is no notion of 'private' enforcement, it's all about what interface you have published vs. not published. This is just one way to have very clearly defined interface that is only 'published' to people who author the implementation file of the core class.

In Objective-C is it possible to keep the entire class inside the .m file?

When I create new classes in x-code it breaks it into a .h and a .m file. can I ignore the .h file and implement the entire class inside the .m file? If so what are the downsides?
It is absolutely possible to implement the whole class in a single .m file just as it is possible to implement an entire c++ class in a .cc file. The major disadvantage is that you lose the decoupling of interface and implementation. Another major disadvantage is that you will need to repeat the same interface code in any other .m file that utilizes the class. In other words you lose the ability to simply import the .h file in any other class file.
Yes it's possible. Sometimes I find it handy to have the #interface and the #implementation in one .m file to keep the class more or less private or hidden from other classes.
Yes, possible.
Often done for "internal" classes that you don't want to expose.