This is from the ViewController.m file in a starter project from a tutorial for a game.
#interface ViewController()
//irrelevant stuff omitted
#end
It's the ViewController() bit that confuses me. I understand the different between public and private interfaces, but I haven't used a private interface til now in Objective-C. I'm used to seeing something like this instead, for the public interface:
#interface ViewController : UIViewController
So why now is it just the first one, and with parentheses, with no inheritance notation?
That's a class extension. It allows for declaring additional interface, usually private because it's in an implementation (.m) file. It's similar to a category, except that the compiler will require you to supply the implementation for any interface declared within it. (A category can declare an interface even if nothing provides any implementation.)
Related
I'm still fairly new to Objective-C but I'd love to learn more about how it should be done.
I'm building a simple cheat sheet that I'd like to print and put on my office wall as a reminder.
Here's what I have so far:
// Headers (.h)
// Shows what's available to other classes
#interface ExampleViewController : UIViewController
// Declare public methods, ivars &
// properties that are synthesized.
#end
// Implementation (.m)
// Defines the content of the class
#interface ExampleViewController ()
// Class extension allowing to declare
// private methods, ivars & properties that are synthesized.
#end
#implementation ExampleViewController
// Private Properties
// Method definitions
#end
One thing I don't understand is why have both #interface and #implementation inside the implementation .m file?
I get that we can declare private stuff but why not simply throw them in #implementation like:
#implementation ExampleViewController
UIView *view; // private property
- (void)...more code
#end
#1 - Why should I ever use #interface from within my implementation .m file?
#2 - For header .h, why should I ever use #class more than #import?
#import actually gets the whole definition and #class tells the compiler that the symbol is a class. So I just don't see why I should ever use #class?
#3 - Otherwise, is there anything I should be adding somewhere in my .h or .m cheat sheet?
That's not a problem-related question but a more wiki-esque question so we everybody can look it up and completely and quickly understand those concepts as they are very hard to grasp for any newcomer.
Why should I ever use #interface from within my implementation .m file?
Because it's better to clearly separate public and private parts of the class.
For header .h, why should I ever use #class more than #import?
When forward-declaring classes for use in protocols. Like this:
#class Foo;
#protocol FooDelegate
// this wouldn't compile without a forward declaration of `Foo'
- (void)fooDidFinishAction:(Foo *)f;
#end
Otherwise, is there anything I should be adding somewhere in my .h or .m cheat sheet?
That's way too general to be answered in one post.
1 - Why should I ever use #interface from within my implementation .m file?
When you do not intend to expose that interface to any other component. That's certainly the case for private class extensions but may also apply for something like a test which doesn't need a .h file at all because while it does define a class it does not need to expose an interface for any other component to use.
2 - For header .h, why should I ever use #class more than #import?
Invert your question; why should I ever use #import rather than #class?
#class informs the compiler that a class definition of that name will exist to be linked but says nothing about it's interface.
#import makes the class' interface available to you.
A forward declaration requires less work and can allow for faster builds. It is also not always possible to #import a class at all times (as in circular references like #H2CO3's protocol example). If all you need to know is that a class exists then just use the forward declaration. When you actually need to interact with its specific interface (usually in your class' implementation) then you need to #import.
3 - Otherwise, is there anything I should be adding somewhere in my .h or .m cheat sheet?
Unless you intend to actually expose ivars as a public interface (almost certainly not the case) leave them out of your .h and expose only properties instead.
Keep your public interface as simple as possible. Try not to reveal implementation details. However keep it informative enough that users of the class can verify its behavior using that public interface. (I find test driving the design of the class using only it's public interface a good tool for striking this balance.)
Imports and forward declarations expose dependencies. Keep them to the minimum you actually need so that you can understand what the class in question actually depends on.
Delegate protocols and block types are a common part of a class' interface but not part of the #interface. Include them in the .h if they are needed by other classes (e.g. to register callbacks).
I'm new to Objective-C and am looking through many examples to wrap my head around it.
I came across this code:
#interface ImagePickerHelper : NSObject <UIImagePickerControllerDelegate, UIPopoverControllerDelegate, UINavigationControllerDelegate>
//Blah Blah
#end
#interface ImagePickerHelper ()
//Blah Blah
#end
On googling, I came to know that they specify the superclass and delegates (about which, incidentally, I know zilch) after the interface name.
But why is the interface declared twice here?
No, it is not declared two times, it is a Class interface (an anonymous category) that it is created to hold methods that you want to keep private in your class, for methods that you don't want other class to see or to interact with ..
People often declare a standard category with a name(usually "private") to hold private methods, but
the main advantage of using an anonymous category over a named category is that the compiler will complain if you do not implement a method declared in the anonymous category.
I have noticed that it is created by default from XCode 4.3 onwards .
Putting methods into this extension Class it is like declaring private methods in Java or C++ ...
The second "#interface" you see (probably in a .m file) is a class extension, and probably meant for private methods (well, private in the sense that the compiler will generate "may not respond to" warnings).
I was looking at some code:
#interface ClassName (Private)
- (float)methodOne:(NSDictionary *)argOne;
- (void)methodTwo:(NSDictionary *)argTwo;
#end
#implementation ClassName
....
The above code is at the top of the ClassName.m file which appears to define additional interface methods for the class as private?
Why do this? what is the point? What else could go where (Private) is? Anyone have docs on this?
Thanks
This is a way of keeping methods that the class uses internally from being exposed to others. It's part of encapsulation. In Objective-C 2.0 (iOS and Mac OS X 10.5+), it's more common to use a class extension at the top of the implementation file:
#interface ClassName ()
- (void)privateMethod;
#end
A class extension is really just a special case of a category (which is what you've asked about). The primary difference is that for a category, the compiler won't complain even if your #implementation doesn't include definitions for the methods declared in the category. For methods in a class extension, your class must implement those methods in its main #implementation block or you'll get a compiler warning.
You're better off using a class extension in iOS code or Mac code that targets at least Mac OS X 10.5 Leopard.
Basically it is a category and allows adding methods in the .m file. These days the best way is to use a Class Extension, the syntax is similar just the "Private" is missing, just two parentheses.
The additional advantage of a class extension is that properties can also be included and the compiler will validate that all methods declared are defined.
One area that is really handy is the ability to declare a properly readonly in the .h file and read write in the .m file. That way users of the class only have read access but the class itself has full access.
The objective-c does not support private method, and the way you are asking is a substitution for that.
you can check this link for detail:
Why doesn't Objective-C support private methods?
Class extensions #interface Class () are a lot more powerful and can inject variables into the class. Categories #interface Class (Category) can't.
What other differences are there, and when should one use a category over a class extension?
The main difference is that with an extension, the compiler will expect you to implement the methods within your main #implementation, whereas with a category you have a separate #implementation block. So you should pretty much only use an extension at the top of your main .m file (the only place you should care about ivars, incidentally) -- it's meant to be just that, an extension.
A class extension bears some similarity to a category, but it can only be added to a class for which you have the source code at compile time (the class is compiled at the same time as the class extension). The methods declared by a class extension are implemented in the #implementation block for the original class so you can’t, for example, declare a class extension on a framework class, such as a Cocoa or Cocoa Touch class like NSString.
The syntax to declare a class extension is similar to the syntax for a category, and looks like this:
#interface ClassName ()
#end
Because no name is given in the parentheses, class extensions are often referred to as anonymous categories.
Unlike regular categories, a class extension can add its own properties and instance variables to a class. If you declare a property in a class extension, like this:
#interface XYZAnimal () {
id _someCustomInstanceVariable;
}
...
#end
IMHO, it's best to think of class extensions as private interface to a class. The primary interface (in your .h file) acts as the public interface which defines the class's behavioural contract with other classes.
Use class extensions to Hide Private Information
Class extensions are often used to extend the public interface with additional private methods or properties for use within the implementation of the class itself. It’s common, for example, to define a property as readonly in the interface, but as readwrite in a class extension declared above the implementation, in order that the internal methods of the class can change the property value directly.
As an example, the XYZPerson class might add a property called uniqueIdentifier, designed to keep track of information like a Social Security Number in the US.
It usually requires a large amount of paperwork to have a unique identifier assigned to an individual in the real world, so the XYZPerson class interface might declare this property as readonly, and provide some method that requests an identifier be assigned, like this:
#interface XYZPerson : NSObject
...
#property (readonly) NSString *uniqueIdentifier;
- (void)assignUniqueIdentifier;
#end
In order for the XYZPerson class to be able to change the property internally, it makes sense to redeclare the property in a class extension that’s defined at the top of the implementation file for the class:
#property (readwrite) NSString *uniqueIdentifier;
Note: The readwrite attribute is optional, because it’s the default. You may like to use it when redeclaring a property, for clarity.
Categories are an Objective-C language feature that let you add new methods to an existing class. Extensions are a special case of categories that let you define methods that must be implemented in the main implementation block.
Private declarations can be in class extensions, which mainly are some properties, because we have no need to declare a method before we call it.
ios extension similiar to c#,java abstract class or interface
ios category similiar to c# class extension
Style-wise (and functionally, if there is any difference), for declaring private methods, which of these is better?
#interface MyClass()
#interface MyClass(private)
The two syntaxes serve different purposes.
A named category -- #interface Foo(FooCategory) -- is generally used to:
(1) extend an existing class by adding functionality. Example: NSAttributedString in Foundation is extended by a category in AppKit that adds AppKit specific RTF-like text formatting API.
(2) declare a set of methods that might or might not be implemented by a delegate. Example: Various classes declare -- but don't implement -- #interface NSObject(SetODelegateMethods).
Form (2) has fallen out of favor now that #protocol has been extended to support #optional methods in Objective-C 2.0.
A class extension -- #interface Foo() -- is designed to allow you to declare additional private API -- SPI or System Programming Interface -- that is used to implement the class innards. This typically appears at the top of the .m file. Any methods / properties declared in the class extension must be implemented in the #implementation, just like the methods/properties found in the public #interface.
Class extensions can also be used to redeclare a publicly readonly #property as readwrite prior to #synthesize'ing the accessors.
Example:
Foo.h
#interface Foo:NSObject
#property(readonly, copy) NSString *bar;
-(void) publicSaucing;
#end
Foo.m
#interface Foo()
#property(readwrite, copy) NSString *bar;
- (void) superSecretInternalSaucing;
#end
#implementation Foo
#synthesize bar;
.... must implement the two methods or compiler will warn ....
#end
Yes,
there are the following differences.
1) Using anonymous categories requires implementing its methods in the main #implementation block for the corresponding class; anonymous categories allow you to declare additional required API for a class in locations other than within the primary class #interface block
2) When using MyClass(private), the following must be taken into account: object/category named pairs must be unique. If you declare a private category on your own class, then there are no problems. However, things are different on existing classes. For instance, only one NSString (Private) category can exist in a given Objective-C namespace. This can lead to problems because the Objective-C namespace is shared between the program code and all the libraries,frameworks,and plug-ins.This is especially important for Objective-C programmers writing screensavers,preference panes, and other plug-ins because their code will be injected into application or framework code that they do not control.