Setter Getter oddness #property - iphone

I am having a really odd problem trying to set a simple float value to 1.
My property:
{
float direction;
}
#property(nonatomic)float direction;
Which is synthesized:
#synthesize direction;
I then used the following code:
- (void)setDirection:(float)_direction {
NSLog(#"Setter called with value of %f",_direction);
self->direction = _direction;
}
For testing purposes...
When I try to change the value with this,
[[w getCharacter] setDirection:1.0f];
where [w getCharacter] gives this:
return [[[self scene] gameLayer] player];
I get the warning, "setDirection not defined."
If I switch to dot notation([w getCharacter].direction), I get "confused by earlier errors, bailing out".
Here is where the weirdness starts. When I try to change the value, the debug message displays _direction = 0.00000. When I check the number later, its still 0.000. I am clearly trying to change it to 1, why is this not working?

The simplest explanation is that [w getCharacter] doesn't return the class of object you think it does. Only the class that has direction defined for it can respond to the message. You should test this by explicitly calling it with the class it defined for.
It is possible you did not include the header that defines the method.
Two probably unrelated issues:
The self->direction construction will work for a scalar value but it does an end run around the entire class concept. In this case just use: 'direction=_direction;` and it will set it directly.
Apple reserves all names that start with underscores for its own internal use. You should not use them because Objective-c has a global name space. It's possible that you can accidentally use an Apple variable that is defined deep within a framework. (This is why framework constants all start with NS,CF,CA etc.)

[Note: In the Comments, the author says to ignore this answer.
self.direction = 1; is syntactic sugar for
[self setDirection: 1];
when you call
-(void)setDirection:(float)_newDirection {
self.direction = _newDirection;
}
You seem to be telling the compiler or preprocessor to set up a recursive loop for you. The preprocessor (I think) changes it to this:
-(void)setDirection:(float)_newDirection {
[self setDirection: _newDirection];
}
If you call it simply
-(void)setDirection:(float)_newDirection {
direction = _newDirection;
}
the assignment should work (it worked for me just now)

Related

When to use . parameter and when to use [ ] to call a function in IOS

In iOS I have some confusion when calling a function.
-(void) function:(NSString*) str
{
selectedstring = str;
}
When calling the function.
When should I call like:
self.function = #"My name";
and
[self function:#"My name"]
What is the difference between (.) parameter and [ ]
in iOS function calling?
myVar = self.property is equivalent to myVar = [self property]
self.property = anotherVar is equivalent to [self setProperty:anotherVar]
Which you use is a matter of style.
Some people will tell you that the dot syntax should only be used for things that are actually defined as properties (with #property). I disagree with this. My opinion is that the dot syntax should be used whenever you're calling something that gets or sets a value, with minimal other side effects. Whether you have written the method yourself or synthesized a property to auto-generate it is not important: the important thing is whether it is related to getting and setting a value.
So myArray.count is fine, despite it not being a #property in the header file. But myURLConnection.start is not, since that doesn't return a value and is related to performing an action.
People do disagree with this. Some people don't like using dot syntax at all, since it could be confused with accessing the members of a struct (which also use .). Others are happy to use dot syntax for #propertys, but not for other methods.

Calling a method in Objective-C that references another class file

I am trying to call a method that checks whether the player is bigger or smaller than the enemy. (this is a fish game)
In EnemyFish.m I am using this method
-(void) compareSize:(Player*)player{
if (self.fSize > player.pSize){
isBigger = true;
}
else{
isBigger = false;
}
}
Then I want to call this method during the update so I am doing this:
-(void) update {
[self compareSize];
//Check to see if bigger than player fish
if( isBigger == true){
//code for if bigger
}else{ //etc. }
I am getting an exception: sharedlibrary apply-load-rules all
not sure what the best way to set up this method would be, and the best way to call it, since [self compareSize] is definately not working.
Any help would be greatly appreciated, Thanks!
------UPDATE----------
What about if I use this
update:(Player *)player{
The problem I was running into here, is how to call this correctly, I wasn't sure how to change this to correctly call the new update method:
[self schedule:#selector(update) interval:1.0f/60.0f];
It is unclear what you are asking, but let's look at your code and see if it helps.
Your first method can be written more concisely as:
- (void) compareSize:(Player *)player
{
isBigger = self.fSize > player.pSize;
}
There is no point in using an if/else to assign a true/false (or YES/NO) value.
Looking at this method raises the obvious question of whether it would be better returning a value rather than assigning to an instance variable. This would look like:
- (BOOL) compareSize:(Player *)player
{
return self.fSize > player.pSize;
}
and now you can use a call to compareSize in an if.
Assuming the second version of compareSize your second method is:
-(void) update
{
//Check to see if bigger than player fish
if ([self compareSize]) // OOPS, no Player
{
//code for if bigger
}
else
{
//etc.
}
}
But this doesn't work as you need an instance of Player to pass to compareSize:, e.g. [self compareSize:somePlayerInstance]. So you now have to ask yourself where you expect the Player to be found; it could be an argument to update (e.g. - (void) update:(Player *)somePlayerInstance), or you might have a method to call which returns a whole collection of players and you need to test against each one, etc., etc. I can't give an answer as I've no idea of your game and algorithm!
Following comment
You must store a reference to your Player object somewhere in your application. If there is only a single player is Player designed as a singleton with a sharedInstance, or similarly named, class method that returns the single instance? If so then your update will contain:
if ([self compareSize:[Player sharedInstance]])
etc.
Another design pattern is to have your application delegate store the reference and to provide a method (or property) for accessing it. Following this pattern (and making up a class MyDelegateApp and property player names) your code might look like:
if ([self compareSize:((MyAppDelegate *)[NSApp delegate]).player])
Yet another model is to create the single player in the application's main XIB/NIB file - etc., etc., there are many application models!
You "simply" (its not simple of course) need to design your application model so that your single player is accessible, one way or another, where you need it...
Your compareSize: method (note the colon) requires a player parameter.
So you need to call it like this:
[someEnemyFish compareSize:somePlayer]
If self is the instance of EnemyFish you want, you can do [self compareSize:somePlayer], but your title seems to indicate self isn't an EnemyFish?

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.

iPhone Int with NSObject &/causes class can't reference itself

I've got a function called updateTheValue() that I have called using [self updateTheValue] for a while now. Two things happened recently; I added the method calling in the viewDidLoad() method and it spit out a warning saying my class may not respond to this. Second, I want to pass objects to updateTheValue() like strings, but mostly ints, so I declared an NSObject to pass into the method. Can an int fit into an NSObject slot, or what should I use instead?
I would have posted these seperately but they seem to be related since after updating updateTheValue() to accept an NSObject every reference to this function turns out the error that my class "May not respond to -updateTheValue"
You could make your method like this:
-(void)updateTheValue:(NSObject *)anObject
// or use -(void)updateTheValue:(id)anObject
{
if ([anObject isKindOfClass:[NSString class]]) {
// Do your string handling here
}
else if ([anObject isKindOfClass:[NSNumber class]]) {
// Do your number handling here
}
}
Use it like this:
[self updateTheValue:[NSNumber numberWithInt:42]];
I'd suggest doing two different methods though, i.e. updateTheValueWithInt: and updateTheValueWithString: making it easier to read and understand.
Make sure you make the method signature visible before using them, so that the compiler knows what this does.
If you use separate methods you can use int directly without wrapping them into NSNumber objects.
First problem:
updateTheValue() must be declared before you try to call it.
You can either move the definition of function before the calls to it, or add a prototype at the top - eg, add:
(void) updateTheValue;
near the top.
Second problem:
Use an NSNumber, eg [NSNumber numberWithInt:45];

Public scope in Objective-C?

I’m sure this is a simple one, but it’s been elusive so far, and I’m stumped ...
How do I declare an Ivar so that it’s accessible from ALL Classes in a project?
[Don’t know if it matters, but the ivar in question is (an instance of) my Model class, whose data needs to be accessible to various view controllers.]
Best as I can tell from "The Scope of Instance Variables” in The Objective-C 2.0 Programming Language
... this would be by using the “#public” directive.
So I’ve tried this in the #interface block where the ivar is declared:
#interface ...
...
#public
ModelClass *theModel;
#end
... But when I try to refer to “theModel” in a different class, the compiler doesn’t auto-complete, and when I type it in anyway, the compiler shows:
“Error: ‘theModel’ undeclared (first use in this function)”.
I assume this is a question of Scope, and that I haven’t made the ivar available appropriately, but how? Somehow I need to access this, or make its pointer available somehow.
Any ideas would be VERY much appreciated. Many thanks!
Perhaps you forgot to put the instance variable inside the braces of the class where all instance variable declarations go?
#interface Foo : NSObject {
// other instance variable declarations
#public
ModelClass *theModel;
}
// method and property declarations
#end
Also, can you show us the code of how you are trying to access the instance variable from elsewhere? The proper syntax should be:
myFooInstance->theModel
where myFooInstance is a value of type "Foo *"
I make properties available to all views managed by a Tab Bar via a singleton representing my data model. This is efficient and allows all Views access to the data (as well as any other application elements. Creating the singleton is straightforward (there are a ton of examples on S.O.). The you just request the instance and get the property values you need.
Here is a framework fro creating the Singleton. The key points are the static instance and the fact that you do the initialization as [[self alloc] init];. This will ensure the object gets cleaned up correctly. All the methods at the bottom of the class are standard from the SDK Docs to make sure release calls are ignored (because the object is shared globally).
Singleton Boilerplate (ApplicationSettings.m):
static ApplicationSettings *sharedApplicationSettings = nil;
+ (ApplicationSettings*) getSharedApplicationSettings
{
#synchronized(self) {
if (sharedApplicationSettings == nil) {
[[self alloc] init]; // assignment not done here
}
}
return sharedApplicationSettings;
}
+ (id)allocWithZone:(NSZone *)zone
{
#synchronized(self) {
if (sharedApplicationSettings == nil) {
sharedApplicationSettings = [super allocWithZone:zone];
return sharedApplicationSettings; // assignment and return on first allocation
}
}
return nil; //on subsequent allocation attempts return nil
}
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
- (id)retain
{
return self;
}
- (unsigned)retainCount
{
return UINT_MAX; //denotes an object that cannot be released
}
- (void)release
{
//do nothing
}
- (id)autorelease
{
return self;
}
You cannot access iVars from any other class.
You have to declare a getter/setter method to change or view a variable from another class - what you are really looking for are properties, that make it easier to define and access these getter/setter methods.
In your example above, you'd have the property defined just after the block that defines the local variable in the header file:
#property (nonatomic, retain) ModelClass *theModel;
In the implementation file you'd have the getter/setter created with the #synthesize statement just after the #implementation line:
#synthesize theModel;
Then if you have an instance of your class created, you access the class instance variable like so:
myInstance.theModel = [[[ModelClass alloc] init] autorelease];
The reason #public & #private are in there are to define visibility for subclasses (which, being extensions of that class type also get all the class local variables defined by a superclass), not for any random class.
The standard Objective-C way of doing it is to have a class method that returns the ivar
In your .h file:
+ (id)defaultModel;
and in your .m file:
static ModelClass * defaultModelInstance;
#implementation ModelClass
+ (id)defaultModel {
if (!defaultModelInstance) {
defaultModelInstance = [[ModelClass alloc] init];
}
return defaultModelInstance;
}
#end
although this will need tweaking if you need a specific ivar instead of just "a ivar that's always the same"
this type of design is used by many Cocoa classes i.e. [NSWorkspace sharedWorkspace]
Think a C global variable.
Adding:
extern ModelClass* theModel;
after the #end in the header will make the variable visible anywhere you include the header.
In the ModelClass.cpp file add:
ModelClass* theModel;
before the class implementation.
The variable will still have a value of nil until you allocate and initialize it though and you will be resposible for ensuring that it gets deallocated at the correct time.
THANK YOU ALL for the very helpful discussion on this topic! Clearly there are several ways to approach things here, so this is a very useful assortment of techniques.
Just to let y'all know that in researching this issue further, I ran across a couple of other very helpful pages, listed below. They include mention of the NSNotificationCenter, which I hadn't heard of before; as well as the idea of the "dependency injection" design pattern.
The idea is to keep "low coupling"(1) between the classes, making the code more modular & better for unit testing.
And while the 'notification' pattern sounds like a great idea, in this case it may be a bit overkill, considering that I only need ONE instance of the data model throughout the run of the app, and it doesn't change throughout.
Finally, even though the "#public" compiler directive is well-documented in Apple's Obj-C guide(2), I later found a fascinating edict in a different doc stating that it shouldn't be used! Quoted from Apple's own Cocoa Fundamentals(3):
"Give the proper scope to your instance variables. Never scope a variable as #public as this violates the principle of encapsulation. ..."
(Strange that they don't mention this in their 'Objective-C 2.0' guide where the directive is actually explained.)
Anyway, here are a couple of other links I found to be full of some great insights as well. FYI:
S.O.: "What’s the best way to
communicate between
viewcontrollers?"(4) <<
CocoaWithLove: "Five approaches to
listening, observing and notifying in
Cocoa"(5)
CocoaWithLove: "Singletons,
AppDelegates and top-level data"(6)
Hope these help. Anyway, thank you all again!
Best,
rond
P.S. Yikes! It won't let me post more than one inline hyperlink, so I'm listing them here instead. Obviously, they’re all prefixed by “http://” ... :O
(1): en.wikipedia.org/wiki/Coupling_(computer_science)
(2): developer.apple.com/DOCUMENTATION/Cocoa/Conceptual/ObjectiveC/Articles/ocDefiningClasses.html#//apple%5Fref/doc/uid/TP30001163-CH12-TPXREF127
(3): developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals/AddingBehaviortoaCocoaProgram/AddingBehaviorCocoa.html#//apple_ref/doc/uid/TP40002974-CH5-SW12
(4): stackoverflow.com/questions/569940/whats-the-best-way-to-communicate-between-viewcontrollers
(5): cocoawithlove.com/2008/06/five-approaches-to-listening-observing.html
(6): cocoawithlove.com/2008/11/singletons-appdelegates-and-top-level.html