If I add a category method to a class, such as NSXMLNode:
#interface NSXMLNode (mycat)
- (void)myFunc;
#end
Will this category method also be available in subclasses of NSXMLNode, such as NSXMLElement and NSXMLDocument? Or do I have to define and implement the method as a category in each class, leading to code duplication?
It's available in subclasses!
It will be available in subclasses as Yuji said.
However, you should prefix your method such that there is no risk that it conflicts with any method, public or private.
I.e.:
-(void) mycat_myMethod;
Yes it will be available, I though of check it by code and here it is:
#import <Foundation/Foundation.h>
#interface Cat1 : NSObject {
}
#end
#implementation Cat1
- (void) simpleMethod
{
NSLog(#"Simple Method");
}
#end
#interface Cat1 (Cat2)
- (void) addingMoreMethods;
#end
#implementation Cat1 (Cat2)
- (void) addingMoreMethods
{
NSLog(#"Another Method");
}
#end
#interface MYClass : Cat1
#end
#implementation MYClass
#end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
MYClass *myclass = [[MYClass alloc] init];
[myclass addingMoreMethods];
[myclass release];
[pool drain];
return 0;
}
The output is:
Another Method
Related
Given the following class,
#interface MyBaseClass : NSObject
-(void)printName
+(NSString*)printableName
#end
how can I call the class method +printableName from within the instance method -printName without explicitly referring to MyBaseClass? [[self class] printableName] doesn't compile.
The idea is that subclasses will override +printableName so -printName should polymorphically invoke the appropriate +printableName for its class.
Declare MyBaseClass as
#interface MyBaseClass : NSObject
and your [[self class] name] should compile.
This compiles for me:
#interface MyBaseClass : NSObject
-(void)printName;
+(NSString*)printableName;
#end
#implementation MyBaseClass
-(void)printName
{
[[self class] printableName];
}
+(NSString*)printableName {
return #"hello";
}
#end
Have you tried [object_getClass(this) printableName]?
(But you realize, of course, that you could also just create a version of
-(NSString*)printableName2 {
return [MyBaseClass printableName];
}
in each of your classes and call [self printableName2]?)
From what you are describing, it should work. As you didn't offer your implementation, we won't be able to tell, what is wrong.
Based on this question, I wrote an example code for polymorphism in Objective-C.
It contains inheritance-based polymorphism, but also polymorphism based on formal and informal protocols. May you want check your code against it.
here an excerpt:
#import <Foundation/Foundation.h>
/*
* 1.: Polymorphism via subclassing
*/
#interface MyBaseClass : NSObject
-(void)printName;
+(NSString*)printableName;
#end
#implementation MyBaseClass
+(NSString *)printableName
{
return NSStringFromClass(self);
}
-(void)printName
{
NSLog(#"%#", [[self class] printableName]);
}
#end
#interface MySubBaseClass : MyBaseClass
#end
#implementation MySubBaseClass
#end
//...
int main (int argc, const char * argv[])
{
/*
* 1.: Polymorphism via subclassing. As seen in any Class-aware OO-language
*/
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
MyBaseClass *myBaseObject = [[MyBaseClass alloc] init];
[myBaseObject printName];
[myBaseObject release];
MySubBaseClass *mySubBaseObject = [[MySubBaseClass alloc] init];
[mySubBaseObject printName];
[mySubBaseObject release];
//...
[pool drain];
return 0;
}
I was wondering if it's possible to store a reference to an anonymous function (block) as an instance variable in Objective-C.
I know how to use delegation, target-action, etc. I am not talking about this.
Sure.
typedef void(^MyCustomBlockType)(void);
#interface MyCustomObject {
MyCustomBlockType block;
}
#property (nonatomic, copy) MyCustomBlockType block; //note: this has to be copy, not retain
- (void) executeBlock;
#end
#implementation MyCustomObject
#synthesize block;
- (void) executeBlock {
if (block != nil) {
block();
}
}
- (void) dealloc {
[block release];
[super dealloc];
}
#end
//elsewhere:
MyCustomObject * object = [[MyCustomObject alloc] init];
[object setBlock:^{
NSLog(#"hello, world!");
}];
[object executeBlock];
[object release];
Yes, you most certainly can store a reference to a (copy) of an Objective-C block. The variable declaration is a little bit hairy, like C function pointers, but beyond that it's no problem. For a block that takes and id and returns void:
typedef void (^MyActionBlockType)(id);
#interface MyClass : NSObject
{
}
#property (readwrite,nonatomic,copy) MyActionBlockType myActionBlock;
#end
will do the trick.
I have a program where inheritance of protocols are there say:
#protocol A
-(void)methodA
#end
The protocol which inherits:
#protocol B<A>
-(void)methodB
#end
The class which implements #protocolA method is
#interface classB<B>
#end
#implementation classB
-(void)methodA
{
//somecode
}
#end
Now i wanted the methodA to be called from Some other class:
#implementation SomeotherClass
{
//call of methodA
//????
id<A>obj=[[classB alloc]init];//i have tried it
[obj methodA];// even this is not working
}
How to do that?
Just send the message as usual:
SomeotherClass *obj = [[[SomeotherClass alloc] init] autorelease];
[obj methodA];
Since instances of classB implement protocol B, they also claim to respond to -methodA.
The following compiles and runs without any problems:
MyClass.h:
#import <Foundation/Foundation.h>
#protocol A
-(void) methodA;
#end
#protocol B <A>
-(void) methodB;
#end
#interface MyClass : NSObject <B>
{
}
#end
MyClass.m:
#import "MyClass.h"
#implementation MyClass
-(void) methodA
{
NSLog(#"%s", __PRETTY_FUNCTION__);
}
-(void) methodB
{
NSLog(#"%s", __PRETTY_FUNCTION__);
}
#end
the code:
MyClass *obj = [[MyClass alloc] init];
[obj methodA];
[obj methodB];
[obj release];
You don't say how it fails to work. I would guess that there's a compilation error as you don't implement methodB in your classB.
Another possibility: what happens after you've initialised classB in SomeOtherClass? Are you sure that you get a valid object back? If it returned a nil the run time would be perfectly within its rights to do nothing when you sent the methodA message to it.
I am trying to write a cocoa touch static library.
To keep it simple I would prefer not to use private variables within my interface file.
The code right now looks like this:
interface file (myView.h):
#interface myView: UIView {
NSTimer * myTimer;
}
#end
implementation file (myView.h)
#implementation myView
#end
This NSTimer pointer is just a private variable so I tried this:
(not working)
interface file (myView.h):
#interface myView: UIView {
}
#end
implementation file (myView.h)
NSTimer * myTimer;
#implementation myView
#end
It seems to work however it turned out that the timer is now a static variable.
Am I doing sth wrong or is there no solution?
You can't define instance variables in your implementation file.
A possible solution is to have a private structure containing the private variables and have one publicly declared private variable pointing to this private structure:
#interface MyView {
void *privateData;
}
Implementation file:
typedef struct {
NSTimer *myTimer;
} PrivateData;
#implementation MyView()
#property (readonly) PrivateData *privateData;
#end
#implementation MyView
- (id) init {
if (self = [super init]) {
privateData = malloc(sizeof(PrivateData));
self.privateData->myTimer = nil; // or something else
}
return self;
}
-(PrivateData *) privateData {
return (PrivateData *) self->privateData;
}
- (void) myMethod {
NSTimer *timer = self.privateData->myTimer;
}
- (void) dealloc {
// release stuff inside PrivateData
free(privateData);
[super dealloc];
}
#end
It's not beautiful, but it works. Maybe there are better solutions.
Just a note; trying to hide iVar's for the sake of security is silly. Don't bother.
For simplicity's sake, though, it has value.
However, a couple of solutions:
(1) If targeting iPhone OS or 64 bit Cocoa, you can #synthesize the ivar:
Foo.h:
#interface Foo:NSObject
#property(readwrite, copy) NSString *publiclyReadwriteNoiVar;
#property(readonly, copy) NSString *publiclyReadonlyPrivatelyReadwriteNoiVar;
#end
Foo.m:
#interface Foo()
#property(readwrite, copy) NSString *privateProperty;
#end
#implementation Foo
#synthesize publiclyReadwriteNoiVar, publiclyReadonlyPrivatelyReadwriteNoiVar, privateProperty;
#end
(2) Use a private subclass kinda like class clusters:
Foo.h:
#interface Foo:NSObject
#end
Foo.m:
#interface RealFoo:Foo
{
.... ivars here ....
}
#end
#implementation RealFoo
#end
#implementation Foo
+ (Foo *) convenienceMethodThatCreatesFoo
{
.... realFoo = [[RealFoo alloc] init]; ....
return realFoo;
}
#end
Depending on the goal of your encapsulation, there's also the #private directive:
Access Modifiers
I need to develop a strategy pattern where i have a main class with other three classes where i need to refer to the objects of the other three classes using the main class object.To solve this is the strategy pattern will help me? If so please do give me the syntax in Objective-C?
You'll want to look at Objective-C's protocol mechanism. Here's a simple protocol with a single required method:
#protocol Strategy <NSObject>
#required
- (void) execute;
#end
Then you declare a class that fulfills that protocol:
#interface ConcreteStrategyA : NSObject <Strategy>
{
// ivars for A
}
#end
The implementation must provide the -execute method (since it was declared as #required):
#implementation ConcreteStrategyA
- (void) execute
{
NSLog(#"Called ConcreteStrategyA execute method");
}
#end
You can make a similar ConcreteStrategyB class, but I'm not going to show it here.
Finally, make a context class with a property maintaining the current strategy.
#interface Context : NSObject
{
id<Strategy> strategy;
}
#property (assign) id<Strategy> strategy;
- (void) execute;
#end
Here is the implementation. The method that delegates to the strategy's -execute method just happens to be called -execute as well, but it doesn't have to be.
#implementation Context
#synthesize strategy;
- (void) execute
{
[strategy execute];
}
#end
Now I'll make a few instances and put them to use:
ConcreteStrategyA * concreteStrategyA = [[[ConcreteStrategyA alloc] init] autorelease];
ConcreteStrategyB * concreteStrategyB = [[[ConcreteStrategyB alloc] init] autorelease];
Context * context = [[[Context alloc] init] autorelease];
[context setStrategy:concreteStrategyA];
[context execute];
[context setStrategy:concreteStrategyB];
[context execute];
The console output shows that the strategy was successfully changed:
2010-02-09 19:32:56.582 Strategy[375:a0f] Called ConcreteStrategyA execute method
2010-02-09 19:32:56.584 Strategy[375:a0f] Called ConcreteStrategyB execute method
Note that if the protocol does not specify #required, the method is optional. In this case, the context needs to check whether the strategy implements the method:
- (void) execute
{
if ([strategy respondsToSelector:#selector(execute)])
[strategy execute];
}
This is a common Cocoa pattern called delegation. For more information on delegation and other design patterns in Cocoa, see this.
Here's a bit more of a concrete example. You can put each item in a separate file. I've put it all in one file for ease of understanding.
// main.m
// StrategyWikipediaExample
//
// Created by steve on 2014-07-08.
// Copyright (c) 2014 steve. All rights reserved.
//
#import <Foundation/Foundation.h>
/**
Equivalent to Java Interface
All concrete Strategies conform to this protocol
*/
#protocol MathOperationsStrategy<NSObject>
- (void)performAlgorithmWithFirstNumber:(NSInteger)first secondNumber:(NSInteger)second;
#end
/**
Concrete Strategies.
Java would say they "Extend" the interface.
*/
#interface AddStrategy : NSObject<MathOperationsStrategy>
#end
#implementation AddStrategy
- (void)performAlgorithmWithFirstNumber:(NSInteger)first secondNumber:(NSInteger)second
{
NSInteger result = first + second;
NSLog(#"Adding firstNumber: %ld with secondNumber: %ld yields : %ld", first, second, result);
}
#end
#interface SubtractStrategy : NSObject<MathOperationsStrategy>
#end
#implementation SubtractStrategy
- (void)performAlgorithmWithFirstNumber:(NSInteger)first secondNumber:(NSInteger)second
{
NSInteger result = first - second;
NSLog(#"Subtracting firstNumer: %ld with secondNumber: %ld yields: %ld", first, second, result);
}
#end
#interface MultiplyStrategy : NSObject<MathOperationsStrategy>
#end
#implementation MultiplyStrategy
- (void)performAlgorithmWithFirstNumber:(NSInteger)first secondNumber:(NSInteger)second
{
NSInteger result = first * second;
NSLog(#"Multiplying firstNumber: %ld with secondNumber: %ld yields: %ld", first, second, result);
}
#end
#interface Context : NSObject
#property (weak, nonatomic)id<MathOperationsStrategy>strategy; // reference to concrete strategy via protocol
- (id)initWithMathOperationStrategy:(id<MathOperationsStrategy>)strategy; // setter
- (void)executeWithFirstNumber:(NSInteger)first secondNumber:(NSInteger)second;
#end
#implementation Context
- (id)initWithMathOperationStrategy:(id<MathOperationsStrategy>)strategy
{
if (self = [super init]) {
_strategy = strategy;
}
return self;
}
- (void)executeWithFirstNumber:(NSInteger)first secondNumber:(NSInteger)second
{
[self.strategy performAlgorithmWithFirstNumber:first secondNumber:second];
}
#end
int main(int argc, const char * argv[])
{
#autoreleasepool {
id<MathOperationsStrategy>addStrategy = [AddStrategy new];
Context *contextWithAdd = [[Context alloc] initWithMathOperationStrategy:addStrategy];
[contextWithAdd executeWithFirstNumber:10 secondNumber:10];
}
return 0;
}