Alternative to global variables in app delegate - iphone

I am developing an application with a speedometer like animation (a meter and an arrow to indicate something on the meter). I store the arrow's position in a global variable declared in my app delegate. I am doing it this way because the arrow position is updated and used by several classes.
However, I am insecure whether this is a good or a bad design decision. My thoughts are that since it is a non-critical piece of information (just a float), no harm is done when storing it globally. But my OOP heart hurts every time I say the word "global" to myself.
Alternatively I have studiet singletons, but as far as I have read, singletons are used when the developer wishes to create one and only one instance of a certain object.
Am I doing it correct or is there a more proper way of doing what I do?

I am doing it this way because the arrow position is updated and used by several classes.
in many cases, you can reduce the scope. this reduces inter-component dependency.
However, I am insecure whether this is a good or a bad design decision. My thoughts are that since it is a non-critical piece of information (just a float), no harm is done when storing it globally. But my OOP heart hurts every time I say the word "global" to myself.
perhaps you can move the state (the float value) to an ivar in your speedometer? example: you likely display just one speedometer view: does it make more sense to add it to what is the view's model? or perhaps to its controller? (yes, it's a bit tough to provide a more specific example without the source)
Alternatively I have studiet singletons, but as far as I have read, singletons are used when the developer wishes to create one and only one instance of a certain object.
not necessary, and a severe pain to maintain. most of the cocoa singletons i have seen should not have been considered singletons, and caused a lot of headaches. better yet, you can write programs which use zero singletons. this is ideal, and easy to test. as is, the programs/types which depend on the app controller's have been compromised wrt testability and reusability.
Am I doing it correct or is there a more proper way of doing what I do?
in the vast majority of cases, you can simply reduce the scope and localize it, while removing global state. with a little more effort, you can remove that value as a global -- that is best.
although it is not a good thing... let's assume you really really really really really must introduce global state:
don't use a singleton. chances are good that you will rewrite it when you want to reuse it. it sugar coats what is ugly. if your app controller is a mess due to too much global state, at least the fact that you have too much global state will be obvious.
hold your global state in your app controller. your app controller is responsible for its initialization, lifetime, and access.
provide that state to dependencies, so they do not refer back to (or even know about) the global domain (the app controller). then you may minimize the impact.
there's also a distinct difference between global state and application/execution state. global state should be eliminated. execution state is not global state, but localized execution context. execution state can be reintroduced at the right level, altered, and updated, tested, and reused predictably. a good design will introduce execution state when needed, and at the right level while avoiding global state.
Update
Your sample is pretty close to what i had imagined, based on the description in the OP. It provided some additional specifics. So the sample below (you'll need some additions in obvious areas to piece it all together) demonstrates how you could update the controller interfaces, and there are two free 'elsewhere' methods at the end which further illustrate how to use these:
#interface MONArrowPosition : NSObject
{
float arrowPosition;
}
#end
#implementation MONArrowPosition
- (id)initWithPosition:(float)position
{
self = [super init];
if (nil != self) {
arrowPosition = position;
}
return self;
}
#end
#interface MyViewController1 : UIViewController
{
MONArrowPosition * arrowPosition; // << may actually be held by the model
}
#end
#implementation MyViewController1
- (void)applyRotation
{
[self rotateLayer:arrow from:self.arrowPosition to:callStatus speed:METER_SPEED];
}
#end
#interface MyViewController2 : UIViewController
{
MONArrowPosition * arrowPosition; // << may actually be held by the model
}
#end
#implementation MyViewController2
- (void)viewDidLoad
{
[super viewDidLoad];
/* ... */
[self.slider addTarget:self action:#selector(sliderValueDidChange) forControlEvents:controlEvents];
}
- (void)sliderValueDidChange
{
self.arrowPosition.arrowPosition = self.slider.value;
[self arrowPositionDidChange];
}
#end
/* elsewhere: */
- (void)initializeArrowPosition
{
/* The variable is set to a default of 0.0f */
MONArrowPosition * arrowPosition = [[MONArrowPosition alloc] initWithPosition:0.0f];
/* ... */
}
- (IBAction)someActionWhichPushesMyViewController1
{
// depending on the flow of your app, the body of initializeArrowPosition
// *could* be right here
MyViewController1 * viewController = [[MyViewController1 alloc] initWithNibName:nibName bundle:bundle];
viewController.arrowPosition = self.arrowPosition;
/* push it */
}
and then if MyViewController1 pushes MyViewController2, locating and setting the arrow position will be easy. the view controllers may also be sharing some information in the models. with a global in your sample, you are crossing many implementations, which adds coupling, increases dependency, etc.. so if you can take this approach and localize the execution state, you're off to a good start. then you can use any number of view controllers with any number of MONArrowPositions, and they will not be subject to the effects of global state. again, i can't get too specific using the samples provided, but i think this should illustrate the concepts i originally outlined well enough (i don't think a project-wide review is needed).

Well this is something that is keeping a lot of programmers up at night.
I try not to misuse the app delegate as much, I'll create a singleton for storing more or less global information. There is no real other way to do it then either the singleton or the app delegate.
But if only one viewController need the information than, the information will never leave that viewController. That viewcontroller could pass that information on to other viewcontroller is needed.
In you case it might be an idea to have some kind of directionManager which hold the floats and might even hold the CLLocationManager.

For this type of thing, I like to use NSNotifications. You have all the view controllers who care about the arrow's position listen for the specific notification, and they can all update the UI at once.

Related

Cocos2d: usage of references vs getChild performance

I am unsure on which approach will give me a better performance:
I have a GameScene class in which I tend to allocate a objects and then add them as childs to the class with a tag. This approach is used in many examples I studied but I am not sure if it is the best when I need to frequently access to child objects (e.g. update a score label in the GameScene). In those cases I am wondering if it would be a better approach in terms of performance to declare a pointer to those frequently used object and use it to access the object instead of getting the child by tag.
Is it more efficient to use getChildByTag or accessing those objects via their pointer?
As example I provide a label that I frequently update during the game, e.g. it could be the score label:
#interface GameScene : CCLayer
{
CCLabelTTF *frequentlyUsedLabel;
}
//Implementation
-(id) initWithId:(int)sceneId
{
if ((self = [super init]))
{
//..code
frequentlyUsedLabel = [CCLabelTTF labelWithString:#"Hearths:" fontName:#"Arial" fontSize:20];
[self addChild:frequentlyUsedLabel];
}
}
Write code that is easy to maintain.
Anything worth optimizing is worth measuring.
Time how long it takes to render a frame using both methods. Ask yourself if it matters.
The extra memory overhead is a little more difficult to measure (in particular, Cocos2D might be using a clever allocator that is more efficient if your CCLayer subclass doesn't declare any extra ivars). My take is that 4 bytes is the amount of memory used by a single pixel.
With UIKit, I personally find it much easier to use ivars than to worry about tag uniqueness (especially when reusing code in different apps or using a view in multiple places). This is especially the case with ARC, since you no longer have to worry about getters/setters/retain/release.

CMMotionManager is a global resource? What does this means?

I am trying to initialize the CMMotionManager so start updates and create a reference attitude matrix, and then when i click a button trough the storyboard, i display a different screen (which is in a viewcontroller) and i want to use the reference attitude matrix and other readings from the motion manager but if I do a simple check to see if its ready it says it isnt (even thought it was ready on the previous screen).
So I was researching a little bit and i came across some standford notes that say it is a global resource so that it is ok to either use delegates or classes, that got me thinking.
If i use a delegate then technically the owner of the resource is doing the action for me right? so it doesnt really mean it is global.
What about classes? i tried implementing a MotionManager Class but i still didnt get any readings on the second screen... and i just didnt initialize it again on the new screen because i dont want to have multiple instances runing at the same time.
To solve my problem i also suppose i could initialize it once in the main one, save the attitude, pass it to the next one in a segue transition and just re initialize the motion manager so i only have 1 instance (or close old one on screen will dissapear).
But i do not want this because the user might click right away on the screen and the motion manager does take a little bit of time to initialize (or thats what i noticed).
Thanks in advance for any help you can provide.
EDIT:
Ok i tried the delegate method and i still cant read from the device manager in the second window. What comes to mind is that MAYBE when I am going to the second window xcode is automaticaly releasing my instance of Motion manager.... (CMMotionManager).
Anyone knows how to check this?
I hope I understood you right. Then I suggest using a singleton design pattern encapsulating motion manager access in a specialised class. Some pseudo code:
MotionHandler.h
#interface MotionHandler {
CMMotionManager* motionManager;
+ (MotionHandler*) getInstance;
}
MotionHandler.c:
#interface MotionHandler {
static MotionHandler* instance;
+ (MotionHandler*) getInstance {
if (instance == nil) {
instance = [[self alloc] init];
}
return instance;
}
- (id)init {
if ((self = [super init])) {
motionManager = [[CMMotionManager alloc] init];
// initialise CMMotionManager
}
}
}
So there is one instance of MotionHandler only which manages access to CMMotionManager. You can accesss your CMMotionManager instance from everywhere with MotionHandler.getInstance.motionManager.
If you need access to CoreMotion from several classes, I recommend total encapsulation of CMMotionManager access. That means make it #private and provide methods like getDeviceMotion, setReferenceAttitude, ...
This helps to avoid complications like starting it twice or access to CMDeviceMotion before start and makes it more convenient to debug.

Changing cell appearance when editing UITableView _without_ using custom cells?

If I am using a custom UITableViewCell I can use the following methods to change the cell's appearance when transitioning state:
- (void)willTransitionToState:(UITableViewCellStateMask)state
- (void)didTransitionToState:(UITableViewCellStateMask)state
Is there a way to achieve this if I'm not using a custom tableview cell?
Edit: Please see Daniel Hanly's comment. Categories may be selectively applied using #import. My apologies to anyone that may have been misled by this answer. Relevant sections will be redacted for future reference.
Okay, attempt number two. As far as I am aware, there is no other documented way to implement the functionality you require without subclassing UITableViewCell. It's worth noting that Apple's docs on UITableViewCell specifically mention that the state transition methods are meant to be implemented by subclasses. That having been said, If you absolutely need to implement them without a subclass, there are a couple of less conventional solutions. Each comes with its own issues, and it may end up being unfeasible for you to implement them, but it's an interesting question nonetheless.
Disclaimer
If you only want a sane and relatively simple explanation, then consider the answer to your question to be "no, there is no way to do what you want." I only present the options below with the assertion that they will work. In no way do I endorse actually using them. Consider this my penance for providing my first answer with such an obvious flaw.
Option One - Categories
It is possible to get the functionality you're looking for by overriding the methods you listed in a custom UITableViewCell category.
The problem is that this approach would be a pretty bad idea 99% of the time. Once you define the category on UITableViewCell, those methods would be defined for all UITableViewCell objects throughout the app. Unless you want the exact same state transition functionality for every single table cell in the app, this approach isn't very helpful.
Option Two - Runtime magic
You can use the low-level Objective-C runtime functions to change the implementation of any method on the fly. Unlike the categories option, this approach is flexible enough to redefine the intended behavior whenever you need to, instead of being a one-shot deal.
For example, if you're trying to manage state transitions from a UITableViewController, you could do this:
CustomTableViewController.m
#import <objc/runtime.h>
- (void) customStateWillChange:(UITableViewCellStateMask)state
{
//custom UITableViewCell code
}
- (void) viewDidAppear:(BOOL)animated
{
//Store the original implementation
Method originalStateWillChangeMethod = class_getInstanceMethod([UITableViewCell class], #selector(willTransitionToState:));
originalStateWillChangeImplementation = method_getImplementation(originalStateWillChangeMethod); //variable declared in header file as type IMP
//Get the new implementation
Method newStateWillChangeMethod = class_getInstanceMethod([self class], #selector(customStateWillChange:));
IMP newStateWillChangeImplementation = method_getImplementation(newStateWillChangeMethod);
//Replace implementation
method_setImplementation(originalStateWillChangeMethod, newStateWillChangeImplementation);
//the rest of your viewDidAppear code
[super viewDidAppear:animated];
}
- (void) viewDidDisappear:(BOOL)animated
{
//restore the original implementation
Method originalStateWillChangeMethod = class_getInstanceMethod([UITableViewCell class], #selector(willTransitionToState:));
method_setImplementation(originalStateWillChangeMethod, originalStateWillChangeImplementation);
//rest of viewDidDisappear code
[super viewDidDisappear:animated];
}
This code may not suit your exact purposes, but I think it provides a useful example.
It's incredibly ugly though because the customStateWillChange: method defined here is only intended to be run as a part of the UITableViewCell class, but in this example it will be compiled as though it were part of the CustomTableController class. Among other annoyances, you would have to eschew the property dot notation, ignore compiler warnings and give up most if not all compile-time checks for that method's body.
Option 3 - Category with runtime magic
Exactly what it sounds like. Define any custom state change methods you like within a category (or several categories) on UITableViewCell. Be sure that each one has a separate name - adding two categories that each have a method of the same name will result in undefined behavior. Also, each one needs to have the same return type and argument types as the method it is intended to replace.
Then the references to [self class] in the above code would be replaced with [UITableViewCell class], and the customStateWillChange: method would be moved to the custom category. While still ugly, you can at least rely on the compiler to interpret the method bodies properly.
Of course, messing with the runtime adds a whole lot of complexity to keep track of. It could work fine, but it's not good design, it would take serious effort to ensure it worked safely and correctly, and it would be likely to bring anguish and despair to anyone maintaining it.
References
The Objective-C Programming Language - Categories and Extensions
Objective-C Runtime Reference
Absolutely. The UITableViewDelegate protocol specifies a number of methods to manage state transitions for the table view's cells. Take a look at the UITableViewDelegate Class Reference, specifically the methods listed under the heading "Editing Table Rows".
Edit
Sorry, you're right. The UITableViewDelegate methods don't respond to direct changes to the cell's properties. I've found a way that does work, but I'm going to put it in a different answer to avoid confusion.

Dealing with variable assignments and async requests

I'm looking for a reliable design for handling assignments that have asynchronous requests involved. To further clarify, I have a class which handles Data Management. It is a singleton and contains a lot of top level data for me which is used throughout my iPhone application.
A view controller might do something such as the following:
users = [MySingleton sharedInstance].users;
MySingleton will then override the synthesized users getter and see if it is set. If it is not set, it will speak to a Connection Manager (a wrapper for NSURLConnection and its delegate methods) which fires off an asynchronous request, and this is where problems begin. I cannot guarantee when "users" will be available. I could change the request to synchronous, but that will directly effect user experience, especially in a mobile environment where bandwidth is limited already.
I need to be able to at some point, have some kind of locking/synchronization code going on in my getter that doesn't return users until it is available or is nil.
Once the NSURLConnection has the data available, it needs to callback something/somewhere with a response object and let the getter know the data is available.. whether it's failed or succeeded.
Any suggestions on handling this?
I solved this problem a couple ways in different apps.
One solution is to pass an object and selector along to notify such as:
- (id)getUsersAndNotifyObject:(id)object selector:(SEL)selector
This breaks the nice property behavior however. If you want to keep the methods as properties, have them return immediately, with either cached data or nil. If you need to go out to the network, do so asynchronous and then let the rest of the app know the data changed via KVO or the NSNotificationCenter. (Cocoa Bindings would be an option on the Mac, but they don't exist on iPhone).
The two methods are fairly similar. Register for updates with your shared instance, and then ask for the data. KVO is a little lighter weight if you just dealing with raw observable properties, but an NSNotification might be more convenient if you're interested in several different pieces of data.
With an NSNotification, the client object could register for one type of notification which includes the changed data in its userInfo dictionary instead of having to register obvservers for every single key path you're interested in.
An NSNotification would also allow you to pass back failures or other status information a lot more easily than straight KVO.
KVO method:
// register observer first so you don't miss an update
[[MySingleton sharedInstance] addObserver:self
forKeyPath:#"users"
options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
context:&kvo_users_context];
users = [MySingleton sharedInstance].users;
// implement appropriate observeValueForKeyPath:ofObject:change:context: method
NSNotification Method:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(sharedDataChanged:)
name:MySingletonDataUpdatedNotification
object:[MySingletonDataUpdatedNotification sharedInstance]];
users = [MySingleton sharedInstance].users;
// implement appropriate sharedDataChanged: method
You can either use a delegate pattern or a notification pattern here.
A delegate would let a particular object know when users is complete, a notification pattern would notify any object that wants to know. Both are valid, depending on your situation.
Just remember: if you have any race issues in your app, your architecture is probably all wrong.
It took me a while to realize what the best way of handling this kind of typical task; it turns out the clue is in the design of many of Cocoa and CocoaTouch's own APIs: delegation.
The reason so many of Cocoa's APIs use delegation is because it fits very well with the asynchronous nature of many GUI apps.
It seems perfectly normal to want do do something along the lines of:
users = [MyDataFactory getUsers];
Except, as you point out, you have no idea when the getUsers method will finish. Now, there are some light-weight solutions to this; amrox mentioned a few in his post above (personally I'd say notifications aren't such a good fit but the object:selector: pattern is reasonable), but if you are doing this kind of thing a lot the delegation pattern tends to yield a more elegant solution.
I'll try to explain by way of an example of how I do things in my application.
Let's say we have a domain class, Recipe. Recipes are fetched from a web service. I typically have a series of repository classes, one for each entity in my model. A repository class' responsibility is to fetch the data required for the entity (or a collection of them), use that data to construct the objects, and then pass those objects onto something else to make use of them (typically a controller or data source).
My RecipeRepository interface might look something like this:
#interface RecipeRepository {}
- (void)initWithDelegate:(id)aDelegate;
- (void)findAllRecipes;
- (void)findRecipeById:(NSUInteger)anId;
#end
I'd then define a protocol for my delegate; now, this can be done as an informal or formal protocol, there are pros and cons of each approach that aren't relevant to this answer. I'll go with a formal approach:
#protocol RepositoryDelegateProtocol
- (void)repository:(id)repository didRetrieveEntityCollection:(NSArray *)collection;
- (void)repository:(id)repository didRetrieveEntity:(id)entity;
#end
You'll notice I've gone for a generic approach; you will likely have multiple XXXRepository classes in your app and each will use the same protocol (you may also choose to extract a base EntityRepository class that encapsulates some common logic).
Now, to use this in a controller, for example, where you previous would have done something such as:
- (void)viewDidLoad
{
self.users = [MySingleton getUsers];
[self.view setNeedsDisplay];
}
You would do something like this:
- (void)viewDidLoad
{
if(self.repository == nil) { // just some simple lazy loading, we only need one repository instance
self.repository = [[[RecipeRepository alloc] initWithDelegate:self] autorelease];
}
[self.repository findAllRecipes];
}
- (void)repository:(id)repository didRetrieveEntityCollection:(NSArray *)collection;
{
self.users = collection;
[self.view setNeedsDisplay];
}
You could even extend this further to display some kind of "loading" notice with an additional delegate method:
#protocol RepositoryDelegateProtocol
- (void)repositoryWillLoadEntities:(id)repository;
#end
// in your controller
- (void)repositoryWillLoadEntities:(id)repository;
{
[self showLoadingView]; // etc.
}
Another thing about this design is that your repository classes really don't need to be singletons - they can be instantiated wherever you need them. They may deal with some kind of singleton connection manager but at this layer of abstraction a singleton is unnecessary (and its always good to avoid singletons where possible).
There is a downside to this approach; you may find you need layers of delegation at each level. For instance, your repositories may interact with some kind of connection object which does the actual asynchronous data loading; the repository might interact with the connection object using it's own delegation protocol.
As a result you might find you have to "bubble up" these delegation events throughout the different layers of your application using delegates that get more and more coarse-grained as they get closer to your application-level code. This can create a layer of indirection that can make your code harder to follow.
Anyway, this is my first answer on SO, I hope its been helpful.

What are best practices that you use when writing Objective-C and Cocoa? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
I know about the HIG (which is quite handy!), but what programming practices do you use when writing Objective-C, and more specifically when using Cocoa (or CocoaTouch).
There are a few things I have started to do that I do not think are standard:
1) With the advent of properties, I no longer use "_" to prefix "private" class variables. After all, if a variable can be accessed by other classes shouldn't there be a property for it? I always disliked the "_" prefix for making code uglier, and now I can leave it out.
2) Speaking of private things, I prefer to place private method definitions within the .m file in a class extension like so:
#import "MyClass.h"
#interface MyClass ()
- (void) someMethod;
- (void) someOtherMethod;
#end
#implementation MyClass
Why clutter up the .h file with things outsiders should not care about? The empty () works for private categories in the .m file, and issues compile warnings if you do not implement the methods declared.
3) I have taken to putting dealloc at the top of the .m file, just below the #synthesize directives. Shouldn't what you dealloc be at the top of the list of things you want to think about in a class? That is especially true in an environment like the iPhone.
3.5) In table cells, make every element (including the cell itself) opaque for performance. That means setting the appropriate background color in everything.
3.6) When using an NSURLConnection, as a rule you may well want to implement the delegate method:
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
return nil;
}
I find most web calls are very singular and it's more the exception than the rule you'll be wanting responses cached, especially for web service calls. Implementing the method as shown disables caching of responses.
Also of interest, are some good iPhone specific tips from Joseph Mattiello (received in an iPhone mailing list). There are more, but these were the most generally useful I thought (note that a few bits have now been slightly edited from the original to include details offered in responses):
4) Only use double precision if you have to, such as when working with CoreLocation. Make sure you end your constants in 'f' to make gcc store them as floats.
float val = someFloat * 2.2f;
This is mostly important when someFloat may actually be a double, you don't need the mixed-mode math, since you're losing precision in 'val' on storage. While floating-point numbers are supported in hardware on iPhones, it may still take more time to do double-precision arithmetic as opposed to single precision. References:
Double vs float on the iPhone
iPhone/iPad double precision math
On the older phones supposedly calculations operate at the same speed but you can have more single precision components in registers than doubles, so for many calculations single precision will end up being faster.
5) Set your properties as nonatomic. They're atomic by default and upon synthesis, semaphore code will be created to prevent multi-threading problems. 99% of you probably don't need to worry about this and the code is much less bloated and more memory-efficient when set to nonatomic.
6) SQLite can be a very, very fast way to cache large data sets. A map application for instance can cache its tiles into SQLite files. The most expensive part is disk I/O. Avoid many small writes by sending BEGIN; and COMMIT; between large blocks. We use a 2 second timer for instance that resets on each new submit. When it expires, we send COMMIT; , which causes all your writes to go in one large chunk. SQLite stores transaction data to disk and doing this Begin/End wrapping avoids creation of many transaction files, grouping all of the transactions into one file.
Also, SQL will block your GUI if it's on your main thread. If you have a very long query, It's a good idea to store your queries as static objects, and run your SQL on a separate thread. Make sure to wrap anything that modifies the database for query strings in #synchronize() {} blocks. For short queries just leave things on the main thread for easier convenience.
More SQLite optimization tips are here, though the document appears out of date many of the points are probably still good;
http://web.utk.edu/~jplyon/sqlite/SQLite_optimization_FAQ.html
Don't use unknown strings as format strings
When methods or functions take a format string argument, you should make sure that you have control over the content of the format string.
For example, when logging strings, it is tempting to pass the string variable as the sole argument to NSLog:
NSString *aString = // get a string from somewhere;
NSLog(aString);
The problem with this is that the string may contain characters that are interpreted as format strings. This can lead to erroneous output, crashes, and security problems. Instead, you should substitute the string variable into a format string:
NSLog(#"%#", aString);
Use standard Cocoa naming and formatting conventions and terminology rather than whatever you're used to from another environment. There are lots of Cocoa developers out there, and when another one of them starts working with your code, it'll be much more approachable if it looks and feels similar to other Cocoa code.
Examples of what to do and what not to do:
Don't declare id m_something; in an object's interface and call it a member variable or field; use something or _something for its name and call it an instance variable.
Don't name a getter -getSomething; the proper Cocoa name is just -something.
Don't name a setter -something:; it should be -setSomething:
The method name is interspersed with the arguments and includes colons; it's -[NSObject performSelector:withObject:], not NSObject::performSelector.
Use inter-caps (CamelCase) in method names, parameters, variables, class names, etc. rather than underbars (underscores).
Class names start with an upper-case letter, variable and method names with lower-case.
Whatever else you do, don't use Win16/Win32-style Hungarian notation. Even Microsoft gave up on that with the move to the .NET platform.
IBOutlets
Historically, memory management of outlets has been poor.
Current best practice is to declare outlets as properties:
#interface MyClass :NSObject {
NSTextField *textField;
}
#property (nonatomic, retain) IBOutlet NSTextField *textField;
#end
Using properties makes the memory management semantics clear; it also provides a consistent pattern if you use instance variable synthesis.
Use the LLVM/Clang Static Analyzer
NOTE: Under Xcode 4 this is now built into the IDE.
You use the Clang Static Analyzer to -- unsurprisingly -- analyse your C and Objective-C code (no C++ yet) on Mac OS X 10.5. It's trivial to install and use:
Download the latest version from this page.
From the command-line, cd to your project directory.
Execute scan-build -k -V xcodebuild.
(There are some additional constraints etc., in particular you should analyze a project in its "Debug" configuration -- see http://clang.llvm.org/StaticAnalysisUsage.html for details -- the but that's more-or-less what it boils down to.)
The analyser then produces a set of web pages for you that shows likely memory management and other basic problems that the compiler is unable to detect.
This is subtle one but handy one. If you're passing yourself as a delegate to another object, reset that object's delegate before you dealloc.
- (void)dealloc
{
self.someObject.delegate = NULL;
self.someObject = NULL;
//
[super dealloc];
}
By doing this you're ensuring that no more delegate methods will get sent. As you're about to dealloc and disappear into the ether you want to make sure that nothing can send you any more messages by accident. Remember self.someObject could be retained by another object (it could be a singleton or on the autorelease pool or whatever) and until you tell it "stop sending me messages!", it thinks your just-about-to-be-dealloced object is fair game.
Getting into this habit will save you from lots of weird crashes that are a pain to debug.
The same principal applies to Key Value Observation, and NSNotifications too.
Edit:
Even more defensive, change:
self.someObject.delegate = NULL;
into:
if (self.someObject.delegate == self)
self.someObject.delegate = NULL;
#kendell
Instead of:
#interface MyClass (private)
- (void) someMethod
- (void) someOtherMethod
#end
Use:
#interface MyClass ()
- (void) someMethod
- (void) someOtherMethod
#end
New in Objective-C 2.0.
Class extensions are described in Apple's Objective-C 2.0 Reference.
"Class extensions allow you to declare additional required API for a class in locations other than within the primary class #interface block"
So they're part of the actual class - and NOT a (private) category in addition to the class. Subtle but important difference.
Avoid autorelease
Since you typically(1) don't have direct control over their lifetime, autoreleased objects can persist for a comparatively long time and unnecessarily increase the memory footprint of your application. Whilst on the desktop this may be of little consequence, on more constrained platforms this can be a significant issue. On all platforms, therefore, and especially on more constrained platforms, it is considered best practice to avoid using methods that would lead to autoreleased objects and instead you are encouraged to use the alloc/init pattern.
Thus, rather than:
aVariable = [AClass convenienceMethod];
where able, you should instead use:
aVariable = [[AClass alloc] init];
// do things with aVariable
[aVariable release];
When you're writing your own methods that return a newly-created object, you can take advantage of Cocoa's naming convention to flag to the receiver that it must be released by prepending the method name with "new".
Thus, instead of:
- (MyClass *)convenienceMethod {
MyClass *instance = [[[self alloc] init] autorelease];
// configure instance
return instance;
}
you could write:
- (MyClass *)newInstance {
MyClass *instance = [[self alloc] init];
// configure instance
return instance;
}
Since the method name begins with "new", consumers of your API know that they're responsible for releasing the received object (see, for example, NSObjectController's newObject method).
(1) You can take control by using your own local autorelease pools. For more on this, see Autorelease Pools.
Some of these have already been mentioned, but here's what I can think of off the top of my head:
Follow KVO naming rules. Even if you don't use KVO now, in my experience often times it's still beneficial in the future. And if you are using KVO or bindings, you need to know things are going work the way they are supposed to. This covers not just accessor methods and instance variables, but to-many relationships, validation, auto-notifying dependent keys, and so on.
Put private methods in a category. Not just the interface, but the implementation as well. It's good to have some distance conceptually between private and non-private methods. I include everything in my .m file.
Put background thread methods in a category. Same as above. I've found it's good to keep a clear conceptual barrier when you're thinking about what's on the main thread and what's not.
Use #pragma mark [section]. Usually I group by my own methods, each subclass's overrides, and any information or formal protocols. This makes it a lot easier to jump to exactly what I'm looking for. On the same topic, group similar methods (like a table view's delegate methods) together, don't just stick them anywhere.
Prefix private methods & ivars with _. I like the way it looks, and I'm less likely to use an ivar when I mean a property by accident.
Don't use mutator methods / properties in init & dealloc. I've never had anything bad happen because of it, but I can see the logic if you change the method to do something that depends on the state of your object.
Put IBOutlets in properties. I actually just read this one here, but I'm going to start doing it. Regardless of any memory benefits, it seems better stylistically (at least to me).
Avoid writing code you don't absolutely need. This really covers a lot of things, like making ivars when a #define will do, or caching an array instead of sorting it each time the data is needed. There's a lot I could say about this, but the bottom line is don't write code until you need it, or the profiler tells you to. It makes things a lot easier to maintain in the long run.
Finish what you start. Having a lot of half-finished, buggy code is the fastest way to kill a project dead. If you need a stub method that's fine, just indicate it by putting NSLog( #"stub" ) inside, or however you want to keep track of things.
Write unit tests. You can test a lot of things in Cocoa that might be harder in other frameworks. For example, with UI code, you can generally verify that things are connected as they should be and trust that they'll work when used. And you can set up state & invoke delegate methods easily to test them.
You also don't have public vs. protected vs. private method visibility getting in the way of writing tests for your internals.
Golden Rule: If you alloc then you release!
UPDATE: Unless you are using ARC
Don't write Objective-C as if it were Java/C#/C++/etc.
I once saw a team used to writing Java EE web applications try to write a Cocoa desktop application. As if it was a Java EE web application. There was a lot of AbstractFooFactory and FooFactory and IFoo and Foo flying around when all they really needed was a Foo class and possibly a Fooable protocol.
Part of ensuring you don't do this is truly understanding the differences in the language. For example, you don't need the abstract factory and factory classes above because Objective-C class methods are dispatched just as dynamically as instance methods, and can be overridden in subclasses.
Make sure you bookmark the Debugging Magic page. This should be your first stop when banging your head against a wall while trying to find the source of a Cocoa bug.
For example, it will tell you how to find the method where you first allocated memory that later is causing crashes (like during app termination).
Try to avoid what I have now decided to call Newbiecategoryaholism. When newcomers to Objective-C discover categories they often go hog wild, adding useful little categories to every class in existence ("What? i can add a method to convert a number to roman numerals to NSNumber rock on!").
Don't do this.
Your code will be more portable and easier to understand with out dozens of little category methods sprinkled on top of two dozen foundation classes.
Most of the time when you really think you need a category method to help streamline some code you'll find you never end up reusing the method.
There are other dangers too, unless you're namespacing your category methods (and who besides the utterly insane ddribin is?) there is a chance that Apple, or a plugin, or something else running in your address space will also define the same category method with the same name with a slightly different side effect....
OK. Now that you've been warned, ignore the "don't do this part". But exercise extreme restraint.
Resist subclassing the world. In Cocoa a lot is done through delegation and use of the underlying runtime that in other frameworks is done through subclassing.
For example, in Java you use instances of anonymous *Listener subclasses a lot and in .NET you use your EventArgs subclasses a lot. In Cocoa, you don't do either — the target-action is used instead.
Sort strings as the user wants
When you sort strings to present to the user, you should not use the simple compare: method. Instead, you should always use localized comparison methods such as localizedCompare: or localizedCaseInsensitiveCompare:.
For more details, see Searching, Comparing, and Sorting Strings.
Declared Properties
You should typically use the Objective-C 2.0 Declared Properties feature for all your properties. If they are not public, add them in a class extension. Using declared properties makes the memory management semantics immediately clear, and makes it easier for you to check your dealloc method -- if you group your property declarations together you can quickly scan them and compare with the implementation of your dealloc method.
You should think hard before not marking properties as 'nonatomic'. As The Objective C Programming Language Guide notes, properties are atomic by default, and incur considerable overhead. Moreover, simply making all your properties atomic does not make your application thread-safe. Also note, of course, that if you don't specify 'nonatomic' and implement your own accessor methods (rather than synthesising them), you must implement them in an atomic fashion.
Think about nil values
As this question notes, messages to nil are valid in Objective-C. Whilst this is frequently an advantage -- leading to cleaner and more natural code -- the feature can occasionally lead to peculiar and difficult-to-track-down bugs if you get a nil value when you weren't expecting it.
Use NSAssert and friends.
I use nil as valid object all the time ... especially sending messages to nil is perfectly valid in Obj-C.
However if I really want to make sure about the state of a variable, I use NSAssert and NSParameterAssert, which helps to track down problems easily.
Simple but oft-forgotten one. According to spec:
In general, methods in different
classes that have the same selector
(the same name) must also share the
same return and argument types. This
constraint is imposed by the compiler
to allow dynamic binding.
in which case all the same named selectors, even if in different classes, will be regarded as to have identical return/argument types. Here is a simple example.
#interface FooInt:NSObject{}
-(int) print;
#end
#implementation FooInt
-(int) print{
return 5;
}
#end
#interface FooFloat:NSObject{}
-(float) print;
#end
#implementation FooFloat
-(float) print{
return 3.3;
}
#end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
id f1=[[FooFloat alloc]init];
//prints 0, runtime considers [f1 print] to return int, as f1's type is "id" and FooInt precedes FooBar
NSLog(#"%f",[f1 print]);
FooFloat* f2=[[FooFloat alloc]init];
//prints 3.3 expectedly as the static type is FooFloat
NSLog(#"%f",[f2 print]);
[f1 release];
[f2 release]
[pool drain];
return 0;
}
If you're using Leopard (Mac OS X 10.5) or later, you can use the Instruments application to find and track memory leaks. After building your program in Xcode, select Run > Start with Performance Tool > Leaks.
Even if your app doesn't show any leaks, you may be keeping objects around too long. In Instruments, you can use the ObjectAlloc instrument for this. Select the ObjectAlloc instrument in your Instruments document, and bring up the instrument's detail (if it isn't already showing) by choosing View > Detail (it should have a check mark next to it). Under "Allocation Lifespan" in the ObjectAlloc detail, make sure you choose the radio button next to "Created & Still Living".
Now whenever you stop recording your application, selecting the ObjectAlloc tool will show you how many references there are to each still-living object in your application in the "# Net" column. Make sure you not only look at your own classes, but also the classes of your NIB files' top-level objects. For example, if you have no windows on the screen, and you see references to a still-living NSWindow, you may have not released it in your code.
Clean up in dealloc.
This is one of the easiest things to forget - esp. when coding at 150mph. Always, always, always clean up your attributes/member variables in dealloc.
I like to use Objc 2 attributes - with the new dot notation - so this makes the cleanup painless. Often as simple as:
- (void)dealloc
{
self.someAttribute = NULL;
[super dealloc];
}
This will take care of the release for you and set the attribute to NULL (which I consider defensive programming - in case another method further down in dealloc accesses the member variable again - rare but could happen).
With GC turned on in 10.5, this isn't needed so much any more - but you might still need to clean up others resources you create, you can do that in the finalize method instead.
All these comments are great, but I'm really surprised nobody mentioned Google's Objective-C Style Guide that was published a while back. I think they have done a very thorough job.
Also, semi-related topic (with room for more responses!):
What are those little Xcode tips & tricks you wish you knew about 2 years ago?.
Don't forget that NSWindowController and NSViewController will release the top-level objects of the NIB files they govern.
If you manually load a NIB file, you are responsible for releasing that NIB's top-level objects when you are done with them.
One rather obvious one for a beginner to use: utilize Xcode's auto-indentation feature for your code. Even if you are copy/pasting from another source, once you have pasted the code, you can select the entire block of code, right click on it, and then choose the option to re-indent everything within that block.
Xcode will actually parse through that section and indent it based on brackets, loops, etc. It's a lot more efficient than hitting the space bar or tab key for each and every line.
I know I overlooked this when first getting into Cocoa programming.
Make sure you understand memory management responsibilities regarding NIB files. You are responsible for releasing the top-level objects in any NIB file you load. Read Apple's Documentation on the subject.
Turn on all GCC warnings, then turn off those that are regularly caused by Apple's headers to reduce noise.
Also run Clang static analysis frequently; you can enable it for all builds via the "Run Static Analyzer" build setting.
Write unit tests and run them with each build.
Variables and properties
1/ Keeping your headers clean, hiding implementation
Don't include instance variables in your header. Private variables put into class continuation as properties. Public variables declare as public properties in your header.
If it should be only read, declare it as readonly and overwrite it as readwrite in class continutation.
Basically I am not using variables at all, only properties.
2/ Give your properties a non-default variable name, example:
#synthesize property = property_;
Reason 1: You will catch errors caused by forgetting "self." when assigning the property.
Reason 2: From my experiments, Leak Analyzer in Instruments has problems to detect leaking property with default name.
3/ Never use retain or release directly on properties (or only in very exceptional situations). In your dealloc just assign them a nil. Retain properties are meant to handle retain/release by themselves. You never know if a setter is not, for example, adding or removing observers. You should use the variable directly only inside its setter and getter.
Views
1/ Put every view definition into a xib, if you can (the exception is usually dynamic content and layer settings). It saves time (it's easier than writing code), it's easy to change and it keeps your code clean.
2/ Don't try to optimize views by decreasing the number of views. Don't create UIImageView in your code instead of xib just because you want to add subviews into it. Use UIImageView as background instead. The view framework can handle hundreds of views without problems.
3/ IBOutlets don't have to be always retained (or strong). Note that most of your IBOutlets are part of your view hierarchy and thus implicitly retained.
4/ Release all IBOutlets in viewDidUnload
5/ Call viewDidUnload from your dealloc method. It is not implicitly called.
Memory
1/ Autorelease objects when you create them. Many bugs are caused by moving your release call into one if-else branch or after a return statement. Release instead of autorelease should be used only in exceptional situations - e.g. when you are waiting for a runloop and you don't want your object to be autoreleased too early.
2/ Even if you are using Authomatic Reference Counting, you have to understand perfectly how retain-release methods work. Using retain-release manually is not more complicated than ARC, in both cases you have to thing about leaks and retain-cycles.
Consider using retain-release manually on big projects or complicated object hierarchies.
Comments
1/ Make your code autodocumented.
Every variable name and method name should tell what it is doing. If code is written correctly (you need a lot of practice in this), you won't need any code comments (not the same as documentation comments). Algorithms can be complicated but the code should be always simple.
2/ Sometimes, you'll need a comment. Usually to describe a non apparent code behavior or hack. If you feel you have to write a comment, first try to rewrite the code to be simpler and without the need of comments.
Indentation
1/ Don't increase indentation too much.
Most of your method code should be indented on the method level. Nested blocks (if, for etc.) decrease readability. If you have three nested blocks, you should try to put the inner blocks into a separate method. Four or more nested blocks should be never used.
If most of your method code is inside of an if, negate the if condition, example:
if (self) {
//... long initialization code ...
}
return self;
if (!self) {
return nil;
}
//... long initialization code ...
return self;
Understand C code, mainly C structs
Note that Obj-C is only a light OOP layer over C language. You should understand how basic code structures in C work (enums, structs, arrays, pointers etc).
Example:
view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, view.frame.size.height + 20);
is the same as:
CGRect frame = view.frame;
frame.size.height += 20;
view.frame = frame;
And many more
Mantain your own coding standards document and update it often. Try to learn from your bugs. Understand why a bug was created and try to avoid it using coding standards.
Our coding standards have currently about 20 pages, a mix of Java Coding Standards, Google Obj-C/C++ Standards and our own addings. Document your code, use standard standard indentation, white spaces and blank lines on the right places etc.
Be more functional.
Objective-C is object-oriented language, but Cocoa framework functional-style aware, and is designed functional style in many cases.
There is separation of mutability. Use immutable classes as primary, and mutable object as secondary. For instance, use NSArray primarily, and use NSMutableArray only when you need.
There is pure functions. Not so many, buy many of framework APIs are designed like pure function. Look at functions such as CGRectMake() or CGAffineTransformMake(). Obviously pointer form looks more efficient. However indirect argument with pointers can't offer side-effect-free. Design structures purely as much as possible.
Separate even state objects. Use -copy instead of -retain when passing a value to other object. Because shared state can influence mutation to value in other object silently. So can't be side-effect-free. If you have a value from external from object, copy it. So it's also important designing shared state as minimal as possible.
However don't be afraid of using impure functions too.
There is lazy evaluation. See something like -[UIViewController view] property. The view won't be created when the object is created. It'll be created when caller reading view property at first time. UIImage will not be loaded until it actually being drawn. There are many implementation like this design. This kind of designs are very helpful for resource management, but if you don't know the concept of lazy evaluation, it's not easy to understand behavior of them.
There is closure. Use C-blocks as much as possible. This will simplify your life greatly. But read once more about block-memory-management before using it.
There is semi-auto GC. NSAutoreleasePool. Use -autorelease primary. Use manual -retain/-release secondary when you really need. (ex: memory optimization, explicit resource deletion)