I'm quite new at Objective-C and i've a question :
I've been through some Apple's sample code and found the following :
https://developer.apple.com/library/ios/#samplecode/GLSprite/Listings/Classes_EAGLView_m.html#//apple_ref/doc/uid/DTS40007325-Classes_EAGLView_m-DontLinkElementID_4
In the top of the file, I found to uses of Objective-C categories
#interface EAGLView (EAGLViewPrivate)
- (BOOL)createFramebuffer;
- (void)destroyFramebuffer;
#end
#interface EAGLView (EAGLViewSprite)
- (void)setupView;
#end
Just after that, starts the implementation of the EAGLView class.
What is the real purpose of categories here, as the 3 functions above could also be defined directly in the header file ??
Thx
As indicated by the first category's name ("EAGLViewPrivate") declaring these methods in the .m file is a way of simulating private methods. Objective-C doesn't have true support for private methods, but since these aren't declared in the .h file, the compiler will warn when code outside the .m file where they're declared tries to call them.
This is more commonly done with class extensions (a special case of a category) these days, mostly because using a class extension results in the compiler warning if a "private" method isn't implemented in the class's #implementation block. Class extensions were a new feature in Objective-C 2.0, so in older code, you'd often see a category with private in the name as in the code you've posted. The intent is the same.
Related
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).
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.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Private Method Declaration Objective-C
I assumed in objective-c class methods need to be declared either in the .h file which makes them publicly visible or in the .m file using class extension to make it more private.
I thought without first declaring the method, xcode would complain, however I add a method to my main AppDelegate class without declaring it, and everything works fine.
What part have I confused, should I be declaring all methods of the class or is it okay not to if the method will only be used by that class and no where else??
You declare methods anyway. Either in .h file
#interface ViewController : UIViewController
-(void)myMethod;
#end
or in private interface in .m
#import "ViewController.h"
#interface ViewController ()
-(void)myMethod;
#end
Declaration of all class methods is not necessary in .h file.
Declare only those methods in .h file which you want to make publicly accessible to others.
Objective C is very dynamic language, and it resolves methods at runtime. That's why we're sending messages to objects and not invoking methods (like for example in C++). So if compiler doesn't see method declaration it doesn't mean that object can't find it at runtime.
So you can actually define ObjC methods everywhere you want (in any file or even in different libraries). Ones the program is compiled and linked ObjC runtime can find all of them.
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?
I am trying to improve the design of my App by using private methods. Coming from .NET I am a little confused because I am declaring these methods in the .m file but from other files they are still showing up i.e. they are still accessible.
.m file:
#interface NSContentWebServiceController (private)
- (NSString *)flattenHTML:(NSString *)html;
- (NSString *)cleanseStringOfJsonP:(NSString *)jsonP;
- (void)retrieve:(NSasdf *)hasdel :(NSDictionary *)rootList;
- (NSString *)removeHTMLTagsFromString:(NSString *)aString;
#end
As JoostK said, there are no private methods in Objective-C like you have them in C++, Java or C#.
On top of that, the expression #interface NSContentWebServiceController (private) defines a so-called category in Objective-C. The term private here is merely a name for the category and has no meaning. Having something like yellowBunny in here would yield the same effect. A category is merely a way to break down a class into several pieces, but at runtime all categories are in effect. Note that a category is only able to add new methods to an object class, but not new variables.
For private categories it's now preferred to use the anonymous category, as in #interface MyClass(), as you then don't need a separate #implementation MyClass(yellowBunny) block but can just add the methods to main #implementation block.
See the "Categories" section in the Wikipedia entry on Objective-C for more information.
Private methods are only private in a way that they're not documented in a header file. Because of this you can't #import them into your project and thus will the compiler warn you about a 'selector not recognized' or something like that.
You'll be able to call these methods just as public methods, since it's just where you declare the prototype that makes a method private, Objective-C doesn't have such a thing as hidden, really private, methods.
At runtime, you will always be able to find all methods using introspection, so there really is no way of completely hiding your methods/properties.
You could add a id _internal instance variable which points to an object that does all the work, that way it's a bit more tough to call the private methods, although not impossible.