Private interface vs. private method - objective c - objective-c

What is the difference between a private method and a private interface?
For example, I know that if you define a method in an implementation and its interface does not mention it, it is considered a private method. I have also seen things such as:
#interface Collector()
#property (readonly) NSMutableDictionary *count;
#end
Inside of the .m implementation file.

#interface Foo() creates a class extension (I stand corrected, props to bbum) on interface Foo which is like additional methods added to the interface. Some people also use #interafce Foo(Private) (category) instead of a class extension with (). It's more like "injecting" new methods into a class from outside the class.
Placing this in the .m file just keeps other things from "seeing it" in the .h file, but that's it. Basically people normally use categories or class extensions in .m files to specify private interfaces, but they are also used for things like UIKit uses categories to add row and section public methods to NSIndexPath. (This can be confusing.)
You don't really need to define private methods this way, but if you have a method called bar that calls method foo before foo is defined in the source file you'll get a compiler warning something like "object self may not respond to foo". You can get rid of that by defining foo before you define bar or any other foo-calling code. It's the same with plain C and functions.
Like Ole says this doesn't stop anyone from calling the private methods, it just declares your intention that they be private and causes the compiler to generate the "may not respond to" warnings even if they import the .h file.
EDIT
Also see http://www.friday.com/bbum/2009/09/11/class-extensions-explained/ for some explanation of categories vs. class extensions. Looks like class extensions should be more correct for defining private methods, from a compiler warning perspective, because category methods are optional. Wish my book would have explained this!

Objective-C has no totally private methods. The method declared in a private interface section in the .m file is invisible to outside callers but it is not private. If someone knows the method signature and ignores the compiler warning, they can call it from outside without problems.

Related

Objective C: Properties Not Found In Forward Declaration Vs Parse Issue: Expected A Type

I have a singleton class called DataManager. This class is used by several other classes to deal with loading and saving plist files.
I am adding the ability for DataManager to save screenshots as well as plist files. This requires me to load the view I wish to take a screenshot of. The view I'm loading comes from a controller that imports DataManager.
Obviously this is circular dependency, so I used:
#class GardenView;
However, this resulted in the following errors:
Receiver 'GardenView' for class message is a forward declaration
Receiver type 'GardenView' for instance message is a forward
declaration Property 'bounds' cannot be found in forward class
object 'GardenView' Property 'layer' cannot be found in forward
class object 'GardenView'
This seems like it can't find properties inherited from the UIView superclass. Is this true of forward class declarations?
If I use the standard #import instead of #class, I get:
Parse Issue: Expected A Type
for the methods in GardenView referencing Plant (which I am importing just fine):
- (void) addPlantToView: (Plant*) plant;
- (void) addPlantToGarden: (Plant*) plant;
- (void) addPlantToViewAndGarden: (Plant*) plant;
The Plant class DOES import the DataManager, but if I change it to #class, I get:
No known class method for selector 'sharedDataManager'
What is the solution for this problem? The class method is there in the header file (+sharedDataManager). Am I doing something completely wrong?
You haven't made it clear where exactly you're doing the imports vs #class. And I think that's causing confusion. Here's what you want to do:
In GardenView.h, use #class Plant
In Plant.h, use #class GardenView
In GardenView.m, use #import "Plant.h"
In Plant.m, use #import "GardenView.m"
This breaks the circular dependency in the headers, but still allows the implementations to see the full information of the dependent class.
Now the reason why #class alone isn't sufficient is because all #class Foo does is it tells the compiler "There exists a class named Foo", without telling it anything at all about the class. The compiler doesn't know its methods. It doesn't know its superclass. All it knows is if it sees the token Foo, then that represents a class type. You can use this in header files so you can refer to the class in arguments and return types, but in order to actually do anything with values of that type you still need the full #import. But you can put that #import in the .m file without any problem.
The only time you need #import instead of #class in your header is if you want to inherit from the class in question. You cannot inherit from forward-declared classes, so you need the full #import. Of course, you may also need the #import if you need access to other types defined in the same header (e.g. structs, enums, etc.), but that's less common in obj-c.

How to define methods and properties only visible within an objective-c framework?

I am trying to write an objective-c framework and I would like to have methods and properties visible only within the framework. I know I could define them in a class extension inside the implementation file but then they will not be accessible by other classes.
One way I was thinking to do it was to define a category for example MyClass+Internals and make that header private. but make the MyClass.h header public. I was wondering if there was a better way of doing this. Also, I'm not sure you can define properties within a category I thought it was only methods. Thanks for any suggestions or feedback.
Say you have a class named "Foo", then in "Foo_Framework.h", create:
#interface Foo()
#property ....;
- .... method ....
#end
Then, make sure that "Foo_Framework.h" is imported before the #implementation Foo. That'll cause the class Foo to be compiled with the extended interface found in said header file. That header can then be used throughout your framework. Just don't make it available outside said framework.
You are correct that you can't declare properties (that are synthesized) in a category. That was one of the primary motivations for the creation of class extensions, of which the above is an example.

How do I know when do put my properties and methods in the .h file and when to put them in the .m interface?

How do I know when do put my properties and messages in the .h file and when to put them in the .m interface?
I am thinking messages which are public like init should be in the .h file. What about properties which describe the class e.g. configuration type etc.
When you want to restrict access of any property, you can define that in .m file using class extension etc.
There is no as such rule defined for putting properties in .h or .m file, you need to check which properties you want to access outside the class(define those in .h) and which you do want to access outside(define in .m).
According to the Apple docs, one declares properties in "#interface" (.h) files. If you want to have private object only variables, those are called ivars and you wouldn't synthesize accessors to them.
Private properties (or "property redeclaration" in the docs) can be used in things like class extensions or protocols.

How do i interface my objc program with an objc++ library?

I have an objc program and i would like to use a widget that is written in objc++ (namely https://launchpad.net/scintilla-cocoa). How do i go about this? Basically i want a new window controller object to interface with this objc++ library to define a scintilla text editor widget. Simply creating a new 'objc class' and accessing the library from there generates a bunch of errors related to the C++ class keyword and so on.
Thanks in advance
Since I'm the one who put you into the (hopefully rewarding :-)) trouble of using Scintilla, here I am.
Let's say we create a ScintillaView subclass, named ppScintillaEditor.
The file should have an .mm extension (e.g. ppScintillaEditor.mm)
The code would be roughly like this...
Interface
#import "Scintilla/ScintillaView.h"
#interface ppScintillaEditor : ScintillaView
{
// your iVars
}
// your properties / methods / whatever
Now, as for the implementation part, remember to put some initialization method to set up the view properly (as in the example accompanying Scintilla-cocoa; I mean the Test project)
Sidenote : Of course, you can create subclasses, categories or whatever on top the ScintillaView class, pretty much based on what you need - I, for example, have create a separate Category just in order to group there some ScintillaView specific commands (sooner or later, you'll notice that for some more advanced Scintilla manipulations, although it's there, it may need some polishing to be a bit more cocoa-friendly, so here you go...)
Now, last but not least...
To resolve the "bunch of errors related to the C++ class keyword and so on", as I've shown in my other video-response to your comment, all you have to do is :
Go to your project's Build Settings
Under Apple LLVM Compiler 3.0 - Preprocessing
Option Preprocessor Macros
Add to both Debug and Release :
SCI_NAMESPACE SCI_LEXER
And that's it. :-)
Hint : The above are defined by Scintilla to avoid clashes between C and non-C elements, like above... so, all it takes is to notify the preprocessor and the rest is taken care of....
you would create an objc class which has the interface your app needs, then implement and add the ivars and implement -- all behind a compilation firewall so the objc++ sources are not included in the header. your implementation would provide any necessary conversions.
it is like you have already done, but you remove the scintilla headers from the header for your wrapper -- they are visible only to your wrapper's implementation.
Update
To illustrate one possible approach:
MONScintillaWrapper.h
// no c++/scintilla sources should be included in this header
#import <Foundation/Foundation.h>
#interface MONScintillaWrapper : NSObject
- (void)setBackgroundColor:(NSColor *)pColor;
#end
MONScintillaWrapper.mm
#import "MONScintillaWrapper.h"
#implementation MONScintillaWrapper
{
scintilla::t_thing scintillaThing;
}
- (void)setBackgroundColor:(NSColor *)pColor
{
...convert pColor to a scintilla color and pass that to scintillaThing...
}
#end

What is the difference between #class and #import

When I compile with the following code there are no errors:
#class RootViewController;
//#import "RootViewController.h"
When I compile with the following code I get an error:
//#class RootViewController;
#import "RootViewController.h"
"error: expected specifier-qualifier-list before 'RootViewController'"
I don't understand what the difference is between the two because I used #import in a similar class and it compiled without errors!
#class is used when you need to know the name of a class in a particular file, but you don't need to know any details about the class (its methods, for example). #import is used when you actually need to use the class (i.e., send it a message).
For example, if you're declaring instance variables in a header file, you can use #class to declare an instance variable of a certain type:
#class MyOtherClass;
#interface MyClass : NSObject
{
MyOtherClass *myIvar;
}
#end
Since you're not using myIvar yet, you don't need to know anything about it except that the type MyOtherClass exists.
However:
#import "MyOtherClass.h"
- (void)doSomething
{
[myIvar doSomethingElse];
}
In this case, you're sending the doSomethingElse message to myIvar; the compiler needs to know that instances of MyOtherClass define this method, so you have to import the header file or the compiler will complain.
Why worry about this?
It mostly has to do with dependencies. When you #import file A into file B, file B becomes dependent upon file A -- that is, if file A changes, you'll have to recompile file B. If you use #class in file B, file B is not dependent on file A, and thus doesn't need to be recompiled when file A changes -- so if you're just declaring a type and not actually dependent upon the implementation of file A, you can save yourself compilation time by not #importing file A.
I decided to refer to the documentation because I was still confused:
#import
This directive is identical to #include, except that it makes sure that the same file is never included more than once. It’s therefore preferred and is used in place of #include in code examples throughout Objective-C–based documentation.
This convention means that every interface file includes, indirectly, the interface files for all inherited classes. When a source module imports a class interface, it gets interfaces for the entire inheritance hierarchy that the class is built upon.
#class
Declarations like this simply use the class name as a type and don’t depend on any details of the class interface (its methods and instance variables), the #class directive gives the compiler sufficient forewarning of what to expect. However, where the interface to a class is actually used (instances created, messages sent), the class interface must be imported.
http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocDefiningClasses.html#//apple_ref/doc/uid/TP30001163-CH12-TPXREF123
Basic rule: use #class in you header file and #import in your implementation file.
(However, you need to #import your class' superclass. And in some other circumstances you also need to use `#import" in the header.)
#import is not equivalent to #include. If a file is included many times, it will be loaded each time, but with many #imports of the same file, it will still only be loaded once.
Therefore, the main reason to use #class is not to avoid circular dependencies, but to make compilation faster.
Here's an example of when you must use #class
//MYControl.h
#class MYControl; // Must use class
#protocol MYControlDelegate
-(void)control:(MYControl *)control didChangeToState:(UIControlState)state;
#end
#interface MYControl : UIControl
{
id<MYControlDelegate> delegate_;
}
#property (nonatomic, assign) id<MYControlDelegate> delegate;
#end
//MYControl.m
#implementation MYControl
#synthesize delegate = delegate_;
. . .
In this case, there is nothing to import, because the delegate protocol is declared above the main class in the header file. But you still need to be able to refer to the main class which has not yet been declared. So what #class does is to just let the compiler know that there is some class that is called MYControl and will be defined at some point. (Not at runtime however. The class will be defined in the course of the compilation.)
EDIT: From the Objective-C manual:
Since declarations like this simply
use the class name as a type and don’t
depend on any details of the class
interface (its methods and instance
variables), the #class directive gives
the compiler sufficient forewarning of
what to expect. However, where the
interface to a class is actually used
(instances created, messages sent),
the class interface must be imported.
Typically, an interface file uses
#class to declare classes, and the
corresponding implementation file
imports their interfaces (since it
will need to create instances of those
classes or send them messages).
The #class directive minimizes the
amount of code seen by the compiler
and linker, and is therefore the
simplest way to give a forward
declaration of a class name. Being
simple, it avoids potential problems
that may come with importing files
that import still other files. For
example, if one class declares a
statically typed instance variable of
another class, and their two interface
files import each other, neither class
may compile correctly.
Note that circularity is mentioned in the last sentence as one in a general class of issues dealt with by using #class.
#class is used to avoid circular dependency... This prevents circular references where in one header A imports a second header B which(B) imports the first(A) which imports the second (B)and so on in an endless cycle....#class is generally used to ask compiler to look for its definition at runtime... especially when it resides in some static library..
Other than that #import works
See this question
#class:- It defines that you can create instance variable of the imported class and use it in your class.
import:- It defines that you can access the variables declared in the required imported class.
you can use given link for more info.
http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocDefiningClasses.html#//apple_ref/doc/uid/TP30001163-CH12-TPXREF123
#class means that the definition of the class RootViewController is not yet declared, but will be defined at run time. I believe it is like declaring an extern class in c++.
#import is equivalent to #include.
by the error message i could guess you just made a mistake somewhere inside RootViewController.h, such as a forgotten ; or something like that
you must have imported the this class in the class to which you want to import here. That is why you are getting error , but it can be rectify by #class example .
#class is a forward declaration, a good practice is to put them in the .h instead of #import for avoiding circular #import problem.