Problems with Pass-by-Reference in ObjC - objective-c

I wanna do pass by reference in ObjC.
Here is the illustration of the scenario:
// MainClass.h
#interface MainClass
{
Board *board;
OtherClass *other;
}
#end
// MainClass.m
#implementation MainClass
- (id)init
{
if (self = [super init])
{
board = [[Board alloc] init];
other = [[OtherClass alloc] initOtherClassWithBoard: board];
}
return self
}
#end
// Other class.h
#interface OtherClass
{
Board *refBoard;
}
- (void)initOtherClassWithBoard: (Board*)ref;
#end
#implementation OtherClass
- (id)initOtherClassWithBoard: (Board*)ref
{
if (self = [super init])
{
refBoard = ref;
}
return self;
}
#end
So my question is does my OtherClass is holding a reference Board from MainClass?
Or OtherClass's Board is a copy but not a reference.
If I wanna do a reference then how should I change it?
EDIT:
What if I add this on both classes
#property (nonatomic, retain) Board *board;

You always refer to objects in Objective-C via pointers, a.k.a. references. Therefore, objects are always passed by reference in Objective-C.

It's a reference. It won't be a copy unless you do something to make it a copy (like use #property (copy) or send it a copy message).

Related

Objective-C : Calling a property of a class in another

I'm using Cocos2d and I can not access properties of an object from another one.
Here I just want to get the hitpoints of a ship form a scene. It fails and returns an error : uncaught exception 'NSInvalidArgumentException', reason: '-[CCSprite hitpoints]: unrecognized selector...
As hitpoints is declared in the interface of the class Ship I can't figure out why.
The only thing I understand is that it's a inhéritance issue.
Let's show some code :
Ship.h
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#interface Ship : CCSprite {
int hitpoints;
}
#property (nonatomic, assign) int hitpoints;
- (id)init;
#end
Then Ship.m
#import "Ship.h"
#implementation Ship
#synthesize hitpoints;
- (id)init
{
hitpoints = 3;
self = [CCSprite spriteWithImageNamed:#"ship.png"];
return self;
}
#end
In the Scene.m
#import "Ship.h"
#implementation Scene
{
Ship *_player;
}
- (id)init
{
_player = [[Ship alloc] init];
[self addChild:_player];
// ERROR HERE
NSLog(#"%s = %d", "_player hp", [_player hitpoints]);
}
Thank you.
I suspect the issue is with your init method; you shouldn't be accessing properties until the object is initialised and you should be calling [super initWith...] instead of the class creation method.
I would suggest the following changes:
Ship.h:
#interface Ship : CCSprite
#property (nonatomic, assign) int hitpoints;
#end
Ship.m:
#import "Ship.h"
#implementation Ship
#synthesize hitpoints;
- (id)init
{
self = [super initWithImageNamed:#"ship.png"];
if (self) {
self.hitpoints = 3;
}
return self;
}
#end
Always use object.property when referencing a property, even when object == self.
This:
- (id)init
Means "a method that returns any kind of object, which is called init".
This:
self = [CCSprite spriteWithImageNamed:#"ship.png"];
Means "create an instance of CCSprite". You then return that instance.
So _player ends up being an instance of CCSprite. CCSprite does not implement hitpoints so the exception is raised.
What are you actually trying to achieve? A subclass of CCSprite? trojanfoe has covered how to write a proper init for that. Things I think you need to know:
all classes look the same at runtime;
declaring the type of class pointers helps humans and the compiler to check your code but doesn't change the code generated;
some Objective-C patterns (probably most notably including class clusters) are built around init being able to return any kind of class — it's a useful feature, not a misfeature.

Objective C arc -- keeping a reference to a Class

I want to have an ivar of type Class, and to keep the pointer around after it is passed in. But no matter what I do, arc will not let me do that. For instance, if I declare
#property (nonatomic, strong) Class myClass;
the compiler decides that myClass should be unsafe_unretained. And if I try this:
-(id) initWithClass: (Class) passedInClass {
if ((self = [super init])) {
self.myClass = passedInClass;
}
return self;
}
what happens is that even if the class is non-nil in the calling code, it is nil within the init method.
Short of turning off arc, is there any way to get around this?
EDIT: This question is just wrong. It does work. See the accepted answer.
Works as advertised with Xcode 4.3.2 targeting 10.7 and 5.1:
#interface MOYNObject : NSObject
#property (nonatomic, strong, readwrite) Class myClass;
#end
#implementation MOYNObject
#synthesize myClass;
- (id)initWithClass:(id)pClass
{
self = [super init];
if (self != nil)
self.myClass = pClass;
assert(self.myClass);
CFShow((__bridge const void*)self.myClass);
return self;
}
#end
int main(int argc, const char* argv[]) {
#autoreleasepool {
MOYNObject * o = [[MOYNObject alloc] initWithClass:[NSString class]];
// ...
}
return 0;
}
Are you ahead of or behind 4.3.2?

Should I "Pull Up" Refactor

I have some very small classes that I feel should be "pulled up" but the methods are so small I'm not sure. For example, the only thing that's meaningfully different is the body of the buildFromJSON: selector.
I acknowledge that this is similar to:
Pull-up refactoring, Objective-C
but I feel my question is specific to refactoring very small classes/methods.
Also, not sure it relates to my particular code example, but I'm wondering if a child class says it conforms to a protocol, whether it's enough that it's parent actually supply the implementation of required selector(s)?
#implementation AsyncFoo
-(void)dealloc {
[clientDelegate release];
[super dealloc];
}
- (id)initWithDelegate: (id <ServiceClientProtocol>) delegate {
if((self = [super init])) {
clientDelegate = [delegate retain];
}
return self;
}
- (void)buildFromJSON:(NSString*)jsonResponseString {
[clientDelegate serviceComplete:[RestAdapter buildFooArray: jsonResponseString]];
}
#end
#implementation AsyncBar
-(void)dealloc {
[clientDelegate release];
[super dealloc];
}
- (id)initWithDelegate: (id <ServiceClientProtocol>) delegate {
if((self = [super init])) {
clientDelegate = [delegate retain];
}
return self;
}
- (void)buildFromJSON:(NSString*)jsonResponseString {
[clientDelegate serviceComplete:[RestAdapter buildBarArray:jsonResponseString]];
}
#end
Answers including code example would be great.
EDIT: Post accepted answer I'd like to add that since I was able to subclass, the derived classes did not need to declare that they conformed to protocol:
#interface Async : NSObject <ModelBuilderProtocol> {
id <ServiceClientProtocol> clientDelegate;
}
- (void)buildFromJSON:(NSString*)jsonResponseString;
#end
#interface AsyncArtistById : Async
#end
You don't normally retain your delegates as this can cause a retain cycle.
Knowing what I know from looking at your example I would probably implement like this:
The super class
// Async.h
#interface Async : NSObject
#property (nonatomic, assign) id<ServiceClientProtocol> delegate;
- (void)buildFromJSON:(NSString *)jsonResponseString;
#end
// Async.m
#implementation Async
#synthesize delegate = _delegate;
- (id)initWithDelegate:(id<ServiceClientProtocol>)delegate
{
self = [super init];
if(self) {
_delegate = delegate;
}
return self;
}
- (void)buildFromJSON:(NSString *)jsonResponseString
{
// This will ensure that we over ride this method in a sub class
[NSException raise:NSInternalInconsistencyException
format:#"You must override %# in a subclass", NSStringFromSelector(_cmd)];
}
#end
Concrete subclass AsyncFoo
// AsyncFoo.h
#interface AsyncFoo : Async
#end
// AsyncFoo.m
#implementation AsyncFoo
- (void)buildFromJSON:(NSString *)jsonResponseString
{
[self.delegate serviceComplete:[RestAdapter buildFooArray: jsonResponseString]];
}
#end
Concrete subclass AsyncBar
// AsyncBar.h
#interface AsyncBar : Async
#end
// AsyncBar.m
#implementation AsyncBar
- (void)buildFromJSON:(NSString *)jsonResponseString {
[self.delegate serviceComplete:[RestAdapter buildBarArray:jsonResponseString]];
}
#end

making class members properties and synthesizing them

Is it safe to say that if a class member does not need getter or setter functions then there's no point in making them properties and synthesizing them?
Well, yes, but often properties can be helpful in the implementation itself even if the properties won't be set outside of the implementation.
For example, suppose you had
#interface SomeObject : NSObject {
NSThing *thing;
}
#end
#implementation SomeObject
- (id)init {
if((self = [super init]))
thing = [[NSThing someThing] retain];
return self;
}
- (void)someMethod {
if(thing)
[thing release];
thing = [[NSThing someOtherThing] retain];
}
// etc etc
#end
Why would you want to bother having to check if thing had been allocated, release thing, set it to something else, and then retain it again, when you could simply do:
- (id)init {
if((self = [super init]))
[self setThing:[NSThing someThing]];
return self;
}
- (void)someMethod {
[self setThing:[NSThing someOtherThing]];
}
If you don't want to make these properties accessible outside of your class, you can use a category
#interface SomeObject ()
#property (retain) NSThing *thing;
#end
in your .m file.

Help with a method that returns a value by running another object's method

I have a Class that runs the following method (a getter):
// the interface
#interface MyClass : NSObject{
NSNumber *myFloatValue;
}
- (double)myFloatValue;
- (void)setMyFloatValue:(float)floatInput;
#end
// the implementation
#implementation
- (MyClass *)init{
if (self = [super init]){
myFloatValue = [[NSNumber alloc] initWithFloat:3.14];
}
return self;
}
// I understand that NSNumbers are non-mutable objects and can't be
// used like variables.
// Hence I decided to make make the getter's implementation like this
- (double)myFloatValue{
return [myFloatValue floatValue];
}
- (void)setMyFloatValue:(float)floatInput{
if ([self myFloatValue] != floatInput){
[myFloatValue release];
myFloatValue = [[NSNumber alloc] initWithFloat:floatInput;
}
#end
When I mouse over the myFloatValue object during debugging, it does not contain a value. Instead it says: "out of scope".
I would like to be able to make this work without using #property, using something other than NSNumbers, or other major changes since I just want to understand the concepts first. Most importantly, I would like to know what mistake I've apparently made.
I can see a couple of mistakes:
The line #implementation should read #implementation MyClass
The function setMyFloatValue is missing a closing ] and } —it should read:
- (void)setMyFloatValue:(float)floatInput{
if ([self myFloatValue] != floatInput){
[myFloatValue release];
myFloatValue = [[NSNumber alloc] initWithFloat:floatInput];
}
}
I've just tested it in Xcode and it works for me with these changes.
Why not just set property in interface and synthesize accessors in implementation?
#interface MyClass : NSObject {
float *myFloat
}
#property (assign) float myFloat;
#end
#implementation MyClass
#synthesize myFloat;
#end