I have a header file for an object as follows.
#import <Foundation/Foundation.h>
#interface CSSRuleSet : NSObject{
NSMutableArray *Selectors;
NSArray *Properties;
NSMutableArray *Values;
}
-(void)printElement;
-(void)initialiseArrays;
-(NSString *)getValue:(NSString *)Property;
-(void)assignValue:(NSString *)Property:(NSString *)Value;
-(void)addSelector:(NSString *)Selector;
#end
However, when I try to call methods on that object, some work, others throw up an error "no visible #interface for 'CSSStore' declares the selector 'initialiseArrays'".
The ones I am having problems with are printElement and initialiseArrays. For some reason I couldn't write a custom init function for this object either: it was there and didn't throw up any errors, it just wouldn't run.
Let me know if more information is needed. Thanks in advance!
This class is CSSRuleSet. You appear to be trying to send messages intended for this class to a different class called CSSStore. The most likely reasons would be that either you've lost track of what object you're passing around at some point or you're not managing retains and releases correctly in a non-ARC program.
Related
Edit 2: In addition to Kurt's solution, there is one more way to do it. Take a look at the end of this page, just before comments: http://www.friday.com/bbum/2009/09/11/class-extensions-explained/
Edit: It seems class methods in a class category cannot access private members such as ivars and private methods that are implemented through class extensions.
I hope this question is not asked and answered before, but I could not find one as both stackoverflow and Google search spams my browser window with kinds of questions that ask to access an ivar directly from a class method, which is clearly not my intention.
Straight to the problem, I'll provide a piece of code, which summarizes what I'm trying to accomplish:
XYZPerson.h:
#interface XYZPerson : NSObject
#property (weak, readonly) XYZPerson *spouse;
#end
XYZPersonMariage.h:
#interface XYZPerson (XYZPersonMariage)
+(BOOL)divorce:(XYZPerson *) oneOfSpouses;
#end
XYZPersonMariage.m
+(BOOL)divorce:(XYZPerson *)oneOfSpouses
{
XYZPerson *otherSpouse = [oneOfSpouses spouse];
if(otherSpouse != nil)
{
oneOfSpouses->_spouse = nil;
otherSpouse->_spouse = nil;
return true;
}
return false;
}
I first thought that maybe an ivar is not automatically synthesized for a property flagged readonly, but it is indeed synthesized.
So, what paths can I take to get the job done?
Your method +[XYZPerson divorce:] is defined in XYZPersonMarriage.m, which is a different compilation unit than XYZPerson.m where the rest of XYZPerson is implemented.
Because of this, when compiling +divorce:, the compiler doesn't know there's an implicitly synthesized _spouse variable. For all it knows, the property could be backed by a method -spouse that you implemented.
Ways to get around this:
Move the implementation of +divorce into XYZPerson.m.
Don't access ivars directly, but do the work via real methods. They don't have to be part of the usual public interface of the class; they can be exposed via a separate header file that only XYZPersonMarriage.m imports. Search for "Objective-C private method" for more discussion on the pros and cons of that pattern.
I think I've seen this done, but I can't find documentation on it because I don't think I know the correct terms. I need to know how to write a special class that's only for use inside one other class, and therefore can be entirely written inside the other class's implementation.
Basically I need a specialized NSMutableArray that can do three extra things:
remove the most recent item once it's asked for
store that item in a last_most_recent_item variable
track whether or not a new item has been added
if a new item hasn't been added, and the last object in the array is asked for, return the last_most_recent_item instead of the actual last item
But, and here's the thing, I only need this SpecialNSArray inside of one class. So I'd like to put the declaration and implementation inside that class, instead of in separate files. I believe I've seen that done. Does anyone know what that's called, and how I could do it?
To do this just add the new class to the implementation file of the class you want to use it. I think this has been called a private class.
Suppose your class is MyClass and the improved array is MyArray the in MyClass.m
#interface MyArray
{
}
#end
#implementation MyArray
#end
#implementation MyClass
#end
In this case the extra methods on MyArray are only seen by the compiler if they are called from MyClass.
Note that there is nothing private in Objective C these methods on MyArray can be called at runtime from anywhere in your program it is just that these methods will raise a warning at compile time.
I think you are describing a category on NSMutableArray.
http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/chapters/occategories.html
YourClass.m
#interface NSMutableArray : (YourClassExtentions)
#end
#implementation NSMutableArray : (YourClassExtentions)
#end
#implementation YourClass()
#end
You could also just create the category in separate m and h files, and import.
You can simply put the class's #interface MyInternalClass ... and #implementation MyInternalClass ... code segments in the .m file for your "public" class. Add a #class MyInternalClass; line to the .h so that you can declare pointers to that class in your "public" class's instance variables.
I'm very new to Objective-C, so this is probably very basic.
Anyhow, I am trying to specify a custom return type in my class, and I keep getting errors that the class either needs an asterisk* or is not considered a type at all. I read that you need to use #class instead of #import in your header files, but that doesn't seem to help in this case. What else am I doing wrong?
Here is my code:
#import <Foundation/Foundation.h>
#class Room;
#interface LevelData : NSObject {
#private
NSArray *data;
Room *currentRoom;
}
+(void)initialize;
+(*Room)getCurrentRoom;
#end
Thanks a bunch!
change that one line to:
+(Room *)getCurrentRoom;
and see if that compiles. Room * indicates you're returning a pointer to a Room Objective-C object.
The asterisk should go after the class name, like a standard C-style
pointer.
Class methods should return a value,
usually a pointer to an object of the same class, so if you do use
initialize you'll want it to return a Room*.
Good coding practice is to override -(Class *) init;, but
only if you need to. This is because the first thing you (or someone
else using your code) should/will do when using an object (usually)
is to call some form of [[Class alloc] init]. If they call this
when you have a special initialize function, it will call the
NSObject -(NSObject *)init; method instead, and your instance
variables won't get setup.
I get an error when I try and import corresponding files.
i.e.
UIViewController "VC.h" Imports "CustomObject.h"
CustomObject Imports "VC.h"
Starts giving error expected specifier qualifier list before
Any ideas? I want both objects to be able to call each other.
Thanks
You have a circular dependency. You need to break the circular dependency by using a forward declaration. A forward declaration says "this is the name of something, but I don't know the full definition of it".
For example:
// In VC.h
// Forward declaration of an Objective-C class. After this, you can now use
// pointers to CustomObject, but you can't cell methods or access properties
// of those objects
#class CustomObject;
#interface MyViewController
{
CustomObject *obj;
}
#end
Then, in the implementation files, you can include both header files with no problems.
Thanks for the detailed response.
This was the solution, I just did not understand fully the first time I read it.
//VC.h calls cannot be made to CustomObject here, however there is not really any need to
#class CustomObject;
#interface VC : ViewController {
CustomObject* gameController;
// ...
//VC.m calls made in .m only.
#import "CustomObject.h"
gameController = [CustomObject init];
and vice versa in CustomObject
Sorry I didn't post this as a reply to your answer, new here :S
Is it possible to declare a method as private in Objective-C?
If you're working in Objective-C 2.0, the best way to create methods that are "hard" for others to call is to put them in a class extension. Assuming you have
#interface MyClass : NSObject {
}
- (id)aPublicMethod;
#end
in a MyClass.h file, you can add to your MyClass.m the following:
#interface MyClass () //note the empty category name
- (id)aPrivateMethod;
#end
#implementation MyClass
- (id)aPublicMethod {...}
- (id)aPrivateMethod {...} //extension method implemented in class implementation block
#end
The advanage of a class extension is that the "extension" methods are implemented in the original class body. Thus, you don't have to worry about which #implementation block a method implementation is in and the compiler will give a warning if the extension method is not implemented in the class' #implementation.
As others have pointed out, the Objective-C runtime will not enforce the privateness of your methods (and its not too hard to find out what those methods are using class dump, even without the source code), but the compiler will generate a warning if someone tries to call them. In general, the ObjC community takes a "I told you not to call this method [by putting it in a private class extension or category or just by documenting that the method is private] and you called it anyways. Whatever mess ensues is your fault. Don't be stupid." attitude to this issue.
No, any object can send any message to any other object. You can, however, put the method in a category that's part of the class's implementation file. That way, you'll get a "Class may not implement this method" warning if you try to call it anywhere else. That's the normal way of making a method "private."
There is nothing that will prevent the method being called (since objective-c is message based anything can be sent any message), but you can declare them outside of the header so they are not visible and the compiler will generate warnings if used.
This works for both class and instance methods.
E.g.
#import "SomeClass.h"
// Interface for hidden methods
#interface SomeClass (hidden)
+(void) hiddenClassMethod;
-(void) hiddenInstanceMethod;
#end
Note: Do NOT declare variables like this or they will become class-variables - e.g. only one variable will be used by all instances.
You can do so by using categories. I've got a fuller description in my answer to this SO question.
As has been said, you can't stop anyone sending a message to a selector, but by using categories you can reduce the visibility of these functions.
Also, you can have more than one category extending a class. So, by using informative category names you can group private functions into related blocks, improving the self-documenting nature of your code.
As others mentioned, you can't have code that's
a method, and
impossible to call from outside a class.
Folks have already pointed out that you can abandon point 2, and get a method that's hard-but-not-impossible to call. Alternatively, why not abandon point 1?
static id myPrivateMethod(MyObject *me, int arg1, id arg2) { ... }
Now the code can only be called from within same file. You don't get any of the magic private-member access you can get with a method, so this is by no means a perfect solution. But there's no better way to achieve privacy.
To implement hidden methods (instance and/or class)
// ===========================
// = File: SomeClass.m
// ===========================
#import "SomeClass.h"
// =================================
// = Interface for hidden methods
// =================================
#interface SomeClass (hidden)
-(void) hiddenInstanceMethod;
#end
// ================================
// = Implementation for SomeClass
// ================================
#implementation SomeClass
-(void) hiddenInstanceMethod
{
printf( "Hidden instance method\n" );
}
-(void) msg
{
printf("Inside msg()...\n");
[self hiddenInstanceMethod];//private method calling
}
#end
http://macdevelopertips.com/objective-c/private-methods.html
reffer this link it will be helpful .