shared static function in objective-c iphone? - iphone

I need to calculate from pricing based on some business rules and I do not want to duplicate this across several ViewControllers. Coming from a .Net world I would use a static method on a class to do this. What is a similar solution in Objective-C?

A class method most likely - ie. a function in the interface declared with a + at the start.
#implementation PriceCalculator
+ (float)calculatePrice:(float)param1 {
return param1*4.0;
}
#end
(and a similar #interface in a header file)
which is called like so:
price = [PriceCalculator calculatePrice:3.0];

If you don't need to override the behavior in subclasses, you can just write a C function, which is the equivalent of a static method in Java and C#. Otherwise, do as JosephH suggested, and write a class method. Here's his example rewritten as a C function:
float calculatePrice(float amount)
{
return amount * 4.0;
}
The function could be declared/implemented in the .h/.m pair of files for one of your classes if that's convenient, but you could also create a separate .h/.m pair that just contains C functions if you like.

Related

How to create global protocol method in iPhone?

I create one protocol method and I want to implement the protocol method in multiple classes
#protocol XMLProtocol <NSObject>
- (BOOL) hasAllRequiredAttributes :(NSDictionary*)attributeMap;
#end
I have use this following class methods
#import "XMLProtocol.h"
#interface MachineA : NSObject<XMLProtocol>
and its implementation method I will implement the protocol method
- (BOOL) hasAllRequiredAttributes:(NSDictionary *)attributeMap {
return false;
}
and also i use this protocol method in another class
#import "XMLProtocol.h"
#interface MachineB : NSObject<XMLProtocol>
and its implementation method I will implement the protocol method
- (BOOL) hasAllRequiredAttributes:(NSDictionary *)attributeMap {
return false;
}
my thought is where should I call the protocol method. I totally confused. How can i do this.
One way you can define a global implementation for your protocol method (if I understand correctly what you are asking) is defining a category on NSObject:
#implementation NSObject (XMLProtocol)
- (BOOL) hasAllRequiredAttributes:(NSDictionary *)attributeMap {
return false;
}
By doing like this every object will have that method. Don't know if this is sensible, but it's a way.
Another way would be defining a Machine base class from which both MachineA and MachineB derive; the protocol method would be defined in the base class:
#interface Machine : NSObject <XMLProtocol>
...
#implementation Machine
- (BOOL) hasAllRequiredAttributes:(NSDictionary *)attributeMap {
return false;
}
....
#end
#interface MachineA : Machine
...
and any derived class could redefine it, if required.
This is not as "global" as the NSObject category, but it might be a better solution if you can define a base class for all the classes that need implement that protocol.
You must write the implementation of the method in both classes, even if the implementations are identical.
In you particular situation notification would be great help full to you. Notification works same like protocol except it broadcast the message. so you could receive that call on multiple classes.
if you want to done with protocol than also it is very easy. just make sure you current view controller is referenced with delegate (i.e. obj.delegate = self). you can implement that on -viewWillAppear. so your current view controller only get called of that method. Delegate will only call one method at one place in a time.
IMHO a global protocol is not very good design for something as specific as XML parsing.
A #protocol doesn't have any implementation part by itself. It is just an API definition, think of it like a contract. Any class that conforms to a protocol must implement its mandatory methods and properties (there is a #optional clause).
For instance, you may have two implementations of an XML parser, one that works in iOS 4 and another one that works in iOS 5+. Both declared as conforming to XMLProtocol protocol. And both implementing - (BOOL) hasAllRequiredAttributes :(NSDictionary*)attributeMap;, let's imagine that they need to implement it differently.
Thanks to being compliant to XMLProtocol you don't care about the implementation details. You know that you'll pass an attribute map and you'll obtain a boolean indicating if it has all required attributes.
You call the method where ever you use those classes:
id <XMLProcotol> parser;
if (iOS4) {
parser = [[OldXMLParser alloc] initWithString:<#...#>];
} else {
parser = [[NewXMLParser alloc] initWithString:<#...#>];
}
/* you call the method without caring which parser class
* has been actually created thanks to the protocol
*/
if ([parser hasAllRequiredAttributes:theMap]) {
...
}
If the implementation of the methods are identical, you can make both a subclass of a common parent class that implements the common methods, present or not in the protocol.

iOS -- use macros to forward a bunch of messages?

ForwardInvocation does exist, but it is slow and has the annoying problem of compiler warnings. So that got me to thinking -- is there a way to use macroes to quickly implement a bunch of getter methods that get the property in question from another object?
For example, if I have a Car object, it might want to implement the following:
Car.h:
#class SparkPlug;
#class Engine;
. . .
-(int) nPistons;
-(float) horsepower;
-(SparkPlug*) sparkPlug;
Car.m:
. . .
-(int) nPistons {
return self.engine.nPistons;
}
-(float) horsepower {
return self.engine.horsepower;
}
-(SparkPlug*) sparkPlug {
return self.engine.sparkPlug;
}
Question -- would it be possible to set up some macroes so that by making one change somewhere, I could add another such method to both the header and implementation files?
e.g. MagicForwardingMacro (nPistons, int, engine);
Ideally, in such a way that the macroes would be reusable if I later wanted to later use a similar strategy to get the firstName, lastName, placeOfBirth, and dateOfBirth properties of a Person from his or her birthCertificate.
The easiest way is probably to add the methods dynamically:
Add the properties to a category so the compiler doesn't complain too much.
Clone a suitable IMP in +[NSObject resolveInstanceMethod:]. You'll need to poke the Objective-C runtime.
Elaborating on the second step:
For each type, add a method like
-(int)getEngineInt {
return (int()(id,SEL))(objc_msgSend)(engine, _cmd);
}
Note that for structs you need objc_msgSend_stret and for floats/doubles you might need objc_msgSend_fpret (I think you only need it on i386; not sure about AMD64). The easy hack to support both the simulator and device is something like (I forget the macro name GCC uses...)
#if __i386
#define objc_msgSend_fpret objc_msgSend
#endif
Now to implement +resolveInstanceMethod:, you need to know the class you're forwarding to ahead of time. Let's say it's Engine.
+(BOOL)instancesRespondToSelector:(SEL)name
{
return [Engine instancesRespondToSelector:name];
}
+(BOOL)resolveInstanceMethod:(SEL)name
{
// Do we want to super-call first or last? Who knows...
if ([super resolveInstanceMethod:name]) { return YES; }
// Find the return type, which determines the "template" IMP we call.
const char * returntype = [Engine instanceMethodSignatureForSelector:name].methodReturnType;
if (!returnType) { return NO; }
// Get the selector corresponding to the "template" by comparing return types...
SEL template = NULL;
if (0 == strcmp(returntype,#encode(int))
{
sel = #selector(getEngineInt);
}
else if (0 == strcmp(Returntype,#encode(float))
{
...
}
if (!sel) { return NO; }
Method m = class_getInstanceMethod(self,template);
return class_addMethod(self, name, method_getImplementation(m), method_getTypeEncoding(m));
}
Alternatively, there's a slightly undocumented method -forwardingTargetForSelector: which may be fast enough for your needs.
EDIT: Alternatively, you can loop over the properties/methods dynamically. There doesn't appear to be an obvious way to introspect categories, but you can define them in a protocol, do something like #interface Engine:NSObject<Engine> ... #interface Car(DynamicEngine)<Engine> and use objc_getProtocol("Engine") and then protocol_copyMethodDescriptionList()/protocol_copyPropertyList() to get the methods, and then add the getters. I'm not sure if properties are added to the "method description list". Also note that the "copy" functions do not copy methods/properties from superclasses, which (in this case) is what you want.
Sadly, I don't think Objective-C 2.0 properties will work for you because I don't think you can specify any kind of forwarding in the property declaration.
You can't have one macro that will insert text in two different places. However, you can use two macros like so:
//This could also take the third argument and discard it, if you like
#define FORWARDI(type, prop) - (type)prop;
#define FORWARDM(type, prop, owner) - (type)prop { return owner.prop; }
//In the header...
FORWARDI(float, nPistons)
//In the implementation...
FORWARDM(float, nPistons, self.engine)
If you don't mind the methods not showing up in the header file (for example, if you will only use these methods inside the class's implementation itself), you can just as well use the implementation file macro by itself.
This is agnostic to the type of the owner, but it should work with any expression.
I'm getting close to what I want. Some nagging details remain:
ForwardingInclude.h:
// no include guard; we want to be able to include this multiple times
#undef forward
#ifdef IMPLEMENTATION
#define forward(a, b, c) -(a) b { return [[self c] b]; }
#else
#define forward(a, b, c) -(a) b;
#endif
CarForwarding.h:
// again, no include guard
#include ForwardingInclude.h
forward(int, nPistons, engine)
forward(SparkPlug* sparkPlug, engine)
Car.h:
#interface Car: SomeSuperclass {
// some ivars
}
. . .
#include CarForwarding.h
Car.m:
. . .
#implementation Car
#define IMPLEMENTATION
#include CarForwarding.h
The nagging details:
1) I don't like that #define IMPLEMENTATION line. I want CarForwarding.h to somehow automatically detect whether or not it is currently being included inside an implementation.
2) It would be waaaaaay cool if I could have the stuff defined in the forwarding file somehow also appear in human-readable form in the header. Or better yet -- write the "forward" definitions directly into the Car.h file somehow, so I don't need the CarForwarding.h file at all.

objective-c static/class method definition - what is the difference between "static" and "+"?

I'm wondering if someone can explain the difference between the functions below. They are both static, but require different signature syntaxes. I'm wondering how these are handled at runtime, and why you would use one over the other?
+ (int) returnInt:(NSString *)myString1 withString2:(NSString *)myString2
{
if ([myString1 isEqualToString:myString2])
return 1;
else
return 0;
}
vs.
static int returnInt(NSString *myString1, NSString *myString2)
{
if ([myString1 isEqualToString:myString2])
return 1;
else
return 0;
}
Thanks!
Unlike in (say) C++, where static member functions are just ordinary functions in the class' namespace, Objective-C has proper class methods.
Since classes are objects, calling a class method is really like calling an instance method on the class. The main consequences of this are:
1) Calling a class method incurs a slight (although generally inconsequential) overhead, since method calls are resolved at runtime.
2) Class methods have an implicit 'self' argument, just like instance methods. In their case, 'self' is a pointer to the class object.
3) Class methods are inherited by subclasses.
together, 2 and 3 mean that you can do stuff like this with a class method:
+ (id) instance
{
return [[[self alloc] init] autorelease];
}
then create a new class that inherits the method and returns a new instance of itself, rather than the superclass.
I believe that marking an ordinary c function static will just make it unavailable to files other than the one it's defined in. You'd generally do this if you wanted to make a helper function that is only relevant to one class and you wanted to avoid polluting the global namespace.

In Objective-C, when should I use class methods and when should I use instance methods?

What is the difference between class and instance methods in Objective-C and when should I use each of them?
Using the tired old Car analogy...
Think of a Class like it is a factory that makes Instances of the class. For example, you might have a Car class and you might declare a method like:
+ carWithColor: (NSColor *) aColor;
And that method would then create a new Car instance, set the color, and return it:
+ carWithColor: (NSColor *) aColor
{
Car *aCar = [[[self alloc] init] autorelease];
[aCar paintWithColor: aColor];
return aCar;
}
Now, that Car class would then declare an instance method that allows the car to be painted. Why an instance method? Because every car can have a different color (and the color of the car would likely be stored in an instance variable).
- (void) paintWithColor: (NSColor *) aColor
{
... do your paint stuff here ...
}
This is explained in the Objects, Classes, and Messaging section of the Objective-C documentation.
This is an old post, but since it comes up first in a Google search I thought I'd add to it.
I'm not going to talk about class methods used as factory methods. I'd like to talk about their use in utility methods. You can/should use class methods for utility methods that are independent of state. What does this mean? Well, for instance, if you're formatting a date the same way for all instances, that's a utility method that should be a class method. Think of the utility method like a screw driver. You don't need to make a new instance of the screw driver every time you want to do something with it. The screw driver remains constant. So, for instance, I have a class that includes a private method that generates a string of emDashes used for displaying to the view. This method is not dependent on state and hence will not vary by instance. Think of class utility methods like constants.
+ (NSString *)emDashString {
return #" \u2014 \u2014 \u2014 \u2014 \u2014 \u2014 \u2014 \u2014 \u2014";
}
You can call this method generically within the class (it's private in my example) like this:
NSString *string = [[self class] emDashString ];
I've deliberately chosen a bit of a trivial example to drive the point home. You would only bother making this a class utility method if you're going to need this string more than once in your class. Notice that instead of referring to the class by name I call it generically with [self class] since this is called internally. If it's exposed and you want to call it from another class then refer to it by the class name as usual.
Instance methods do things with instances of a class:
NSString *myString;
myString = [[[NSString alloc] initWithString:#"Hello, world."] autorelease];
NSLog (#"myString's length: %u", [myString length]); // instance method
Class methods can do class-specific things without relying on an object instance, often returning an instance of the class, or some other class-specific result:
NSLog (#"%#", [NSString stringWithString:#"Hello, world."]); // class method
I think it may be rare to see class methods that do not return something.
You don't need to implement both. Either option is available to you as you design your class.
An instance method can operate on an instance of the class. This can get or set a property, or cause behavior you only want that instance to perform. You need to actually have an instance to use it. These can either use or change the state of the instance.
// Notional instance methods
myHouse.color = blueColor;
[myCar accelerate];
speed = myCar.speed;
A class method operates on the notion that the class exists. It can be used to create an instance, or perform a calculation that doesn't depend on having an instance. You might have a class for custom math helper, that essentially contains functions.
// Notional class method uses
myString = [NSString stringWithFormat:#"&f", floatToConvert];
myResult = [MyMathHelper MyFunctionWithInput:myInput];
Class method signatures are prefixed with +, instance methods with - so in your header file declarations would look something like this:
-(void)setAllThings:(NSArray*)things; //instance method
+(void)setAllClassThings:(NSArray*)things; //class method
And of course the same rules apply when you define the methods in the .m file.

What type of variable do I use to store mathematical operator?

I'm trying to put buttons that have operators on them, like / * +, etc. I want to store the operator in such a way that I can use it in an expression, like 1 var 2 = 8
I would like to avoid having to use a different method for each operator, so an operator var would be my best option, I think. Objective-C for iPhone
The usual OO way to do this is to create a class "mathOperator" that has a method "performOp" taking two parameters, then inherit different classes from it that represent the different operations. I'm not an expert in objective-C, so my syntax is probably a bit off, but I think you'd write something like:
result = [var On:arg1 And:arg2];
for example
result = [var On:2 And:3];
would set result to 5 or 6 depending on whether var was set to add or mul. The implementation would look like (again, very roughly):
#interface Add: mathOperator
-(int)On: (int)arg1 And: (int)arg2;
#end
...
#implementation Add
-(int)On: (int)arg1 And: (int)arg2 {
return arg1 + arg2;
}
and of course similar for the other operators:
#implementation Mul
-(int)On: (int)arg1 And: (int)arg2 {
return arg1 * arg2;
}
Read ch 5 in Cocoa Design Patterns. The approach used is to define "Command" classes that will perform each operation defined as a class method "execute". Then you can dynamically perform the operation by obtaining the appropriate class by using the following
commandName = [NSString stringWithFormat:#"MY%#Command", [commandString capitalizedString]];
commandClass = NSClassFromString(commandName);
result = [commandClass executeWithXValue:x yValue:y];
The way i'd do it is to make methods for each type of arithmatic and pass the numbers into them. Then instead of all that with the variable call the function.
There's no such thing in C. You'll have to use a selector which invokes a method to do what you want.