Fast enumeration on a class object - objective-c

I'm implementing an application where both instances of a class as well as the class itself have "children" (placed inside a NSMutableArray). It's a pretty complicated application, but thanks to Objective-C, it's a breeze: classes are themselves objects and can have methods and "variables" (with the help of static variables and such).
To make it myself easy, I implemented accessor/setter method on both my instances (using -) and classes (using +) to fetch and manipulate the "children" without having direct access to the arrays. I like to have my objects as much as possible closed and the methods do some data validation.
I also implemented a fast enumeration instance method from the NSFastEnumeration protocol. And here comes the question: can I implement a fast enumeration class method and use it with Objective-C's for...in construct? In order words, can I implement this:
+ (NSUInteger)countByEnumeratingWithState: (NSFastEnumerationState *)state objects: (__unsafe_unretained id [])buffer count: (NSUInteger)len;
And then use it somewhere like that:
for (id child in [MyClass class]) {
// Do magic stuff…
}
I peeked in GNUStep's GSFastEnumeration.h file which implements fast enumeration as a macro, which affirms the above is possible, but I'm not sure if Apple does the same.
Even if I can't associate the NSFastEnumeration protocol to my class object, is fast enumeration without that protocol possible (and future-proof)?

The method -countByEnumeratingWithState:objects:count: is the whole of fast enumeration—the protocol is, I believe, mostly there for description (it's easier to implement a protocol than declare the method with the correct signature). I would expect it to work just fine, but I don't have a reference for that. You would probably want to loop over [MyClass class], though.
I would probably consider it future-proof. Note that it'd be really trivial to make a tiny wrapper class around your class object that does nothing but implement NSFastEnumeration and forward the instance method -countByEnumeratingWithState:objects:count: to your class's method +countByEnumeratingWithState:objects:count:.

I would recommend creating a protocol with a class method that is identical to the NSFastEnumeration method. You could then iterate over the [MyClass class] as John Calsbeek mentioned.
//Protocol implementation
#protocol FastClassEnumeration <NSObject>
#required
+ (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id [])buffer count:(NSUInteger)len;
#end
//Class implementation
#interface EnumeratedClass : NSObject<FastClassEnumeration>
#end
#implementation EnumeratedClass
+ (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id [])buffer count:(NSUInteger)len
{
static const unsigned long items_length = 4;
static NSString * items[items_length] = { #"item1", #"item2", #"item3", #"item4" };
if(state->state >= items_length)
{
return 0;
}
state->itemsPtr = items;
state->state = items_length;
state->mutationsPtr = (unsigned long *)self;
return items_length;
}
#end
//Usage
...
for(NSString *item in [EnumeratedClass class])
{
NSLog(#"%#", item);
}
...

can I ... ?
Well, did you try it? Does it work? If you've tried it, you would notice that it does indeed compile and work.
And why shouldn't it? Class objects are objects just like other objects. Class methods are just methods that happen to be on the class object. If you send a message to a class object, it will call a class method; whereas if you send a message to a non-class object, it will call an instance method. So pretty much, you can put class methods on a class and use the class object the same way you can use a normal object by putting instance methods on its class.
The only possible difference is that the class object won't explicitly conform to the NSFastEnumeration protocol, similar to if you loop over a normal object whose class does not explicitly specify that it conforms to the NSFastEnumeration protocol. So the question is, do they check that an object explicitly conforms to the protocol before using it (as opposed to checking if it responds to the selector)?
In my experience, for pretty much all of Cocoa, for APIs that say they require an object that conforms to a protocol, you can give an object that does not explicitly conform to the protocol, but implements all of the protocol's methods, and it will work fine. (How would they check it anyway? If they use conformsToProtocol:, that won't work for class objects since there's a +conformsToProtocol:, which has a different meaning. They would have to use runtime functions or special-case class objects probably.) For example, the NSDictionary documentation says its keys are required to conform to NSCopying, but if you have an object that does not conform to NSCopying, but does implement copyWithZone:, it works fine. (In fact, there is a +copyWithZone: method, whose stated purpose is to allow class objects to be used as dictionary keys, so obviously it is intended that keys don't need to explicitly conform to NSCopying.)

Related

Exposing/Synthesizing iVar properties in Objective c

I have a class that essentially acts as a light weight wrapper class around another class. It holds that other class as an iVar. I want to be able to expose certain properties (quite a few actually) of the iVar, but to do so I have to write out each property accessor like so:
- (void) setProperty:(Class *)value{
_iVar.property = value;
}
- (Class *) property{
return _iVar.property;
}
Of course, I have to do this for every single property, which is a pain (there are about 30 of them). I would love to be able to synthesize this but I haven't been able to figure out how.
Is it possible to synthesize?
Also, I can't subclass....well, I might be able to but it's really not recommended. The iVar class is really quite heavy (it implements CoreText). I'd rather write out the methods by hand.
Ok, so here's the solution I found...ended up being pretty simple once you knew what to do. First overwrite '- (id) forwardingTargetForSelector:(SEL)aSelector' and return the iVar:
- (id) forwardingTargetForSelector:(SEL)aSelector{
return iVar;
}
When the runtime is looking for a method and cannot find one, it will call this method to see if there is another object to forward the message to. Note that this method normally returns nil and if you return nil here, your program will crash (which is the appropriate behavior).
The second part of the problem is to shush the compiler errors/warnings you'll get when you try to send a message that's not declared. This is easily done by declaring a category you don't implement.
#interface Class (iVarClassMethods)
#propoperty (strong) Class *property1;
......more properties
#end
As long as you don't put in an implementation anywhere, aka #implementation Class (category), the compiler won't complain (it'll assume that the implementation is somewhere....).
Now the only drawback I see is if you change any of the properties in the interface of the iVar Class, you need to make sure you update all other classes that use the method described above, otherwise you'll crash when another class tries to send what is now the wrong method (and the compiler won't warn you beforehand). However, this can be gotten around. You can declare protocols in a category. So instead you create a separate protocol for the iVar class and move the methods/properties you wish out of the iVar class into the protocol.
#protocol iVarClassProtocol
#propoperty (strong) Class *property1;
......more properties
#end
Add that protocol to the iVar subclass so it has those methods declared through the protocol now.
#interface iVarClass <iVarClassProtocol>
....other methods/properties you don't need forwarded
#end
Finally, simply add the protocol to the category. So instead of the aforementioned category with explicit declarations you'll have:
#interface Class (iVarClassMethods) <iVarClassProtocol>
#end
Now, if you need to change any of the to-be-fowarded properties/methods, you change them in the protocol. The compiler will then warn you when you try to send the wrong method to the forwarding class.
I think you can forward the messages to the ivar:
- (void) forwardInvocation: (NSInvocation*) invocation
{
[invocation invokeWithTarget:ivar];
}
- (NSMethodSignature*) methodSignatureForSelector: (SEL) selector
{
NSMethodSignature *our = [super methodSignatureForSelector:selector];
NSMethodSignature *ivars = [ivar methodSignatureForSelector:selector];
return our ? our : ivars;
}
Then you have to hide or fake the type of your object, for example by casting to id, otherwise the compiler will complain that your class does not implement those methods.
Of course it would be best if you could come up with some better design that would do without such tricks.

What's the difference between "class method" and "static method"?

I've worked with a few different languages such as Java, C#, and Objective-C.
In most languages, methods that don't require an instance of an object are called static methods. However, when it comes to Objective-C, some people get defensive when you call them static methods, and they expect you to call them class methods.
Why are they called class methods instead of static methods? What is the difference between a static method and a class method?
So my question is why are they called class methods instead of a
static method? What is the difference between a static method and a
class method?
From Wikipedia: Static methods neither require an instance of the class nor can they implicitly access the data (or this, self, Me, etc.) of such an instance.
This describes exactly what Objective-C's class methods are not.
An Objective-C class method very much requires an instance that is the target of the method invocation. That is, it requires an instance of the metaclass that describes the class object being invoked.
Unlike static methods, Objective-C's class methods can be inherited (which, in combination with having the aforementioned self, is exactly why many classes can share a single, simple, implementation of +alloc on NSObject without needing their own custom implementations) and invoking a class method goes through the exact same objc_msgSend* based dispatch mechanism as any other method call site.
Objective-C's class methods can be overridden across the class hierarchy and they can be swizzled. None of which is supported in languages that typically offer static methods in lieu of class methods.
The bottom line is that static methods and class methods are very different. While that difference is mostly transparent for day to day coding purposes, there are still situations where knowing how class methods work can save you a ton of unnecessary lines of code.
For example, you can't do this with static methods:
#interface AbstractClass:NSObject
+ factory;
#end
#implementation AbstractClass
+ factory
{
return [[[self alloc] init] autorelease];
}
#end
#interface Concrete1:AbstractClass
#end
#implementation Concrete1
#end
#interface Concrete2:AbstractClass
#end
#implementation Concrete2
#end
void foo() {
Concrete1 *c = [Concrete1 factory];
Concrete2 *d = [Concrete2 factory];
... etc ...
}
Because it's dynamically bound, not static.
Because it's really a class object's instance method.
Objective-C class method is actually an object's class object's instance method.
It's hard to describe with text. See nice illustration here.
http://www.sealiesoftware.com/blog/archive/2009/04/14/objc_explain_Classes_and_metaclasses.html
Though class methods and static methods are in practice the same most of the time, they are different. With static methods the class is acting as a namespace qualifier. With class methods the class itself is an object and so class methods are to the class object exactly the same thing instance methods are to an instance; as a consequence you can do the following
#interface TestClass : NSObject
+ (void)classOrInstanceMethod;
- (void)classOrInstanceMethod;
#end
...
NSArray * arr = [NSArray arrayWithObjects:
[[[TestClass alloc] init] autorelease],
[TestClass class],
nil];
for( id obj in arr )
[obj classOrInstanceMethod];
which version of classOrInstanceMethod is called depends on whether obj is a class object or and instance. If you are familiar with the factory class pattern, this pattern is part of the Objective-C language.
This is purely a historical difference, mostly stemming from the fact that Objective-C was developed contemporaneously with C++, and before C++ or later languages like Java and C# had much influence. Objective-C was essentially a port of the Smalltalk object model to C, so its syntax and terminology don't necessarily seem as "C-like" as that used by C++. However, Objective-C was in no way bucking a trend by not using the term "static method", because that trend wasn't well-established back in 1983.

How do I provide a default implementation for an Objective-C protocol?

I'd like to specify an Objective-C protocol with an optional routine. When the routine is not implemented by a class conforming to the protocol I'd like to use a default implementation in its place. Is there a place in the protocol itself where I can define this default implementation? If not, what is the best practice to reduce copying and pasting this default implementation all over the place?
Objective-C protocols have no affordance for default implementations. They are purely collections of method declarations that can be implemented by other classes. The standard practice in Objective-C is to test an object at runtime to see if it responds to the given selector before calling that method on it, using -[NSObject respondsToSelector:]. If e object does not respond to the given selector, the method isn't called.
One way you could achieve the result you're looking for would be to define a method encapsulating the default behavior you're looking for in the calling class, and call that method if the object doesn't pass the test.
Another approach would be to make the method be required in the protocol, and provide default implementations in the superclasses of any classes wherein you may not want to provide a specific implementation.
There are probably other options as well, but generally speaking there isn't a particular standard practice in Objective-C, except perhaps to just not call the given method if it hasn't been implement by the object, per my first paragraph, above.
There is no standard way for doing that as protocols should not define any implementations.
Since Objective-C comes with a neat runtime, you can of course add such a behavior if you really think you need to do it that way (and there's no possibility by achieving the same with inheritance).
Say you declared MyProtocol, then just add an interface with the same name in the .h file under your protocol declaration:
#interface MyProtocol : NSObject <MyProtocol>
+ (void)addDefaultImplementationForClass:(Class)conformingClass;
#end
And create a corresponding implementation file (using MAObjCRuntime for readability here, but the standard runtime functions wouldn't be much more code):
#implementation MyProtocol
+ (void)addDefaultImplementationForClass:(Class)conformingClass {
RTProtocol *protocol = [RTProtocol protocolWithName:#"MyProtocol"];
// get all optional instance methods
NSArray *optionalMethods = [protocol methodsRequired:NO instance:YES];
for (RTMethod *method in optionalMethods) {
if (![conformingClass rt_methodForSelector:[method selector]]) {
RTMethod *myMethod = [self rt_methodForSelector:[method selector]];
// add the default implementation from this class
[conformingClass rt_addMethod:myMethod];
}
}
}
- (void)someOptionalProtocolMethod {
// default implementation
// will be added to any class that calls addDefault...: on itself
}
Then you just have to call
[MyProtocol addDefaultImplementationForClass:[self class]];
in the initializer of your class conforming to the protocol and all default methods will be added.
A truly fascinating way is to use the runtime. At the start-up, very early in the program execution, do the following:
Enumerate all the classes, find classes which implement the protocol
Check if the class implements a method
If not, add to the class the default implementation
It can be achieved without that much trouble.
I agree with "w.m." A very nice solution is to put all the default implementations into an interface (with the same name as the protocol). In the "+initialize" method of any subclass it can simply copy any unimplemented methods from the default interface into itself.
The following helper functions worked for me
#import <objc/runtime.h>
// Get the type string of a method, such as "v#:".
// Caller must allocate sufficent space. Result is null terminated.
void getMethodTypes(Method method, char*result, int maxResultLen)
{
method_getReturnType(method, result, maxResultLen - 1);
int na = method_getNumberOfArguments(method);
for (int i = 0; i < na; ++i)
{
unsigned long x = strlen(result);
method_getArgumentType(method, i, result + x, maxResultLen - 1 - x);
}
}
// This copies all the instance methods from one class to another
// that are not already defined in the destination class.
void copyMissingMethods(Class fromClass, Class toClass)
{
// This gets the INSTANCE methods only
unsigned int numMethods;
Method* methodList = class_copyMethodList(fromClass, &numMethods);
for (int i = 0; i < numMethods; ++i)
{
Method method = methodList[i];
SEL selector = method_getName(method);
char methodTypes[50];
getMethodTypes(method, methodTypes, sizeof methodTypes);
if (![toClass respondsToSelector:selector])
{
IMP methodImplementation = class_getMethodImplementation(fromClass, selector);
class_addMethod(toClass, selector, methodImplementation, methodTypes);
}
}
free(methodList);
}
Then you call it in your class initializer such as...
#interface Foobar : NSObject<MyProtocol>
#end
#implementation Foobar
+(void)initialize
{
// Copy methods from the default
copyMissingMethods([MyProtocol class], self);
}
#end
Xcode will give you warnings about Foobar missing methods, but you can ignore them.
This technique only copies methods, not ivars. If the methods are accessing data members that do not exist, you could get strange bugs. You must ensure that the data is compatible with the code. It is as if you did a reinterpret_cast from Foobar to MyProtocol.
As Ryan mention there are no default implementations for protocols, another option to implementing in the superclass would be is to implement a "Handler" kind of class that can be contained in any class that want to provide the default implementation, the appropriate method then calls the default handlers implementation.
I ended up creating a macro that has a default implementation of the method.
I've defined it in the protocol's header file, and then it's just a one-liner in each implementation.
This way, I do not have to change the implementation several places, and it's done on compile time, so no run-time magic is necessary.

Should I subclass the NSMutableArray class

I have an NSMutableArray object that I want to add custom methods to. I tried subclassing NSMutableArray but then I get an error saying "method only defined for abstract class" when trying to get the number of objects with the count method. Why is the count method not inherited?
I read somewhere else that I will have to import some NSMutableArray methods into my custom class if I want to use them. I just want to add a custom method to the NSMutableArray class. So should I subclass NSMutableArray, or should I do something else?
NSMutableArray is not a concrete class, it is just the abstract superclass of a class cluster. The documentation for NSMutableArray does have information about how to subclass, but also strongly advises you not to! Only subclass if you have a special need for actual storage.
A class cluster means that the actual class will be chosen at run-time. An array created empty, may not use the same class as an array created with 1000 items. The run-time can do smart choices of what implementation to use for you. In practice NSMutableArray will be a bridged CFArray. Nothing you need to worry about, but you might see it if you inspect the type of your arrays in the debugger, you will never see NSArray, but quite often NSCFArray.
As mentioned before, subclassing is not the same as extending a class. Objective-C has the concept of categories. A category is similar to what other programming languages call mix-ins.
If you for example want a convenience method on NSMutableArray to sort all members on a property, then define the category interface in a .h file as such:
#interface NSMutableArray (CWFirstnameSort)
-(void)sortObjectsByProperty:(NSString*)propertyName;
#end
And the implementation would be:
#implementation NSMutableArray (CWFirstnameSort)
-(void)sortObjectsByProperty:(NSString*)propertyName;
{
NSSortDescriptor* sortDesc = [NSSortDescriptor sortDescriptorWithKey:propertName ascending:YES];
[self sortUsingDescriptors:[NSArray arrayWithObject:sortDesc]];
}
#end
Then use it simply as:
[people sortObjectsByProperty:#"firstName"];
If you're just adding a custom method, use a category on NSMutableArray. It's a class cluster, so the implementation is provided by undocumented subclasses. You need to provide a few methods to generate your own subclass. However, if you just add a category then your custom method will work on all NSMutableArrays in your app.
For comparison, here's an example I wrote a while back of implementing a custom NSMutableArray subclass.
Objective-C has a mechanism for adding methods to existing classes called Categories. That way you don't have to create your own subclass.
This is an old post, but thought I'd add my experience. #PayloW's answer is a good answer and I think answers your question perfectly, however, no one really answered your question the other way around, so I'll do that here.
Should you subclass NSMutableArray (or NSArray)? Depends on what you want to achieve. If you only want to add a method to extend an array's BASIC functionality, like sorting, then #PayloW's answer Categories are the way. However, if you want to create a custom class that behaves like an array then yes, subclassing NSMutableArray is quite easy. But because it's a Class Cluster it doesn't exactly subclass as you'd expect. Normally in subclassing the methods available in the Super Class are available to your subclass or you may override them. With Class Clusters you MUST instead include the Super's methods that you're going to use and provide a _backend instance of the super class to wrap those methods around.
Below is an example of how you'd subclass NSMutableArray (or any Class Cluster):
The interface:
#interface MyCustomArrayClass : NSMutableArray {
// Backend instance your class will be using
NSMutableArray *_backendArray;
}
// *** YOUR CUSTOM METHODS HERE (no need to put the Super's methods here) ***
-(bool)isEmpty;
-(id)nameAtIndex:(int)index;
-(int)rowAtIndex:(int)index;
-(int)columnAtIndex:(int)index;
#end
The implementation:
#implementation MyCustomArrayClass
-(instancetype)init {
if (self = [super init]) {
_backendArray = [#[] mutableCopy];
}
return self;
}
// *** Super's Required Methods (because you're going to use them) ***
-(void)addObject:(id)anObject {
[_backendArray addObject:anObject];
}
-(void)insertObject:(id)anObject atIndex:(NSUInteger)index {
[_backendArray insertObject:anObject atIndex:index];
}
-(void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject {
[_backendArray replaceObjectAtIndex:index withObject:anObject];
}
-(id)objectAtIndex:(NSUInteger)index {
return [_backendArray objectAtIndex:index];
}
-(NSUInteger)count {
return _backendArray.count;
}
-(void)removeObject:(id)anObject {
[_backendArray removeObject:anObject];
}
-(void)removeLastObject {
[_backendArray removeLastObject];
}
-(void)removeAllObjects {
[_backendArray removeAllObjects];
}
-(void)removeObjectAtIndex:(NSUInteger)index {
[_backendArray removeObjectAtIndex:index];
}
// *** YOUR CUSTOM METHODS ***
-(bool)isEmpty {
return _backendArray.count == 0;
}
-(id)nameAtIndex:(int)index {
return ((MyObject *)_backendArray[index]).name;
}
-(int)rowAtIndex:(int)index {
return ((MyObject *)_backendArray[index]).row;
}
-(int)columnAtIndex:(int)index {
return ((MyObject *)_backendArray[index]).column;
}
#end
Then to use like so:
MyCustomArrayClass *customArray = [[MyCustomArrayClass alloc] init];
// Your custom method
int row = [customArray rowAtIndex:10];
// NSMutableArray method
[customArray removeLastObject];
// Your custom class used just like an array !!!
index = 20;
MyObject *obj = customArray[index];
It all works very nicely, is clean and actually pretty cool to implement and use.
Hope it helps.
I have to agree with both node ninja and PeyloW because technically they have both right. Actually, that does not help me much.
Preamble:
There are many arrays in code that all to one contain only one but different type of data e.g. classA, classB, classC.
Problem:
I can easily mix arrays by passing wrong one to e.g. some selector because they are all NSMutableArray. There is no static check, only runtime one.
Solution - 1st try:
Make subclass of NSMutableArray so compiler makes static check and warns about wrong data type.
That is good because compiler warns you even when you pass wrong type to -addObject or -objectAtIndex when you overload that ones.
That is bad because you cannot instantiate NSMutableArray superclass this way.
Solution - 2nd try:
Make new (proxy) class of some type e.g. NSObject as for NSMutableArray and add class member of type NSMutableArray.
This is good because you can instantiate NSMutableClass and compiler checks when you pass wrong type to -addObject or -objectAtIndex when you overload that ones.
The bad side of that is that you need to overload every selector of the NSMutableArray that you use, not only that ones that differs in class that array contains.
Conclusion:
When you build some sophisticated code that has many class types in its arrays, believe me it is worth to try. Simply by doing this compiler showed me several errors that I would not recognize until I will face it in runtime. Or even worse, when end user would face it.
From the Apple reference for NSArray, in the Methods to Override section:
Any subclass of NSArray must override the primitive instance methods count and objectAtIndex:. These methods must operate on the backing store that you provide for the elements of the collection. For this backing store you can use a static array, a standard NSArray object, or some other data type or mechanism. You may also choose to override, partially or fully, any other NSArray method for which you want to provide an alternative implementation.
As a side note, in Objective-C, there is no actual feature that allows you to declare a class as an abstract class, per se, as in Java, for instance. So, what they do instead is call something like the code below, from within some method that they want to force to be overridden by a subclass. In effect, they give the class 'abstract class' semantics.
This method definition acts as an abstract method, which raises an Exception if not overridden, with the following output:
-someAbstractFooMethod only defined for abstract class. Define -[YourClassName someAbstractFooMethod]!
- (void) someAbstractFooMethod
{
//Force subclassers to override this method
NSString *methodName = NSStringFromSelector(_cmd);
NSString *className = [self className];
[NSException raise:NSInvalidArgumentException
format:#"-%# only defined for abstract class. Define -[%# %#]!", methodName, className, methodName];
}

What is the difference between class and instance methods?

What's the difference between a class method and an instance method?
Are instance methods the accessors (getters and setters) while class methods are pretty much everything else?
Like most of the other answers have said, instance methods use an instance of a class, whereas a class method can be used with just the class name. In Objective-C they are defined thusly:
#interface MyClass : NSObject
+ (void)aClassMethod;
- (void)anInstanceMethod;
#end
They could then be used like so:
[MyClass aClassMethod];
MyClass *object = [[MyClass alloc] init];
[object anInstanceMethod];
Some real world examples of class methods are the convenience methods on many Foundation classes like NSString's +stringWithFormat: or NSArray's +arrayWithArray:. An instance method would be NSArray's -count method.
All the technical details have been nicely covered in the other answers. I just want to share a simple analogy that I think nicely illustrates the difference between a class and an instance:
A class is like the blueprint of a house: You only have one blueprint and (usually) you can't do that much with the blueprint alone.
An instance (or an object) is the actual house that you build based on the blueprint: You can build lots of houses from the same blueprint. You can then paint the walls a different color in each of the houses, just as you can independently change the properties of each instance of a class without affecting the other instances.
Like the other answers have said, instance methods operate on an object and has access to its instance variables, while a class method operates on a class as a whole and has no access to a particular instance's variables (unless you pass the instance in as a parameter).
A good example of an class method is a counter-type method, which returns the total number of instances of a class. Class methods start with a +, while instance ones start with an -.
For example:
static int numberOfPeople = 0;
#interface MNPerson : NSObject {
int age; //instance variable
}
+ (int)population; //class method. Returns how many people have been made.
- (id)init; //instance. Constructs object, increments numberOfPeople by one.
- (int)age; //instance. returns the person age
#end
#implementation MNPerson
- (id)init{
if (self = [super init]){
numberOfPeople++;
age = 0;
}
return self;
}
+ (int)population{
return numberOfPeople;
}
- (int)age{
return age;
}
#end
main.m:
MNPerson *micmoo = [[MNPerson alloc] init];
MNPerson *jon = [[MNPerson alloc] init];
NSLog(#"Age: %d",[micmoo age]);
NSLog(#"%Number Of people: %d",[MNPerson population]);
Output:
Age: 0
Number Of people: 2
Another example is if you have a method that you want the user to be able to call, sometimes its good to make that a class method. For example, if you have a class called MathFunctions, you can do this:
+ (int)square:(int)num{
return num * num;
}
So then the user would call:
[MathFunctions square:34];
without ever having to instantiate the class!
You can also use class functions for returning autoreleased objects, like NSArray's
+ (NSArray *)arrayWithObject:(id)object
That takes an object, puts it in an array, and returns an autoreleased version of the array that doesn't have to be memory managed, great for temperorary arrays and what not.
I hope you now understand when and/or why you should use class methods!!
An instance method applies to an instance of the class (i.e. an object) whereas a class method applies to the class itself.
In C# a class method is marked static. Methods and properties not marked static are instance methods.
class Foo {
public static void ClassMethod() { ... }
public void InstanceMethod() { ... }
}
The answer to your question is not specific to objective-c, however in different languages, Class methods may be called static methods.
The difference between class methods and instance methods are
Class methods
Operate on Class variables (they can not access instance variables)
Do not require an object to be instantiated to be applied
Sometimes can be a code smell (some people who are new to OOP use as a crutch to do Structured Programming in an OO enviroment)
Instance methods
Operate on instances variables and class variables
Must have an instanciated object to operate on
I think the best way to understand this is to look at alloc and init. It was this explanation that allowed me to understand the differences.
Class Method
A class method is applied to the class as a whole. If you check the alloc method, that's a class method denoted by the + before the method declaration. It's a class method because it is applied to the class to make a specific instance of that class.
Instance Method
You use an instance method to modify a specific instance of a class that is unique to that instance, rather than to the class as a whole. init for example (denoted with a - before the method declaration), is an instance method because you are normally modifying the properties of that class after it has been created with alloc.
Example
NSString *myString = [NSString alloc];
You are calling the class method alloc in order to generate an instance of that class. Notice how the receiver of the message is a class.
[myString initWithFormat:#"Hope this answer helps someone"];
You are modifying the instance of NSString called myString by setting some properties on that instance. Notice how the receiver of the message is an instance (object of class NSString).
Class methods are usually used to create instances of that class
For example, [NSString stringWithFormat:#"SomeParameter"]; returns an NSString instance with the parameter that is sent to it. Hence, because it is a Class method that returns an object of its type, it is also called a convenience method.
So if I understand it correctly.
A class method does not need you to allocate instance of that object to use / process it. A class method is self contained and can operate without any dependence of the state of any object of that class. A class method is expected to allocate memory for all its own work and deallocate when done, since no instance of that class will be able to free any memory allocated in previous calls to the class method.
A instance method is just the opposite. You cannot call it unless you allocate a instance of that class. Its like a normal class that has a constructor and can have a destructor (that cleans up all the allocated memory).
In most probability (unless you are writing a reusable library, you should not need a class variable.
Instances methods operate on instances of classes (ie, "objects"). Class methods are associated with classes (most languages use the keyword static for these guys).
Take for example a game where lots of cars are spawned.. each belongs to the class CCar.
When a car is instantiated, it makes a call to
[CCar registerCar:self]
So the CCar class, can make a list of every CCar instantiated.
Let's say the user finishes a level, and wants to remove all cars... you could either:
1- Go through a list of every CCar you created manually, and do whicheverCar.remove();
or
2- Add a removeAllCars method to CCar, which will do that for you when you call [CCar removeAllCars]. I.e. allCars[n].remove();
Or for example, you allow the user to specify a default font size for the whole app, which is loaded and saved at startup.
Without the class method, you might have to do something like
fontSize = thisMenu.getParent().fontHandler.getDefaultFontSize();
With the class method, you could get away with [FontHandler getDefaultFontSize].
As for your removeVowels function, you'll find that languages like C# actually have both with certain methods such as toLower or toUpper.
e.g. myString.removeVowels() and String.removeVowels(myString) (in ObjC that would be [String removeVowels:myString]).
In this case the instance likely calls the class method, so both are available.
i.e.
public function toLower():String{
return String.toLower();
}
public static function toLower( String inString):String{
//do stuff to string..
return newString;
}
basically, myString.toLower() calls [String toLower:ownValue]
There's no definitive answer, but if you feel like shoving a class method in would improve your code, give it a shot, and bear in mind that a class method will only let you use other class methods/variables.
class methods
are methods which are declared as static. The method can be called without creating an instance of the class. Class methods can only operate on class members and not on instance members as class methods are unaware of instance members. Instance methods of the class can also not be called from within a class method unless they are being called on an instance of that class.
Instance methods
on the other hand require an instance of the class to exist before they can be called, so an instance of a class needs to be created by using the new keyword. Instance methods operate on specific instances of classes. Instance methods are not declared as static.
In Objective-C all methods start with either a "-" or "+" character.
Example:
#interface MyClass : NSObject
// instance method
- (void) instanceMethod;
+ (void) classMethod;
#end
The "+" and "-" characters specify whether a method is a class method or an instance method respectively.
The difference would be clear if we call these methods. Here the methods are declared in MyClass.
instance method require an instance of the class:
MyClass* myClass = [[MyClass alloc] init];
[myClass instanceMethod];
Inside MyClass other methods can call instance methods of MyClass using self:
-(void) someMethod
{
[self instanceMethod];
}
But, class methods must be called on the class itself:
[MyClass classMethod];
Or:
MyClass* myClass = [[MyClass alloc] init];
[myClass class] classMethod];
This won't work:
// Error
[myClass classMethod];
// Error
[self classMethod];
CLASS METHODS
A class method typically either creates a new instance of the class or retrieves some global properties of the class. Class methods do not operate on an instance or have any access to instance variable.
INSTANCE METHODS
An instance method operates on a particular instance of the class. For example, the accessors method that you implemented are all instance methods. You use them to set or get the instance variables of a particular object.
INVOKE
To invoke an instance method, you send the message to an instance of the class.
To invoke a class method, you send the message to the class directly.
Source: IOS - Objective-C - Class Methods And Instance Methods
Class methods can't change or know the value of any instance variable. That should be the criteria for knowing if an instance method can be a class method.
Also remember, the same idea applies to variables. You will come across terms like static, member, instance, class and so on when talking about variables the same as you would for methods/functions.
It seems the common term in the Obj-C community is ivar for instance variable, but I am not an Obj-C guy, yet.
An update to the above answers, I agree instance methods use an instance of a class, whereas a class method can be used with just the class name.
There is NO more any difference between instance method & class method after automatic reference counting came to existence in Objective-C.
For Example[NS StringWithformat:..] a class method & [[NSString alloc] initwihtformat:..] an instance method, both are same after ARC
Note: This is only in pseudo code format
Class method
Almost does all it needs to do is during compile time. It doesn't need any user input, nor the computation of it is based on an instance. Everything about it is based on the class/blueprint——which is unique ie you don't have multiple blueprints for one class. Can you have different variations during compile time? No, therefore the class is unique and so no matter how many times you call a class method the pointer pointing to it would be the same.
PlanetOfLiving: return #"Earth" // No matter how many times you run this method...nothing changes.
Instance Method
On the contrary instance method happens during runtime, since it is only then that you have created an instance of something which could vary upon every instantiation.
initWithName: #"John" lastName: #"Doe"Age:12 #"cool"
initWithName: #"Donald" lastName: #"Drumpf"Age:5 attitude:#"He started"
initWithName: #"President" lastName: #"Obama"Age:54 attitude: #"Awesome"
//As you can see the value can change for each instance.
If you are coming from other languages Static methods are same as class methods.
If you are coming from Swift, type methods are same as class methods.
Adding to above answers
Class method will work on class, we will use this for general purpose where like +stringWithFormat, size of class and most importantly for init etc
NSString *str = [NSString stringWithFormat:#"%.02f%%",someFloat];
Instance Method will work on an instance of a class not on a class like we are having two persons and we want to get know the balance of each separately here we need to use instance method. Because it won't return general response. e.g. like determine the count of NSSArray etc.
[johnson getAccountBalance];
[ankit getAccountBalance];