an abused topic but I couldn't find an answer to this. I am following the "Learn iPhone and iPad cocos2d Game Development" book and cannot really understand if the approach in the ShootEmUp example (available at 1) is the best one. The author uses a GameScene to which adds as child various objects (e.g. Ship, InputLayer etc..). The controversial aspect is that within those object there are calls to the GameScene via using a static method that returns a static instance of the GameScene class that is instantiated in the init method of GameScene. This to me seems a circular reference and according to many (e.g. see this post) is something to avoid. I am not quiet sure if that's also true in Game Programming as this approach is found in 1 and there might be a reason for this.
Would anyone be able to clarify? I am undecided whether to restructure my code completely or keep the static variable approach.
Thank you very much :)!
Source code
What you see here is a semi-singleton pattern, and it is used extensively throughout Cocos, in fact the Cocos framework itself is built entirely on singleton objects (as is a lot of Apple's UIKit). Games frequently employ singletons because you typically have a lot of central data in a game, like scores, health, weapons, etc that many of your objects need some knowledge of. You also typically have objects, like players, enemies, etc that need to notify the central dispatch of your app what they are doing so other objects in the game can react or adjust accordingly.
This is why many Cocos games use the technique you've shown here. It is not bad practice if you understand the risks of singleton programming. Basically, keep this in mind:
Whether you use a singleton-style technique or instead call up the parent using another method, you are essentially doing the same thing either way. It's probably better to directly reference the central game engine directly than rely on methods to derive it for you. I would not recommend using [self parent] as that can get hard to read and debug later when you first have to figure "who is the parent," instead a singleton access lets you know immediately who you are accessing.
A child should never retain its parent. You can reference the parent, but don't retain.
An alternative to the singleton approach here is to make an iVar in the child that points to the parent. But this is essentially the same idea, so to minimize the risks of a retain cycle, accessing the singleton is typically safer. If your iVar is not set properly, you could have a circular reference. The method you've shown here is not a circular reference.
Note that this particular code prevents you from using +(GameScene*) sharedGameScene method until after the GameScene has been initialized. This is what makes it a semi-singleton. Typically, this method in a singleton will be smart enough to initialize itself if it is not already initialized so that using this class method either returns or first creates and then returns the object.
Probably not an issue in Cocos since you will likely initialize the Game Scene before you do anything else, so it will already exist.
I'm guessing you're referring this part :
static GameScene* instanceOfGameScene;
+(GameScene*) sharedGameScene
{
NSAssert(instanceOfGameScene != nil, #"GameScene instance not yet initialized!");
return instanceOfGameScene;
}
This doesn't create a circular reference. Some might argue that's not a great practice to build your code this way, but that's a different discussion.
If the returning value from this function (the GameScene object) isn't referenced as strong property in some of GameScene children, it's ok.
You would have the case of circular reference if you had this in one of the children :
#property(nonatomic, strong) GameScene *mainScene;
// OR for non-ARC
#property(nonatomic, retain) GameScene *mainScene;
These would have kept the reference count for the GameScene object from getting to 0 and dealloc-ing.
Hope this helps.
Related
I'm developing a rogue like game (iOS/Cocos2d). I have a object of class Map, which has bunch of GameObjects.
I have GameViewController class. When something in model happens (creature killed, player moved, anything), I need to notify GameViewController about this changes. How to do that?
I see two options:
GameViewController instance could be a delegate of Map and a delegate of every GameObject.
GameViewController will listen NSNotifications from Map and GameObjects.
Which way is better? Why?
Cocos is a strongly singleton-based library, so the singleton method is quite common in Cocos games. That does not mean, however, it is the logical default choice.
Your second option is generally a wiser and safer approach for any program, not just Cocos. NSNotifications allow you to notify objects from other objects without getting into a potentially buggy state of passing numerous references or singletons around in your program. If you can achieve your goals with a few notifications, this is the way to go.
If you find you are using NSNotifications to an extreme degree, like multiple notifications every second, then you should consider either passing references around between your objects via pointers, or creating your parent class or main Cocos scene class as a singleton.
Just remember that when you get singletons involved, though they are easy to implement, it is just as easy to abuse them. You don't want to get into the habit of having children classes control the behavior of their siblings just because they can access the parent and the parent's methods easily.
In Objective-C, we can add #property and #synthesize to create a property -- like an instance variable with getter and setter which are public to the users of this class.
In this case, isn't it just the same as declaring an instance variable and making it public? Then there won't be the overhead of calling the getter and setter as methods. There might be a chance that we might put in validation for the setter, such as limiting a number to be between 0 and 100, but other than that, won't a public instance variable just achieve the same thing, and faster?
Even if you're only using the accessors generated by #synthesize, they get you several benefits:
Memory management: generated setters retain the new value for a (retain) property. If you try to access an object ivar directly from outside the class, you don't know whether the class might retain it. (This is less of an issue under ARC, but still important.)
Threadsafe access: generated accessors are atomic by default, so you don't have to worry about race conditions accessing the property from multiple threads.
Key-Value Coding & Observation: KVC provides convenient access to your properties in various scenarios. You can use KVC when setting up predicates (say, for filtering a collection of your objects), or use key paths for getting at properties in collections (say, a dictionary containing objects of your class). KVO lets other parts of your program automatically respond to changes in a property's value -- this is used a lot with Cocoa Bindings on the Mac, where you can have a control bound to the value of a property, and also used in Core Data on both platforms.
In addition to all this, properties provide encapsulation. Other objects (clients) using an instance of your class don't have to know whether you're using the generated accessors -- you can create your own accessors that do other useful stuff without client code needing changes. At some point, you may decide your class needs to react to an externally made change to one of its ivars: if you're using accessors already, you only need to change them, rather than make your clients start using them. Or Apple can improve the generated accessors with better performance or new features in a future OS version, and neither the rest of your class' code nor its clients need changes.
Overhead Is Not a Real Issue
To answer your last question, yes there will be overhead—but the overhead of pushing one more frame and popping it off the stack is negligible, especially considering the power of modern processors. If you are that concerned with performance you should profile your application and decide where actual problems are—I guarantee you you'll find better places to optimize than removing a few accessors.
It's Good Design
Encapsulating your private members and protecting them with accessors and mutators is simply a fundamental principle of good software design: it makes your software easier to maintain, debug, and extend. You might ask the same question about any other language: for example why not just make all fields public in your Java classes? (except for a language like Ruby, I suppose, which make it impossible to expose instance variables). The bottom line is that certain software design practices are in place because as your software grows larger and larger, you will be saving yourself from a veritable hell.
Lazy Loading
Validation in setters is one possibility, but there's more you can do than that. You can override your getters to implement lazy loading. For example, say you have a class that has to load some fields from a file or database. Traditionally this is done at initialization. However, it might be possible that not all fields will actually be used by whoever is instantiating the object, so instead you wait to initialize those members until it's requested via the getter. This cleans up initialization and can be a more efficient use of processing time.
Helps Avoid Retain Cycles in ARC
Finally, properties make it easier to avoid retain loops with blocks under ARC. The problem with ivars is that when you access them, you are implicitly referencing self. So, when you say:
_foo = 7;
what you're really saying is
self->_foo = 7;
So say you have the following:
[self doSomethingWithABlock:^{
_foo = 7;
}];
You've now got yourself a retain cycle. What you need is a weak pointer.
__block __weak id weakSelf = self;
[self doSomethingWithABlock:^{
weakSelf->_foo = 7;
}];
Now, obviously this is still a problem with setters and getters, however you are less likely to forget to use weakSelf since you have to explicity call self.property, whereas ivars are referenced by self implicitly. The static analayzer will help you pick this problem up if you're using properties.
#property is a published fact. It tells other classes that they can get, and maybe set, a property of the class. Properties are not variables, they are literally what the word says. For example, count is a property of an NSArray. Is it necessarily an instance variable? No. And there's no reason why you should care whether it is.
#synthesize creates a default getter, setter and instance variable unless you've defined any of those things yourself. It's an implementation specific. It's how your class chooses to satisfy its contractual obligation to provide the property. It's just one way of providing a property, and you can change your implementation at any time without telling anyone else about it.
So why not expose instance variables instead of providing getters and setters? Because that binds your hands on the implementation of the class. It makes other acts rely on the specific way it has been coded rather than merely the interface you've chosen to publish for it. That quickly creates fragile and inter-dependent code that will break. It's anathema to object-oriented programming.
Because one would normally be interested in encapsulation and hiding data and implementations. It is easier to maintain; You have to change one implementation, rather than all. Implementation details are hidden from the client. Also, the client shouldn't have to think about whether the class is a derived class.
You are correct... for a few very limited cases. Properties are horrible in terms of CPU cycle performance when they are used in the inner loops of pixel, image and real-time audio DSP (etc.) code. For less frequent uses, they bring a lot of benefits in terms of readable maintainable reusable code.
#property and #synthesize is set are getting getter and setter methods
other usage is you can use the that variable in other classes also
if you want to use the variable as instance variable and your custom getter and setter methods you can do but some times when you set the value for variable and while retrieving value of variable sometimes will become zombie which may cause crash of your app.
so the property will tell operating system not to release object till you deallocate your object of class,
hope it helps
I'm creating a library that will be used by multiple types of iOS apps. Part of my API allows a user to specify routines that will be used for the library's allocations. My library is implemented mostly in C++, so this has been straightforward so far.
However, I've recently been adding some user interface functionality to the library: displaying a UIWebView using a custom view controller. I'm not sure how to ensure that my allocators are used for these objects.
How can I ensure that all of the Cocoa UI objects created by my library are allocated with my own functions?
I've tried a few things including overriding -initWithZone and calling CFAllocatorSetDefault before my -init. None of them have worked yet; and honestly I'm still a beginner with Objective C and Cocoa, so I'd like to know what the "correct" way to do this is.
I'm unable to find evidence of it now, but it certainly was the case that CFAllocator, malloc_zone_t and NSZone were all toll-free bridged. So you could just cast your allocator to an NSZone and pass it along.
I think the problem you're going to face is that NSZone was added at NextStep so as to allow a program to maintain multiple heaps, with the feeling being that it would allow programmers to keep related objects close to one another in memory — which is good for caching — and in some cases to throw away entire object graphs without walking the graph, which is obviously fast. However the former was of little benefit in practice and the latter is more likely to create problems than to be of actual benefit. So Apple has back-peddled from NSZones, gradually turning the related runtime calls into no-ops and removing detailed documentation. Apple's feeling is that, at the Objective-C level, you should not only maintain only a single heap (which is a side issue from your point of view) but that they'll always know best how to maintain it.
EDIT: an alternative idea is to replace NSObject's alloc, that being the thing that creates memory. The Objective-C runtime is well-defined enough that we know exactly what behaviour alloc exhibits, so that a vanilla version might be:
+ (id)alloc
{
Class *newInstance;
// we'll use calloc to ensure we get correct initial behaviour of
// everything equal to 0, and use the runtime's class_getInstanceSize
// so that we're allocating the correct amount of memory irrespective
// of whether this call has fallen through from a subclass
newInstance = (Class *)calloc(1, class_getInstanceSize(self));
// the thing that defines a class is that the first thing stored in
// it is the isa pointer, which points to the metaclass. So we'll
// set the isa pointer appropriately
*newInstance = self;
return (id)newInstance;
}
To replace NSObject's normal init, you'd probably want to define your alternative as a category method on NSObject named, say, customInit, then use class_getClassMethod, class_getMethodImplementation and method_setImplementation directly on [NSObject class] to switch it into place. See the Object-C Runtime Reference for documentation on those.
Am not sure how to put this, and I couldn't find the answer because of my inability to find the words to express what am looking for. (!)
In Java, I used to do something like this (I don't remember):
JPanel myButton = new JPanel("Press me"){
public void add(JComponent component){
//override add method
}
};
But, i couldn't find how to do this in Objective-C .. What I found in my search was categories and weird ^{} symbols ...
So, how can I override method(s) in a newly created object?
(For example, override -(BOOL)isEqual; in a newly created NSString* ?)
Am sorry if the question is a bit vague..
EDIT:
Obviously, without subclassing :)
EDIT:
Might as well post my problem in case someone has a better idea:
I have a few CCTransitions in COCOS2D, and I want to be notified when the transition ends .. The thing is, as soon as the transition ends, the -(void)finish; method is invoked (which is part of the CCTransition class structure)
I would really want to avoid subclassing the CCTransition class, and override the finish method to do my logic when the transition ends :)
EDIT:
-(void)onEnterTransitionDidFinish; ... I can't believe something as awesome as that existed and I haven't came across it while searching......
Which means, instead of subclassing CCTransition, override this method in my CCNode subclass :D!
It's still not going to be very clean, but assuming you're willing to concentrate the ugliness, you could do something like (untested):
Method methodToReplace =
[targetClass instanceMethodSignatureForSelector:#selector(methodToReplace)];
IMP implementationToSet =
[someProxyClass instanceMethodForSelector:#selector(implementationYouWant)];
method_setImplementation(methodToReplace, implementationToSet);
Relevant reference documentation is the Objective-C Runtime Reference and, optionally, the NSObject Class Reference (because it makes a few things slightly neater, though e.g. you could use class_getInstanceMethod from the runtime rather than instanceMethodSigntureForSelector:).
Note that you'll have no way to call the original implementation if you use exactly that recipe. method_setImplementation returns the old implementation, it's generally wise to add that to the class under a brand new selector and call that instead.
For reference, I've had a legitimate reason to do this sort of thing only exactly once: when we implemented printing support in an iOS application with which needed to be compatible with both OS 3.2 and 4.0. You need to subclass a particular class, but the class isn't available in 3.2. So you sort of have to subclass at runtime (though the conceptually neater way would be to use a normal subclass, put that into a framework and weak link, but Apple's iOS SDK terms allow static libraries only, so...).
Following Daniel's suggestion, you can implement a method in an NSObject category of the form
[anObject overrideMethod:#selector(foo:)
byBlock:^(id self,id super,id originalArg){
...
}];
What you need to do is to
objc_allocateClassPair against self's own class, to create a new temporary class
Turn a block into a function pointer, using e.g. this or this
method_setImplementation to set the new implementation to the temporary class
use object_setClass to self to set the class to the new temporary class
I haven't figured out how to provide super to the block :p
It's believed this is basically how the KVO is done by Apple, see e.g. this discussion.
Read Runtime reference.
What you have there in Java is an anonymous subclass. This is not possible in Objective-C (well, it sort of is but you would have to do some pretty involved contortions with the Obj-C runtime library).
But Objective-C as of iOS 4 or OS X 10.6 has "blocks", which is what the ^{} syntax is for. This is Objective-C's notion of a closure. This isn't going to help you directly if the APIs that you're calling don't support block callbacks, but you may be able to create wrapper classes that use blocks instead of subclassed methods to handle callbacks.
There are many resources for learning about blocks in Objective-C.
Would anyone be able to explain to me what data encapsulation in Objective-C is? I've been told that this an important concept of Objective-C but I don't see why...
Explain it to me as if I was 5 and then as if I was 25....
Thanks for your time,
~Daniel
From http://mobile.tutsplus.com/tutorials/iphone/learn-objective-c-2/ :
What we mean by data encapsulation is
that data is contained (so to speak)
by methods meaning to access it we
need to use methods. Some of you who
have programmed in other languages and
havenʼt heard of data encapsulation
may be wondering why we do things this
way. The answer is that by
encapsulating data, there is a nice
cushion between the developer of a
class and the user of a class. Because
the class methods manage and maintains
the attributes within the class, they
can more easily maintain data
integrity. Another major benefit is
that when a developer distributes his
class, the people using it donʼt have
to worry about the internals of the
class at all. A developer may update a
method to make it faster or more
efficient, but this update is
transparent to the user of the class
as he/she still uses the same method
with no change to his/her code.
In simple terms, the user is provided with what the developer wanted them to have, and "protects" everything else. The developer can change anything internal without the user having to rewrite their code.
If developers did not conform to data encapsulation, we would need to rewrite our code every time a new version of a library, code snippet, or an entire program was released.
Data encapsulation in Objective-C means that only the class itself should touch it's instance variables. Therefor you should always mark them as private, and only expose them through properties, as this:
#interface Foo : NSObject {
#private
int numberOfBars;
Baz* contentBaz;
}
#property(nonatamic, assign) int numberOfBars;
#property(nonatomic, retain) Baz* contentBaz;
#end
This means that the class can implement validation in it's setter methods. And even better if you use #synthesizeto generate your getter and setters than you need not even worry about the memory model of Cocoa at all (with the exception of releasing your ivars in dealloc).