In Objective-C Can you define a class in two different files? - objective-c

I know one file can define many different classes. What about the other way around? Can one class is defined in several different files?
Say you want to add method or property of classes you wrote (rather than the framework classes). Can you do that?
Notice I do not want to change original .m file and I want to add property which is something category cannot do.

A class can only have one #implementation block, so no you can not define a class in multiple files.
If there is some reason you can't add code to the original class #implementation, the alternatives are subclassing or categories.

Not directly.
Alternatively:
nicely - create category in other file
not nicely - #include other file in main implementation file.

Yes you can do that with categories.
//File1.h
#interface Object : NSObject
-(void)method;
#end
//File1.m
#implementation Object
-(void)method
{
NSLog (#"hello");
}
#end
//File2.h
#interfacae Object(ObjectExtention) //How you declare a category
-(void)methodTwo;
#end
//File2.m
#implementation Object(ObjectExtention)
-(void)methodTwo
{
NSLog (#"Categorie Method");
}
#end
//File3.m
#import "File1.h"
#import "File2.h"
int main()
{
Object obj = [[Object alloc] init];
[obj method]; //Declared in first file
[obj methodTwo]; //Declared in second file where we had our categorie defined
return 0;
}
You can do this with methods, however, you can't add more instance variables to a object like a categorie.

Related

From another class, how do I call a method that's declared in the implementation file but not interface?

In this tutorial here: http://www.raywenderlich.com/62989/introduction-c-ios-developers-part-1
It mentions that for Objective-C:
Even if you only declare a method inside the implementation of a
class, and don’t expose it in the interface, you technically could
still call that method externally.
How is this done?
There are a lot of ways.
For example, as long as a compatible method is declared somewhere, you can call it normally with dynamic typing. Here's a demonstration:
// MyClass.h
#interface MyClass : NSObject
#end
// MyClass.m
#interface MyClass()
- (void)addObject;
#end
#implementation MyClass
- (void)addObject:(id)object {
NSLog(#"Whoa, I got called!");
}
#end
// main.m
#import <Foundation/Foundation.h>
#import "MyClass.h"
int main() {
id something = [[MyClass alloc] init];
[something addObject:#"Look ma, no errors!"];
return 0;
}
Since there is a known method named addObject: that takes an object, and id variables are dynamically typed, this is 100% valid and will call MyClass's addObject: method.
They could even get it with a statically typed variable and a method that isn't known by declaring the method in a category. A few other options:
using performSelector: as #michaels showed in his answer
going straight to objc_msgSend()
getting the method IMP and calling it directly.
You can use the performSelector: method of NSObject, though the compiler will give you a warning if the selector is not publicly declared anywhere
[someObject performSelector:#selector(someMethod)];

How to write methods that should only be used within the class itself and are able to access ivars [duplicate]

This question already has answers here:
Best way to define private methods for a class in Objective-C
(12 answers)
Closed 9 years ago.
I have a class which has some methods that are only to be used within the class itself. These methods exist because I have a three-step process for the graphics work I'm doing, but I only want instances of the class to access the final result of those calculations, in a simplified example:
#import <Foundation/Foundation.h>
#interface GraphicsWorld : NSObject
#property(nonatomic, strong) NSMutableArray *objects;
#property(nonatomic, strong) NSMutableArray *adjustedObjects
/* three methods I'll never use outside of this class
I want to find a way to get replace these methods.
*/
-(void) calcTranslation;
-(void) calcRotation;
-(void) calcPerspective;
/* the one method I'll use outside of this class */
-(NSMutableArray *) getAdjustedObjects;
#end
I could define c-functions just outside of my implementation for this, but then they wouldn't have access to the properties:
#import <Foundation/Foundation.h>
#import "GraphicsWorld.h"
void calcTranslation()
{
// I'm useless because I can't access _objects.
}
void calcRotation()
{
// Hey, me too.
}
void calcPerspective()
{
// Wow, we have a lot in common.
}
#implementation GraphicsWorld
-(NSMutableArray *) getAdjustedObjects
{
calcTranslation();
calcRotation();
calcPerspective();
return adjustedObjects;
}
#end
Unless I'm misunderstanding your question, it sounds like you just want to hide your methods from being public? If so, just delete them from the header. You no longer need to declare methods in advance in objc (Xcode). The compiler will just find them internally now.
Make C-style functions (as you've shown) that take arguments and return values.
Make private Objective-C-style methods.
In addition to your #implementation section in the .h file, you can also have one in your .m file, which is private. Just as you declare methods and properties in the .h file's #implementation, you can do the same in the .m.
A method can be called whether it is declared private, or not put in the header file; due to the nature of Objective-C hiding methods is hard.
Hiding functions is a lot easier, just declare them static. To access the current instance you just pass in a reference to it - i.e. exactly what Objective-C does behind the scenes.
So for example:
void calcTranslation(GraphicsWorld *self)
{
// Access properties, instance variables, call instance methods etc.
// by referencing self. You *must* include self to reference an
// instance variable, e.g. self->ivar, as this is not a method the
// self-> part is not inferred.
}
and to call it:
-(NSMutableArray *) getAdjustedObjects
{
calcTranslation(self);
...

How to create a data type only for use inside one class in objective-c?

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.

How to use the same category in multiple classes?

I have stack category for NSMutableArray that I use in Class A
#implementation NSMutableArray (StackUtil)
- (void)push:(id)stackObject {
[self addObject:stackObject];
}
- (id)pop {
id retVal = [[self lastObject]retain];
[self removeLastObject];
return [retVal autorelease];
}
#end
How do I properly include this category for for Class B which is unrelated to Class A? Also I noticed that when I #import Class A into the header for Class C the category methods work, but I get the " object may not respond to push message" warning. Could someone clear up how categories are "reused" and why they have names (StackUtil in this case), and how they are used.
You should have a corresponding #interface NSMutableArray (StackUtil) in a header file that declares the category. Importing that header should be enough to confer use of your new methods onto any NSMutableArray in the scope of the import.
#interface NSMutableArray (StackUtil)
- (void) push:(id)stackObject;
- (id) pop;
#end
Certainly the #interface, and usually the #implementation, should be in files of their own, independent of your classes A, B and C, since they are general purpose additions, not something belonging to one of those client classes.

Putting methods in separate files

I have a class (MyClass) with a lot of methods. Consequently, the .m file has become quite difficult to read. I'm relatively new to Objective-C (having come from REALbasic) and I was wondering if it's possible to put some of the methods in MyClass into different files and then include them in the class. How would I go about this in Xcode?
Yes it is possible and fortunately this can be done easily in Objective-C with Categories.
Say you have your base class MyClass.
#interface MyClass : NSObject
-(void) methodA;
#end
And the according implementation file (not relevant here).
Then you can create a category by defining a new interface in a new header file:
// the category name is in parenthesis, can be anything but must be unique
#interface MyClass (extended)
-(void) methodB;
#end
and the implementation file:
#implementation MyClass (extended)
-(void) methodB {
}
#end
Common convention to name these files is ClassToAddMethodsTo+CatgoryName, i.e.:
MyClass+extended.h
MyClass+extended.m
Group related functionality into categories and give it a meaningful name.
In Objective-c you can break a class into 'categories' - a class spread across many files. The normal Object-Oriented way is to use SuperClasses and SubClasses.
This is almost certainly a code smell telling you that you have a design problem. See this antipattern
There is one thing you could do..........
But be warned, some might consider this pure blasphemy. :)
Say you have a class with two methods you want to have in separate files.
You'll have three files:
• Class.h
• Class.m
• Class_otherMethod.m
Your Class.h should look just like any other. I think it's better to keep the header file complete, but this 'trick' can work on separating .h files just as well.
#interface Class : NSObject
- (void) method;
- (void) otherMethod;
#end
In your Class.m file you will #include the Class_otherMethod.m inside the Class #implementation like this:
#import "Class.h"
#implementation Class
- (void) method {
// do something.
}
#include "Class_otherMethod.m"
#end
And your Class_otherMethod.m file will have only the bare otherMethod implementation:
- (void) otherMethod {
// do something different.
}
Why this works
It's quite simple actually. The preprocessor simply "pastes" the content of Class_otherMethod.m inside the Class.m file and the compiler treats it as one big long file. :P