How should I be using class variables in Objective-C? - objective-c

This has been bugging me for a long time, and I have tried to look it up many times.
When I first began learning Objective-C, I remember looking into class variables. I saw many threads on stack overflow and elsewhere that basically said, "Objective-C doesn't support class variables like C does, but there are some workarounds."
Reading this made me shy away from using class variables, especially because I have read hundreds of times that global variables tarnish the elegance of OOP.
So I have a very open ended, opinionated, and conversational question:
Should I use class variables in objective C? Also, am I doing it right?
Here is my situation: I am making an app, and I set up a touch handling class to deal with all the input received from screen touches. The data is pretty useful, and I would like every single sprite to have access to it.
Since every object is a subclass of my GameObject class, I figure I just make a class variable, done like so:
header for GameObject class:
+(SSTouchHandler *)touchHandler;
+(void)setHandler:(SSTouchHandler *)handler;
implementation for GameObject class:
static SSTouchHandler *touchHandler = nil;
+(SSTouchHandler *)touchHandler
{
if (touchHandler)
return touchHandler;
else
return nil;
}
+(void)setHandler:(SSTouchHandler *)handler
{
touchHandler = handler;
}
Now, this works. This works beautifully.
I can refer to my handler with [GameObject touchHandler] from every place I need.
This is all I could ever want and more.
But should I use this method? Am I dirtying the beauty that is object oriented programming?
Is there a way I should touch up this process to make it work optimally?
Thanks for any and all input, I probably rambled a bit, I just don't want to proceed with a faulty game structure.

I saw many threads on stack overflow and elsewhere that basically
said, "Objective-C doesn't support class variables like C does, but
there are some workarounds.
"Class variables" make no sense in the context of C since C is not object oriented.
So I have a very open ended, opinionated, and conversational question:
Should I use class variables in objective C? Also, am I doing it
right?
This is more of a general OOP question than anything specific to Objective-C. The answer tends to be pretty subjective, but in general I'd say to avoid them unless you're trying to set a property of some sort that affects all instances of a class.
Here is my situation: I am making an app, and I set up a touch
handling class to deal with all the input received from screen
touches. The data is pretty useful, and I would like every single
sprite to have access to it.
It sounds to me like a better design pattern for this would be to pass the SSTouchHandler instance as a parameter to the initializer of the sprite objects that use it. e.g.:
#interface GameObject : NSObject
- (id)initWithTouchHandler:(SSTouchHandler *)handler;
#end
Now, if you really want to use the same instance of SSTouchHandler for every GameObject, you have two options:
1) The controller/factory that creates the GameObject objects should create and keep a reference to a single instance of SSTouchHandler, and then initialize any new GameObject instances with it. For example:
#interface GameObjectController : NSObject
#property (nonatomic, strong, readonly) SSTouchHandler *touchHandler;
- (GameObject *)newGameObject;
#end
#implementation
- (id)init
{
if ((self = [super init])) {
_touchHandler = [[SSTouchHandler alloc] init];
}
return self;
}
- (GameObject *)newGameObject
{
return [[GameObject alloc] initWithTouchHandler:self.touchHandler];
}
#end
2) You could make SSTouchHandler a shared singleton and call methods on the shared instance directly from the implementation of GameObject. However, shared singletons are discouraged in OOP because they hide dependencies and make it difficult to unit test code that depends on them. You shouldn't go down this route unless you deem it absolutely necessary.
implementation for GameObject class: ...
If you decide that the patterns above aren't suitable for your use case (and that sometimes does happen), yes that is essentially how you would implement class properties in Objective-C. One thing:
if (touchHandler)
return touchHandler;
else
return nil;
This is not necessary, you can just return touchHandler since it will be nil anyways if not set.

If it works, you're done. I think there are some improvements, though. First, you might like to use an instance var here: it's not more complicated, but it allows some flexibility in the future (e.g. if you want to make two views side by side). Also, using a bare pointer is not so good; the class here does not own the pointer, and it can be left dangling! Defining the touchHandler as a property (also an instance var) takes care of that problem.

Related

Adapting a few Java-based singleton objects to Objective-C [duplicate]

This question already has answers here:
Global Variables for Class Methods
(2 answers)
Closed 8 years ago.
I've decide to rewrite a java-based game prototype I've been working on in Objective-C. The iOS platform will be a better fit.
Unfortunately I'm having to learn Obj-C at the same time. In the Java game, there were a few libraries that were instantiated by the main game class, and accessed statically when needed. This meant that I could the overhead of new instances each time.
i.e.:
Game.getRNG().nextInt() or Game.getNoiseGen().noise( x, y )
I'm trying to understand the best method to replicate this in Obj-C. I've looked at examples of singletons and am trying this method, but I'm not sure if this is the best way to do this.
The above code, would apparently translate into something like:
[[[Game getInstance] getNoiseGen] noise]
Is there a better way to create a single instance of library classes and statically reference them from anywhere inside my application code?
For creating a singleton make sure you only create the static instance once, you can do this by using GCD.
+ (id)sharedInstance;
{
static dispatch_once_t once;
static id sharedInstance;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
and you can then:
Game *game = [Game sharedInstance];
//...
CGPoint point = CGPointMake(x, y);
[[game noiseGen] noise:point]
//...
Singletons are considered an anti-pattern and should be avoided if possible.
Just from looking at your example you also violate the Law of Demeter, might be worth a read to see if you can improve there.
If I understand your Java model correctly there is no reason why you cannot translate it directly into Objective-C, which certainly has the advantage that you are familiar with it - helpful while you're learning a new language.
By "there were a few libraries that were instantiated by the main game class, and accessed statically when needed" I take it that either:
The main class declared global variables of the appropriate types and initialised them; or
The classes themselves have a global variable which holds a reference to an instance of themselves.
You are not generating "singletons" here, just objects you want to share. Also given that your main class created them they always exist. Combined this means you've no need to use any of the "singleton" schemes which delay creation until first use and deal with one-time thread-safe initialisation.
All you need is the model for global variables in Objective-C. In outline this is:
Declare the variable as extern in a header file
Define the variable in an implementation file
In outline, your MainGame.h:
#import "SharedGameObject.h"
#interface MainGame : NSObject
extern SharedGameObject *TheSharedGameObject;
...
#end
and MainGame.m
#import "MainGame.h"
SharedGameObject *TheSharedGameObject;
- (id) init
{
TheSharedGameObject = [SharedGameObject new];
...
}
Now every other class which import MainGame.h has access to the same shared object using TheSharedGameObject. This is the model Apple used for NSApplication and it associated NSApp global variable.
HTH

Is it an acceptable pattern for an init method to return an object of a different type?

I'm working on bugfixes for some existing objective-c code and came across something I thought strange:
#interface ClassA : UIView
...
static ClassA* oldSelf = nil;
#implementation
- (id)initWithFrame:(CGRect)frame {
oldSelf = self;
self = [[ClassB alloc] initWithFrame:(CGRect)frame]; // xcode warns: Incompatible pointer types assigning to "ClassA *" from "ClassB *"
// ^^^^^^ Is this ok?
[oldSelf release];
return self;
}
#interface ClassB : UIView
...
#implementation
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
return self;
}
This whole thing is wrapped up into a static library. The public gets the lib.a file and ClassA.h
In code using the library, This occurs:
#import "ClassA.h"
...
// useage
ClassA *myA = [[ClassA alloc] initiWithFrame:CGRectMake(0,0,100,100)];
...
So we got an initializer for ClassA that actually returns an unrelated class. ClassA and ClassB respond to the same messages so it compiles and runs. Seems like ClassA is being used to obscure some features exposed in ClassB?
I'm curious if this is acceptable behavior, and if it's a known pattern, what is it called? Are there any side effects to this setup?
=========================================================
Thanks for everyone's answers! I think I've got it... in short, not a normal pattern, and not exactly a good idea
Kind of like a "class cluster"(abstract factory), but not quite, because a common abstract class should be returned. And since the code doesn't seem to ever intend to return anything but a ClassB object, probably not what the original author was thinking.
More like a proxy, but implemented wrong. ClassA should hold a private instance of ClassB and pass messages between the two.
=========================================================
Edited: added "oldSelf" parts...
Edited: added static library details...
Edited: added a blurb about the accepted answer...
The major disadvantage I see here is: a user of ClassA would expect that an object he just created via [[ClassA alloc] initWithFrame:...] returns YES for [object isKindOfClass:[ClassA class].
This might also lead to errors when using things like NSInvocation, because the wrong class would be used to determine the method signature, though I am not sure about that.
Due to Objective-Cs dynamic nature, this will, as you described, work, but may be confusing to use and i would strongly discourage anyone from using this pattern.
As pilavdzice said, the "right" alternative to this would be to have both ClassAand ClassB inherit from another class (an abstact superclass) which then in its initializer decides what concrete subclass to use. Good examples of this pattern, called class clusters, are NSString, NSArray and NSDictionary which all return objects of various subclasses based on how you initialize them, which is also the reason you can not subclass those directly without some effort.
It's not an unreasonable thing to do in all cases, but it's hard to say whether it's a good idea in the situation you describe. Two examples where it might be fine:
The initializer returns an instance of a more specialized subclass. For example, you might choose different implementations of a data structure depending on the number of items being stored.
The initializer returns some sort of proxy object.
Your code does seem a bit odd. At the very least, I'd expect to see a cast as a signal (both to the compiler and to future programmers) that the author knew what he was doing. A comment explaining the reason for returning a different type of object wouldn't hurt, either. Ideally, ClassB should be a subclass of ClassA since it's expected to provide the same interface.
Class clusters are implemented in this way, sort-of. A related technique, isa-swizzling can be used to implement a sort of state machine. It does require the same ivar layout to work. In terms of side effects, I believe that it may break KVO; but someone may correct me on that point.
It's certainly not common in user code to return an unrelated class, however it is common in some of Apple's frameworks to return a more specific version of a class with the same public interface.
Apple's Cocoa Fundamentals discusses in some amount of detail the fact that objects such as NSArray and NSNumber may return a different object than the class you are asking for.
That isn't a pattern I know of.
If I am understanding this correctly, the normal way to do this would be to have both classes inherit from the same abstract base class.
As #alan duncun notes, this technique is called a class cluster and is somewhat common. But your implementation is slightly incorrect. You should never return a incompatible type. In your example, ClassB should inherit from ClassA.
Well this is somewhat how NSScanner is implemented.
This way the inner class is not exposed and can not be misused. ClassB can not be initialized somewhere else other than in the implementation file of ClassA.
This makes sense if you have multiple inner classes and your initializer somehow decides which class is actually needed.
I don't see any advantages if you only use one inner class.

How can I prevent a method from being wrongly overridden

How can I prevent a method from getting overridden in a subclass, missing a call to its superclass' implementation within?.
I know calling [super methodName]; will solve my problem sometimes.
But if somebody else was to use my parent class and overrode my method, accidentally missing to call super, what can I do?
Some more explanations:
I create a viewcontroller VC1 which has a method -(void)indexDidChange:(int)index { }. I write some actions there which I need to perform every time. and I subclass this viewcontroller named as SVC1 in it I need -(void)indexDidChange:(int)index { } for doing some other actions but at the same time the VC1 -(void)indexDidChange:(int)index { } action also need to perform. So I need to call like,
-(void)indexDidChange:(int)index {
[super indexDidChange:index];
}
So I decide to change VC1 function like,
-(void)indexDidChange:(int)index {
[self currentIndexDidChange:(int)index];
}
-(void)currentIndexDidChange:(int)index { }
And I need -(void)currentIndexDidChange:(int)index { } to override and prevent -(void)indexDidChange:(int)index { } from overriding.
Is it possible?
Edit: After OP rephrased the question it is clear that OP is actually NOT looking for final methods, despite the questions initial phrasing, which implied just this.
New (updated) answer to OP's question on method overriding safety:
According to your rephrased question you are not looking for protecting a method from being overridden at all, but rather worried about one of your subclasses overriding a method and accidently missing to include a call to super in its new implementation.
This however is a fairly common and widespread issue and something you're dealing with on a daily basis, without paying much attention to it.
Every Objective-C programmer is familiar with the following method, right?
- (void)dealloc {
[iVar release], iVar = nil;
[super dealloc]; //skipping this call to super is fatal!
}
And we al know that skipping the [super dealloc]; makes things get uncomfortable. (afaik the clang compiler issues a warning if dealloc lacks the call to super, …pretty handy.)
Despite the fact that a bad overriding of this method can have fatal consequences Apple did not choose to put any kind of security system in place here.
Instead Apple did this (as done with any other method requiring calls to super):
Add a note to the method's documentation:
After performing the class-specific
deallocation, the subclass method
should incorporate superclass versions
of dealloc through a message to
super
Expect you, the programmer, to be a grown-up and responsible for what you do. And for playing by the rules (as defined by the documentation).
Keep in mind that - (void)dealloc is by no means an exception. There are dozens and dozens of methods of this type in Cocoa. (Take just about any derivative of - (id)init, most of the KVO observing methods, etc. just to name a few.)
So what you should do is:
Write a good documentation for your
method. (better for your entire project, actually)
Add a big loud note to your method's documentation, explaining its rules.
Add a note to each of your subclasses' overridden method implementations, right above the line that's calling super, telling the reader/dev to look up documentation, when in doubt of the rules. (optional)
Code responsibly. Otherwise, you shouldn't be coding in first place. It's your customers who will suffer from it, eventually.
Old (pre-rephrasing) answer on archieving pseudo-final methods:
What you are asking for is the equivalent of a final function, as known from Java or C++.
Unlike Java or C++, however there are no final methods in Objective-C.
Depending on your situation there are solutions that might bring your at least near to what you're aiming for. All you'll get though is slightly better separation. You won't get any significant security from them. In Objective-C you cannot even be sure about the origin of your methods. Method swizzling allows you to exchange methods at will. With code injection you an even inject code into processes at runtime. All this is by design of Objective-C. Objective-C allows you to saw off the branch you're sitting on. Thus it demands you to act like a grown-up. As such there are no private methods either. If a method is proclaim private you as a dev are expected to behave accordingly.
Now to possible "solutions":
If only your super class if supposed to call the given (final) method anyway:
Then Macmade's solution of making your method a pseudo-private method would work quite well. The downside of hiding method declarations though is, that calling your hidden method from subclasses will give you a compiler warning, basically preventing*(sic!)* you from calling it. (It will not prevent you from calling the method though. It will only avoid you from doing so, by throwing compiler warnings.)
If subclasses however are expected to call the given (final) method:
Use a delegation pattern and by this only make those methods public that are allowed to be overridden.
To prevent overriding at all you could use the class cluster & abstract factory patterns, which hides your implementation classes and thus preventing overriding entirely. (Apple's NSArray, NSDictionary, NSSet classes do this)
However you might notice that with Objective-C lack of protection one usually can only choose between the two: openness, protectedness, not intermix them.
You can use categories in the implementation, so your methods aren't exposed in your header file.
MyClass.m
#interface MyClass( Private )
- ( void )myMethod;
#end
#implementation MyClass( Private )
- ( void )myMethod
{}
#end
#implementation MyClass
/* ... */
#end
If you don't declare your function in the ".h file" then its not listed, I think.

Sending messages to objects?

I have done this successfully many times before, but this time it just won't work.
The code in my .h file:
#interface Images : NSView {
}
- (void) draw;
#end
The .m file (of another object):
- (IBAction) go: (id) sender; {
[Images draw:nil];
}
When I try to compile this, it says the following:
'*' may not respond to '*
Images may not respond to '+draw'
This has me quite confused. Shouldn't this be working?
Please Note: Yes, I have seen the other questions about messages, but none of those answers was even partially helpful for me. After reading them, I was even more confused.
Your draw method is an instance method: it can only be called on instances of the Images class. In your go: method you're trying to call it as a class method—if this is what you want, change it to:
#interface Images : NSView
+ (void)draw;
#end
I think a review of some of the basic concepts of object-oriented programming is in order; namely the difference between a class and an object or instance.
A class, in the general sense, is a collection of data and the functions which act upon it. A class defines the interface that one uses to access and manipulate data that is logically grouped together, and serves as a blueprint for creating objects or instances. See http://en.wikipedia.org/wiki/Class_(computer_programming)
Instances of a class (objects) are the typical things you manipulate in an object-oriented program, and they are created from the class "blueprint" and follow the behavior as specified by the class.
A typical example would be a fruit- take apples for example. An imaginary Apple class would represent all apples in the general sense and would model properties such as color and size and actions such as wash and eat. An instance would represent one, single physical apple- a Granny Smith or Pippin or whatever variety.
Just as it doesn't make sense to wash or eat apples in the general sense of the word (the concept of apples, not the agglomeration), typically it doesn't make sense to tell a class what to do. You tell objects (individual apples) what to do.
The code you present above defines the class Images. The "-" in front of -(void)draw indicates that the draw method only exists for specific objects. It is an instance method in typical OO parlance.
Of course, in Obj-C it is also possible to send a message to a class without requiring an object. This is denoted by a "+" in front of the method name, as other answers indicate. This is called a static method and it typically used to control some shared behavior or aspect of all objects of that particular class.
The problem with your code is that you are declaring -(void)draw as an instance method but calling it as a static method. Which way you want to do things is up to you, and it's difficult to determine from your code what the intent of the Images class is.

Objective-C: Protocols

I'd like an instance variable object to adopt a protocol.
#interface GameScene : Scene <AVAudioPlayerDelegate> {
#private
Layer *content <CocosNodeOpacity>;
}
For example I'd like my Layer object to adopt the <CocosNodeOpacity> so that I can get the methods
-(GLubyte) opacity; //and
-(void) setOpacity: (GLubyte) opacity;
for free. The syntax shown above is invalid. Is it possible to achieve this without creating a new implementation file and creating a custom object? Thanks.
If these are all code you created, the best way to do this is probably to make the Layer class itself adopt the protocol, rather than the variable.
#interface Layer : NSObject <CocosNodeOpacity> { ... }
A key benefit to this approach is that the compiler will check whether you've implemented all required methods in the protocol at compile time, which is generally what you want. Adding the methods in same place as the rest of the standard class implementation is easier to understand (no hunting to find where the magical code came from) and less fragile than using categories (adding the same method via different categories can result in undefined behavior). As a general rule, I only use categories when I have to, such as adding methods to (closed-source) third-party code.
If you don't control the source of Layer, you may have to use this instead when you declare your ivar:
Layer<CocosNodeOpacity> *content;
Note that adopting a protocol allows you to statically type variables with a class type and get compile warnings if the methods aren't present. However, you don't get the methods "for free", since you still have to implement them. Still, judicious use of protocols and static typing can make your code more robust and "fail-fast" than using id as the type for everything. You are to be commended for not just taking the easy way out. :-)
For some details about protocols (including required and optional methods) see this SO answer.
A protocol in Objective-C is similar to an interface in Java. The protocol defines a set of functions and acts as a contract. It's like saying "I guarantee that whatever this object is, it has these methods."
You're pretty close on the syntax in your first code block. It would actually look something like this:
#interface GameScene : Scene <AVAudioPlayerDelegate> {
#private
Layer<CocosNodeOpacity> * content;
}
However, that doesn't save you from having to define the methods for opacity in your Layer class. Using the protocol, you've established that your class will have those functions, but you haven't actually provided them. You'll still need to write the code for them.
I think what you're looking for is an Objective-C category. A category provides a way to extend the functionality of any class by adding methods to it at runtime. They're possible because Objective-C is a completely dynamic language. If you aren't the author of the Layer class and can't easily add the opacity methods to it, a category is the way to go. In some cases, categories are extremely useful - you can add methods to built-in classes, like NSString and NSColor, without having the existing class source.
There's plenty of documentation for categories here on stack overflow. The apple docs are also very good. Here's an article to get you started:
http://macdevelopertips.com/objective-c/objective-c-categories.html