I'm fairly new to objective-c.
I'm trying to develop mostly experimental projects for a future development of a game app.
I would like to have suggestions on what I should use for the following purpose.
I'm trying to keep a group of objects somewhere (lets say something like an Array) in objective-c. I want that group of objects to be available everywhere in my application (different functions etc.) That group of objects has to be edit ready so NSArray (I guess) is out of the question? must be.
I'm struggling with concepts and still looking for the right way to do such a thing, tried to force some global arrays but I think that wasn't good practice.
Any help would be highly appreciated, thanks. (Please be kind enough to provide some further explanation on why I should use this -your suggestion- instead of something else. In that way you will help me grasp the idea better).
If it's a group of objects that needs to be shared throughout the entire application, and you want to shy away from global variables, then I think you have one good option:
By creating and storing the collection (which should be an NSMutableArray, an editable version of NSArray) in your application delegate, it can be accessible everywhere:
//MyAppDelegate.h
#property (nonatomic, retain) NSMutableArray *_editableArray;
//MyAppDelegate.m
- (void)applicationDidFinishLaunching {
_editableArray = [[NSMutableArray alloc] init];
// Add objects if you'd like
}
And then you can access it anywhere, like so:
// In other classes
((CastToYourAppDelegateClass *)[NSApp delegate]).editableArray;
Keep in mind that if you're going to be accessing/editing this array on any background thread (or using GCD) then you'll have to ensure that the access is properly synchronized. (Are you planning on doing so?)
Why not just to implement Singleton pattern for your shared object, that will have NSMutableArray as one of it's properties?
Related
I just try to figure out the upside of categories compared to subclassing... I do understand how they are implemented, but the only upside I see right at the moment is, that it saves you from refactoring your whole code, if you wanna extend a used class in a later stage, which normaly shouldn't happen with a good planning. Otherwise it takes about the same time to implement as a subclass and it doesn't really bring different functionality. So for my knowledge about subclasses vs. categories I don't see a reason why to use categories. Can someone please wash my head and explain the reason for the existence of categories? I'd be very thankful :)
You're focusing on objects that you create, in which case, subclassing is fine. But what if you're calling some Cocoa method that returns some standard object. Do you want to have to create a new instance of your subclass everytime just so you can use your new method? No, it's much more convenient to be able to create methods that you add to existing class via category.
Also, you might want your new methods to be available to not only the base class, but all of its subclasses, too (e.g. if you add extension to NSString, it's available to NSMutableString instances, too).
For more information, see the discussion in Customizing Existing Classes in the Programming with Objective-C guide.
A major difference is that categories can not add instance variables, subclasses can.
Additionally there are classes that are very difficult to subclass such as NSString, see the subclassing notes. Here is an excerpt: "It is possible to subclass NSString (and NSMutableString), but doing so requires providing storage facilities for the string (which is not inherited by subclasses) and implementing two primitive methods." As soon as you see but you know it will not be easy.
Try adding a new method to the NSString class. Try doing it by subclassing NSString and by adding a category. One of these takes two minutes, the other you are never going to get working properly. That will then answer your question.
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.
Objective c | xcode | iphone question
Im building a model(data) class for a monetary transaction and have kind of a basic/noob question regarding pointers and object copying. The Transaction class I'm creating contains 4 or 5 ivars/properties that represent object type variables. now when I get the user entered data from the view controller to populate these ivars is it safe to use pointers or do i need to make a copy of the object and then assign that to the ivar?
Because I'll need to store these transactions after the user exits the program I'm assuming that any references I made to pointers in a previous session will be essentially broken links. Am i wrong here, any explanation and maybe some code examples would be appreciated.
If you have any suggestions as far as how to store the data while the app is not in use that would also be helpful.
Thanks so much,
Nick
I would suggest re-reading the intro guides as you seem to be a bit off the rails here; over-thinking the basics. No big deal, we've all been there (still are there when faced with new stuff, often!).
First, for any string value, copy it. In terms of properties, which you should use, you would want:
#property(copy) NSString *myString;
Make sure you -release myString in your -dealloc method.
For other kinds of values, it is really context dependent. Copying is often the safe route. NSDate and NSNumber instances happen to be immutable so copies are irrelevant, but free.
As far as saving data, you are semi-correct. Pointers do not remain valid/same across running sessions with your application. If you need to save data, you explicitly do so through any of a number of common mechanisms. For dead-simple data in an entirely non-document based, app specific, role, user defaults might be enough. Otherwise, see the documentation regarding archiving data.
Objective-C 2.0 gave us #properties.
They allow for introspection.
They allow for declarative programming.
The #synthesize and #dynamic mechanisms relieve use from having to write repetitive, stock accessors.
Finally, there is the ‘dot’ property syntax, which some love, and some hate.
That isn't what I'm hear to ask. Like any new feature, there is an initially tendency to want to use #property everywhere. So where is property use appropriate?
Clearly in model objects, attributes and relationships are good fodder for properties.
#property(...) NSString *firstName;
#property(...) NSString *lastName;
#property(...) Person *parent;
Even synthesized/computed attributes seem like a good use case for properties.
#property(...) NSString *fullName;
Where else have you used properties? Where have you used them, then later decided it was an inappropriate use of the feature?
Do you use properties for your private object attributes?
Can you think of any examples of things which aren't properties in Cocoa, which at first look, seem like they might want to be properties, but after closer inspection, are actual an example of abuse or property-itis?
My recommendation to people is to use property's wherever possible. If you are working in a framework, the ability to use non-fragile instance variables in the modern runtime is a huge bonus and if you aren't, properties make it clear how your ivars are to be managed (assigned vs retained vs copied). There isn't an inherent performance loss from declaring a property other than the time it takes to write the line of code (I actually use a TextExpander snippet to do this for me) but the potential for preventing bugs is large enough that it becomes a fantastic best-practice. If you do plan to user properties for private ivars, you can do so inside your implementation file via an #interface block. For example
#interface MyObject()
#property(retain) NSArray *myArray;
#end
If I had to think of a reason to avoid them, I'd say don't use it for computed attributes where the computation involved is significant. Properties encourage code like:
if (foobar.weight > 100) {
goober.capacity = foobar.weight;
}
In this example, foobar.weight is called twice. If it's just returning a cached value, no problem. But if it needs to block the thread while it deploys a robot to manually weigh the foobar each time, the above snipped of code would waste two robot deployments when only one is needed.
In such cases, I'd recommend NOT using a property, and also naming the method differently, so that the code would look more like:
int w = [foobar computeWeight];
if (w > 100) {
goober.capacity = w;
}
With a name like computeWeight it is easier to remember that it is a long running operation.
I would avoid using properties if the accessor method does something non-obvious to the object, like setting an unrelated instance variable. Also if the property being returned doesn't really "belong" to the object. For instance, in one of my projects I have a stringValue method that I decided not to make a property for this reason. This is really more a matter of style though.
A question that has pondered me for the last while. I am primarily a .net developer who dabbles in Objective-C for iPhone and Mac.
How do you go about sending "datasets" between methods in objective-c. For example in C# you can populate a custom class with data and pass it around in a List of type custom class. EG if you had a customer class you would just do something like:
List<Customer> customers = DataLayer.GetAllCustomers();
The only way I can see how this could be done in obj-c would be to populate an NSArray with custom objects? Is this an efficient way to do things? Any other recommendations? I am using sqlite as the database/data I want to return.
You're on the right track.
Cocoa's collection classes — which all have mutable an immutable variants — are:
NSArray: ordered, can contain an object multiple times
NSDictionary: unordered, mapping from keys to values, keys are copied
NSSet: unordered, can contain an object only once
NSCountedSet: unordered, can contain an object multiple times
The immutable variants help a lot with efficiency. The standard pattern for accessors of classes that have mutable variants is to copy rather than retain. This is codified in the #property mechanism, by using the copy attribute on the property:
// Department.h
#interface Department : NSObject
#property (readwrite, copy) NSSet *employees;
#end
This means that if you pass a mutable array to something that takes an array, it will be copied, and if you pass that to something else, it will be copied again. The trick is though that "copying" an immutable object really just retains it, so you only take a hit for that first copy. You probably want to make a copy that first time anyway so you don't pass a mutable array to something else, then mutate it behind the back of whatever you passed it to.
For Cocoa on Mac OS X, I'd also strongly encourage you to take a look at Core Data. It's an alternative to the "data set" pattern you might be used to from .NET/ADO/etc. With Core Data, you don't "get all customers" and then pass that collection around. Instead you query for the customers you care about, and as you traverse relationships of the objects you've queried for, other objects will be pulled in for you automatically.
Core Data also gets you features like visual modeling of your entities, automatic generation of property getters & setters, fine-grained control over migration from one schema version to another, and so on.