TweetFollow Us on Twitter

The Road to Code: There's a Hole in your Bucket

Volume Number: 24 (2008)
Issue Number: 02
Column Tag: The Road to Code

The Road to Code: There's a Hole in your Bucket

Objective-C Memory Management

by Dave Dribin

Introduction

Welcome back to The Road to Code. In previous articles, we've talked about dynamic memory management and how to use malloc and free in C. We've also covered using alloc and release in Objective-C. Unfortunately, I left out a lot of the details of Objective-C memory management, mentioning only that alloc and release worked the same as malloc and free. This was a white lie, and the truth is that they are a bit more complicated. While the complications are a bit of a hurdle to overcome, they paradoxically make it easier on the programmer, in the long run.

Object Ownership

Let's assume, for a bit more, that the alloc method allocates memory for an object and the release method immediately deallocates it. For the simple programs we've written so far, it's easy to remember when to call release. Take this simple example where we use our Rectangle class in Listing 1:

Listing 1: Using the Rectangle class

#import <Foundation/Foundation.h>
#import "Rectangle.h"
int main (int argc, const char * argv[])
{
   NSAutoreleasePool * pool =
      [[NSAutoreleasePool alloc] init];
   Rectangle * rectangle;
   
   rectangle = [[Rectangle alloc] initWithLeftX   : 5
                                 bottomY   : 5
                                  rightX   : 15
                                   topY   : 10];
   printf("Area is %.2f\n", [rectangle area]);
   printf("Perimeter is: %.2f\n", [rectangle perimeter]);
   
   [rectangle release];
   
   [pool release];
   return 0;
}

We've allocated a Rectangle instance at the beginning of main so we just need to remember to call release to deallocate it at the end of main before it returns. However, as programs get larger and start running for longer periods of time, the task of how and when to release memory becomes daunting. You may have two objects that both are using the same Rectangle instance, for example, by showing the rectangle in two different windows. This would give you an object graph that looks like Figure 1:


Figure 1: Simple object graph

Both object_1 and object_2 have references to the same instance of a Rectangle class, rectangle. Which object, object_1 or object_2, has the responsibility to release rectangle when they get released and deallocated? If neither of them call release, then you end up in a situation like Figure 2.


Figure 2: Leaking an object

rectangle now exists with no other object pointing to it, so it is lost to the system and taking up memory. This is called a memory leak, and memory leaks are serious bugs. If you have memory leaks in a long-running program, such as a GUI application, then the program will be using more and more memory as it runs. Pretty soon, it could be using most of the memory in the system. This leads to a bad user experience, as memory is being used for dead and no longer used objects, instead of useful stuff.

Okay, so clearly not releasing used objects is a bad thing. But on the other end of the spectrum of memory problems, you can also over-release an object. Say that both object_1 and object_2 decide they should be responsible for releasing rectangle. Now, if object_2 is released and deallocated, it releases and deallocates rectangle along with it. You end up with a situation like Figure 3:


Figure 3: Dangling pointer

Oops! Now object_1 is pointing to memory that was previously used by rectangle, but has now been deallocated and returned to the system. This situation is called a dangling pointer. Dangling pointer bugs manifest themselves in strange ways and can be hard to track down. Since memory returned to the system may not be recycled and reallocated for other purposes right away, object_1 might be able to use rectangle after its death. It will continue to work...for a bit. But then, at some point, your program may start acting really strange or outright crash. Because the symptoms of the bug are delayed - the bug actually occurred where rectangle was prematurely released - these kinds of bugs are hard to squash.

In order to avoid both memory leaks and dangling pointers, we need to make sure that objects are only deallocated after all objects pointing to them are finished. One way to do this is with the concept of ownership. We can setup a system where every object is owned by one and only one other object, and only the owner is responsible for releasing the object. Also, object ownership can be transferred from one object to another. For example, take Figure 1 again. If object_1 owns rectangle, then when object_2 is deallocated it does not take rectangle with it. If, on the other hand, object_2 is the owner, it may pass ownership to object_1. Thus, when object_1 is deallocated, it will take rectangle with it.

As you can begin to see, even from this simple example, the concept of ownership can be hard to manage. How do you notify object_1 that it now owns rectangle? What if a third object, object_3, is created before object_1 is deallocated and it also uses rectangle? object_1 needs to somehow know about this and transfer ownership, instead of releasing rectangle upon deallocation. There are ways to manage the single ownership problem, but they can be difficult to get right. Thankfully, Objective-C gives us a better way.

Reference Counting

Instead of having single ownership, with one and only one owner, Objective-C embraces shared ownership. Thus object_1 and object_2 both own rectangle. rectangle does not need to know who its owners are; it just needs to keep track of the number of owners. When the number of owners drops to zero, then it's deallocated. The number of owners is called a reference count since it counts how many other objects reference (point to) it. I've modified the original object graph in Figure 4 to also show the reference count of rectangle. Thus when object_2 releases rectangle, it decrements the reference count from two to one. Since the reference count is still greater than zero, it is not deallocated and is available for object_1. When object_1 also releases it the reference count will be zero, and rectangle will finally be deallocated.


Figure 4: Reference count

This also fixes our situation where object_3, which also uses rectangle, is created before object_1 releases rectangle. The reference count for rectangle goes back up to two. Thus if object_1 releases rectangle, the reference count will be one and it will live until object_3 also releases it.

Okay, so that's the theory. How do you actually use reference counting in Objective-C? You've already been partially using it. All objects that inherit from NSObject (which are all objects) already contain a reference count. The release method does not deallocate the memory straight away, like the free function does. Instead, it subtracts one from the reference count, and only if the new reference count is zero will it deallocate the memory.

So release decrements (reduces) the reference count, but how do you increase the reference count? When an object is created with the alloc it is given a reference count of one. Thus, if we look at our program in Listing 1, you'll see why releasing rectangle deallocates it. If you need to increase the reference count there is a method called retain that does just this. Because Objective-C uses the retain method, the reference count in Objective-C is also called the retain count. Same thing, different name. In fact, you can even get the retain count of an object with the retainCount method. Listing 2 demonstrates the retain count.

Listing 2: Retain counts

#import <Foundation/Foundation.h>
#import "Rectangle.h"
int main (int argc, const char * argv[])
{
   NSAutoreleasePool * pool =
      [[NSAutoreleasePool alloc] init];
   
   Rectangle * rectangle;
   
   rectangle = [[Rectangle alloc] initWithLeftX   : 5
                               bottomY   : 5
                                rightX   : 15
                                 topY   : 10];
   
   printf("Retain count: %d\n", [rectangle retainCount]);
   
   [rectangle retain];
   printf("Retain count: %d\n", [rectangle retainCount]);
   
   [rectangle release];
   printf("Retain count: %d\n", [rectangle retainCount]);
   [rectangle release];
   [pool release];
   return 0;
}

When run, this program will output:

Retain count: 1
Retain count: 2
Retain count: 1

As an aside, while using retainCount can be interesting to see how reference counting works in Objective-C, you should only use it for debugging purposes. There are cases when the retain count is not telling the whole story, especially when autorelease pools (discussed below) come into play.

While Objective-C has built in support for shared ownership via reference counting, it is still an explicit step that all Objective-C programmers need to use properly. If you take away only one thing from this article, let it be this rule: every alloc and retain must be balanced by a corresponding release. Thus, in the example above, because we allocate the object and retain it once more, we need to release it twice.

Since it is a manual step, you can still get memory leaks if you forget to release an object after retaining it, and you can get dangling pointers if you release an object without first retaining it. Because the programmer must explicitly manage the reference count with retain and release, this is called manual reference counting. Other languages, such as Python, have automatic reference counting, where the language takes care of incrementing and decrementing the reference count for you. Alas, we Objective-C programmers have to do it manually, but at least we have it better than straight C programmers.

Retaining and Releasing in Accessors

Listing 2 is not a realistic usage of retaining and releasing objects, though, as you rarely retain an object for no reason. The reason you would retain an object is to take shared ownership in it. Let's create a new class called RectanglePrinter that holds onto a Rectangle instance and prints information about it. Listing 3 shows the interface for this class.

Listing 3: RectanglePrinter.h

#import <Foundation/Foundation.h>
#import "Rectangle.h"
@interface RectanglePrinter : NSObject
{
   Rectangle * _rectangle;
}
- (Rectangle *) rectangle;
- (void) setRectangle: (Rectangle *) rectangle;
- (void) printArea;
@end

To use this new class, let's use the test program in Listing 4.

Listing 4: RectanglePrinter test application

#import <Foundation/Foundation.h>
#import "Rectangle.h"
#import "RectanglePrinter.h"
int main(int argc, const char * argv[])
{
   NSAutoreleasePool * pool =
      [[NSAutoreleasePool alloc] init];
   
   Rectangle * rectangle;
   
   rectangle = [[Rectangle alloc] initWithLeftX   : 5
                               bottomY   : 5
                                rightX   : 15
                                 topY   : 10];
   
   RectanglePrinter * printer =
      [[RectanglePrinter alloc] init];
   
   [printer setRectangle: rectangle];
   [rectangle release];
   rectangle = nil;
   
   [printer printArea];
   [printer release];
   
   [pool release];
   return 0;
}

Let me point out a couple of things here. First, after calling setRectangle:, we release our instance, since we are no longer in need of it. This does not deallocate rectangle, though, since setRectangle: should take additional ownership and increase the retain count. We also set rectangle to nil after its release. nil is a special value that can be assigned to any object pointer, and it means the pointer points to no object at all. It's good practice to set your object pointers to nil after releasing them. While it won't matter if you've written your program without any bugs, it can help while debugging if you've made a mistake dealing with the retain counts.

Before diving into the implementation, there's a little more terminology to cover. Remember that instance variables are private and should only be used internally to the class. If you want to make an instance variable, like _rectangle, available outside your class, you should use methods to keep encapsulation intact. The pair of methods, rectangle and setRectangle:, expose the _rectangle instance variable publicly and are called accessor methods. The rectangle method is called a getter and setRecangle: is called a setter. The getter and setter pair of accessor methods is an important design pattern that we will be seeing more of in advanced Objective-C topics.

The implementation of RectanglePrinter shows how to use retain to take ownership for accessor methods, and is shown in Listing 5.

Listing 5: RectanglePrinter.m, first version

#import "RectanglePrinter.h"
@implementation RectanglePrinter
- (Rectangle *) rectangle
{
   return _rectangle;
}
- (void) setRectangle: (Rectangle *) rectangle
{
   if (rectangle == _rectangle)
      return;
   
   [_rectangle release];
   _rectangle = [rectangle retain];
}
- (void) printArea
{
   printf("Rectangle area: %.2f\n", [_rectangle area]);
}
@end

The rectangle method is simple: it just returns the _rectangle instance variable. This is how most getter methods should be implemented. The setRectangle: method is a bit more complicated, though. Notice that retain also returns the object, so you can perform the retain and assignment in a single step. You might be tempted to implement it as follows, by first releasing the current rectangle, and the retaining the new one:

- (void) setRectangle: (Rectangle *) rectangle
{
   [_rectangle release];
   _rectangle = [rectangle retain];
}

However, don't do it! This causes issues if the new rectangle is the same instance as the old one and the current retain count is already one. If this happens to be the case, releasing the object would cause it be deallocated before the retain happened, and you'd end up retaining a dead object. While this does not happen very often, it can happen, so it's wise to follow the pattern in Listing 5 and check for identical instances in all your setters. There are other correct ways of writing accessor methods, and indeed the "correct" way is still a topic of debate, but the pattern covered here covers the vast majority of situations.

Destructors

There's still one more bug lurking in this code. If calling release on a RectanglePrinter causes it to be deallocated, the Rectangle instance pointed to by the _rectangle instance variable is leaked. This is because we did a retain in setRectangle: but never paired this up with a release. What we really need is a way to be notified that our object is about to be deallocated so we can clean up any objects we're using. Thankfully, Objective-C calls a method named dealloc just before deallocating your object to give you a chance to do just that. Here's how we would implement it:

- (void) dealloc
{
   [_rectangle release];
   [super dealloc];
}

Because dealloc is called when the object is just about to be reclaimed for system usage, it is called a destructor. This terminology also pairs up with the init method being called a constructor, as we talked about in the previous article.

You may be wondering about the case where _rectangle is nil. Calling methods on objects set to nil does nothing at all. Thus, it's safe to call release on nil. This may seem odd if you're coming from a C++ or Java background where calling methods on an object set to null (their equivalent of nil) will cause your program to crash. This is one of the oddball Objective-C moments. Some people love it and some people hate it. Whatever your take, you may as well just live with it and embrace it, because it's not going to change.

You may also be wondering what _rectangle is set to if you never call setRectangle:. All instance variables are set to nil automatically by the default constructor (the init method of NSObject), so our code will work just fine. However, some people like to explicitly set objects to nil in a custom constructor. Listing 6 shows the complete implementation of RectanglePrinter, complete with constructor and destructor, accessor methods, and printArea.

Listing 6: RectanglePrinter.m, complete

#import "RectanglePrinter.h"
@implementation RectanglePrinter
- (id) init
{
   self = [super init];
   if (self == nil)
      return nil;
   
   _rectangle = nil;
   
   return self;
}
- (void) dealloc
{
   [_rectangle release];
   [super dealloc];
}
- (Rectangle *) rectangle
{
   return _rectangle;
}
- (void) setRectangle: (Rectangle *) rectangle
{
   if (rectangle == _rectangle)
      return;
   
   [_rectangle release];
   _rectangle = [rectangle retain];
}
- (void) printArea
{
   printf("Rectangle area: %.2f\n", [_rectangle area]);
}
@end

Retain Cycles

While reference counting is an effective technique to help deal with memory management, it can break down in one case. If two objects both reference each other, you end up with a situation where the retain count will never reach zero. This is because their retain counts will be stuck at one. Figure 5 shows how this can happen, where parent and child retain each other (see below):


Figure 5: Retain cycles cause memory leaks

When object_1 is deallocated, it releases its reference to parent. However, since child also references parent, the retain count can never reach zero, and we're stuck leaking an instance of both parent and child.

The trick to this is to have child contain a reference to parent, but not retain it. This is called a weak reference. By having child not retain parent, the reference count for parent is only one, as in Figure 6.


Figure 6: Using weak reference to break retain cycles

The key for this to actually work in practice is to explain, in a comment, that it is a weak reference, so that other developers will understand why a retain and release are not done on this reference. An example is shown in Listing 7.

Listing 7: Weak references

#import <Cocoa/Cocoa.h>
@class Parent;
@interface Child : NSObject
{
   // This is a weak reference.  Do not retain.
   Parent * _parent;
}
- (id) initWithParent: (Parent *) parent;
@end

Delayed Release

Sometimes getter methods do not simply return an instance variable. They may need to create a new object on the fly. Take this method that returns a Rectangle object that is a 4x4 square:

- (Rectangle *) square4x4
{
   Rectangle * square =
      [[Rectangle alloc] initWithLeftX   : 0
                         bottomY   : 0
                          rightX   : 4
                           topY   : 4];
   return square;
}

This looks very similar to any other getter method, except the caller is supposed to release the object when it is done with it. But how is the caller supposed to know this? We could document this in the code comments, but there's a high probably that people will miss this. Or we could rename the method such that it indicates object creation, such as newSquare4x4. But this limits our implementation choices in the future. What if we decided to use an instance variable to keep returning the same object for increased performance? We'd have to change our name back to square4x4 so as not to confuse the caller. The solution to this is to use the autorelease method supplied by NSObject. Thus the correct implementation of square4x4 is:

- (Rectangle *) square4x4
{
   Rectangle * square =
      [[Rectangle alloc] initWithLeftX   : 0
                         bottomY   : 0
                          rightX   : 4
                           topY   : 4];
   return [square autorelease];
}

The autorelease method is similar to release in that it will decrease the reference count, but at some point in the future instead of immediately. Thus, if the caller does not keep a reference to the return value, the object will be properly released. However, if the caller does retain the return value, then the retain count will still only be one. It will temporarily be two, but the delayed release causes the retain count to go back to one.

How does this autorelease thing actually work? The secret is autorelease pools, implemented by the NSAutoreleasePool class. Yup, those are the objects we see in our main class. When the autorelease method is called, the object gets added to the most current autorelease pool. When the pool is released, it also releases all objects in the pool. Thus, in our simple programs, the delayed release occurs just before the main application exits.

Because autorelease may by used internally by parts of the standard Foundation library, including NSObject, every application needs at least one autorelease pool active at all times. That's why the first thing our Objective-C programs do is set up an autorelease pool. We want to ensure an autorelease pool is in place before we start using any other objects. It's also why the last thing our program does is release the autorelease pool.

In GUI applications, you don't need to setup any autorelease pools. The standard Cocoa libraries take care of all this for you. For our command line applications, though, we need to take care of the autorelease pools, ourselves.

Autorelease and Class Methods

The methods we have been using so far only work on an instance of that class, thus they are called instance methods. There is another kind of method that does not require an instance of a class called class methods. These are declared using a plus ('+') instead of a minus sign ('-') as the first character:

+ (void) myClassMethod;

The definition also uses the plus sign, but is otherwise identical to an instance method:

+ (void) myClassMethod
{
   printf("In myClassMethod\n");
}

Since you don't use an object instance to call these methods on, you use the class name when calling class methods. For example, if the above class method were part of the Rectangle class, it would be called like this:

   [Rectangle myClassMethod];

Class methods, because they do not require an instance, are very similar to a function call. The benefit is that the are tied to a particular class. Whether you create a function or a class method really depends on the situation. One particular case where class methods are useful is for creating autoreleased instances in a single step.

Because autoreleased objects make memory management easier when you use short-lived objects, they tend to get used a lot. However, creating them can be a bit a pain. For example, to create an autoreleased instance of our Rectangle class, we need to call three methods:

   rectangle = [[Rectangle alloc] initWithLeftX   : 5
                               bottomY   : 5
                                rightX   : 15
                                 topY   : 10];
   [rectangle autorelease];

To make this common task easier, it is useful to create a class method that does this all in one step:

+ (Rectangle *) rectangleWithLeftX   : (float) leftX
                     bottomY   : (float) bottomY
                     rightX   : (float) rightX
                       topY   : (float) topY;
{
   Rectangle * rectangle =
      [[self alloc] initWithLeftX: leftX
                     bottomY   : bottomY
                      rightX   : rightX
                        topY   : topY];
   return [rectangle autorelease];
}

This could then be used like:

   rectangle = [Rectangle rectangleWithLeftX   : 5
                             bottomY   : 5
                              rightX   : 15
                               topY   : 10];

You will see this "class method for autorelease" pattern in many of the standard Foundation and Cocoa libraries. By convention, the name of the class method starts with the name the class. For example, there's an NSNumber class in Foundation that holds standard C numbers, such as int and float. To create an instance of this, you would use:

   NSNumber * number = [[NSNumber alloc] initWithInt: 42];

To create an autoreleased instance, you would use the numberWithInt: class method:

   NSNumber * number = [NSNumber numberWithInt: 42];

I mention this because the pattern is so heavily used that the documentation often fails to mention the fact that the return object is autoreleased. So just keep this in mind if you see code like this and you are wondering why release is not being called on these objects.

Garbage Collection

While reference counting is a big step up from the malloc and free usage of standard C, it can still be problematic, especially since Objective-C uses manual reference counting. It is easy for a programmer to forget to call release and cause memory leaks. Properly using retain and release is yet another thing programmers have to think about, instead of how to implement new features. Thankfully, there exists another technique for dealing with dynamic memory.

Objective-C 2.0, which was released along with Mac OS X 10.5, Leopard, includes a technique called garbage collection. In short, garbage collection, or GC, works by having the system keep track of all object allocations and assignments. Then, the system will periodically scan all allocated objects, looking for objects that have no references to them. If an object has no references, it is considered garbage and deallocated automatically.

In plain English, this means that you no longer have to use retain, release, or autorelease ever again. Memory management is completely automatic, and the burden of memory leaks, dangling pointers, and retain cycles has been lifted from the backs of Objective-C programmers. This is really huge. Here is our RectanglePrinter test application from Listing 4 written with garbage collection:

Listing 8: Garbage collection example

#import <Foundation/Foundation.h>
#import "Rectangle.h"
#import "RectanglePrinter.h"
int main (int argc, const char * argv[])
{
   Rectangle * rectangle;
   
   rectangle = [[Rectangle alloc] initWithLeftX   : 5
                               bottomY   : 5
                                rightX   : 15
                                 topY   : 10];
   
   RectanglePrinter * printer =
      [[RectanglePrinter alloc] init];
   
   [printer setRectangle: rectangle];
   [printer printArea];
   
   return 0;
}

As you can see, we've removed the autorelease pool and all calls to release. Of course, there are still a few finer points you have to worry about, but in general, Apple has delivered on this. Another major difference you will notice is that the dealloc method is no longer called, thus you should not implement it. This is because you no longer need to release your references to other objects. While the lack of dealloc is mainly transparent, there are some cases when you will have to restructure your code a bit. For classes that just release their instance variables, like our RectanglePrinter, it means we can just delete our dealloc method and things will work. We will go over the finer points of GC as we come across them in future articles.

The only major downside at this point is that GC is only supported on Leopard. If you are writing code that needs to execute on prior versions of Mac OS X, you won't be able to use GC, just yet.

Conclusion

Objective-C memory management is a bit different from most other languages out there. Until recently, it used reference counting which is more flexible than malloc and free, but it's not completely automatic. There are a few rules that you must follow in order to properly retain and release objects. This means you must constantly think about and follow the rules in your programs. The advent of Leopard brings us garbage collection and promises to simplify memory management even more. In either case, memory management is a cornerstone of Objective-C programming. With this topic under your belt, we can start exploring areas of the Foundation and Cocoa libraries.


Dave Dribin has been writing professional software for over eleven years. After five years programming embedded C in the telecom industry and a brief stint riding the Internet bubble, he decided to venture out on his own. Since 2001, he has been providing independent consulting services, and in 2006, he founded Bit Maki, Inc. Find out more at http://www.bitmaki.com/ and http://www.dribin.org/dave/.

 
AAPL
$467.36
Apple Inc.
+0.00
MSFT
$32.87
Microsoft Corpora
+0.00
GOOG
$885.51
Google Inc.
+0.00

MacTech Search:
Community Search:

Software Updates via MacUpdate

VueScan 9.2.23 - Scanner software with a...
VueScan is a scanning program that works with most high-quality flatbed and film scanners to produce scans that have excellent color fidelity and color balance. VueScan is easy to use, and has... Read more
Acorn 4.1 - Bitmap image editor. (Demo)
Acorn is a new image editor built with one goal in mind - simplicity. Fast, easy, and fluid, Acorn provides the options you'll need without any overhead. Acorn feels right, and won't drain your bank... Read more
Mellel 3.2.3 - Powerful word processor w...
Mellel is the leading word processor for OS X, and has been widely considered the industry standard since its inception. Mellel focuses on writers and scholars for technical writing and multilingual... Read more
Iridient Developer 2.2 - Powerful image...
Iridient Developer (was RAW Developer) is a powerful image conversion application designed specifically for OS X. Iridient Developer gives advanced photographers total control over every aspect of... Read more
Delicious Library 3.1.2 - Import, browse...
Delicious Library allows you to import, browse, and share all your books, movies, music, and video games with Delicious Library. Run your very own library from your home or office using our... Read more
Epson Printer Drivers for OS X 2.15 - Fo...
Epson Printer Drivers includes the latest printing and scanning software for OS X 10.6, 10.7, and 10.8. Click here for a list of supported Epson printers and scanners.OS X 10.6 or laterDownload Now Read more
Freeway Pro 6.1.0 - Drag-and-drop Web de...
Freeway Pro lets you build websites with speed and precision... without writing a line of code! With it's user-oriented drag-and-drop interface, Freeway Pro helps you piece together the website of... Read more
Transmission 2.82 - Popular BitTorrent c...
Transmission is a fast, easy and free multi-platform BitTorrent client. Transmission sets initial preferences so things "Just Work", while advanced features like watch directories, bad peer blocking... Read more
Google Earth Web Plug-in 7.1.1.1888 - Em...
Google Earth Plug-in and its JavaScript API let you embed Google Earth, a true 3D digital globe, into your Web pages. Using the API you can draw markers and lines, drape images over the terrain, add... Read more
Google Earth 7.1.1.1888 - View and contr...
Google Earth gives you a wealth of imagery and geographic information. Explore destinations like Maui and Paris, or browse content from Wikipedia, National Geographic, and more. Google Earth... Read more

Strategy & Tactics: World War II Upd...
Strategy & Tactics: World War II Update Adds Two New Scenarios Posted by Andrew Stevens on August 12th, 2013 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Expenses Planner Review
Expenses Planner Review By Angela LaFollette on August 12th, 2013 Our Rating: :: PLAIN AND SIMPLEUniversal App - Designed for iPhone and iPad Expenses Planner keeps track of future bills through due date reminders, and it also... | Read more »
Kinesis: Strategy in Motion Brings An Ad...
Kinesis: Strategy in Motion Brings An Adaptation Of The Classic Strategic Board Game To iOS Posted by Andrew Stevens on August 12th, 2013 [ | Read more »
Z-Man Games Creates New Studio, Will Bri...
Z-Man Games Creates New Studio, Will Bring A Digital Version of Pandemic! | Read more »
Minutely Review
Minutely Review By Jennifer Allen on August 12th, 2013 Our Rating: :: CROWDSOURCING WEATHERiPhone App - Designed for the iPhone, compatible with the iPad Work together to track proper weather conditions no matter what area of the... | Read more »
10tons Discuss Publishing Fantasy Hack n...
Recently announced, Trouserheart looks like quite the quirky, DeathSpank-style fantasy action game. Notably, it’s a game that is being published by established Finnish games studio, 10tons and developed by similarly established and Finnish firm,... | Read more »
Boat Watch Lets You Track Ships From Por...
Boat Watch Lets You Track Ships From Port To Port Posted by Andrew Stevens on August 12th, 2013 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Expenses Review
Expenses Review By Ruairi O'Gallchoir on August 12th, 2013 Our Rating: :: STUNNINGiPhone App - Designed for the iPhone, compatible with the iPad Although focussing primarily on expenses, Expenses still manages to make tracking... | Read more »
teggle is Gameplay Made Simple, has Play...
teggle is Gameplay Made Simple, has Players Swiping for High Scores Posted by Andrew Stevens on August 12th, 2013 [ permalink ] | Read more »
How To: Manage iCloud Settings
iCloud, much like life, is a scary and often unknowable thing that doesn’t always work the way it should. But much like life, if you know the little things and tweaks, you can make it work much better for you. I think that’s how life works, anyway.... | Read more »

Price Scanner via MacPrices.net

13″ 2.5GHz MacBook Pro on sale for $150 off M...
B&H Photo has the 13″ 2.5GHz MacBook Pro on sale for $1049.95 including free shipping. Their price is $150 off MSRP plus NY sales tax only. B&H will include free copies of Parallels Desktop... Read more
iPod touch (refurbished) available for up to...
The Apple Store is now offering a full line of Apple Certified Refurbished 2012 iPod touches for up to $70 off MSRP. Apple’s one-year warranty is included with each model, and shipping is free: -... Read more
27″ Apple Display (refurbished) available for...
The Apple Store has Apple Certified Refurbished 27″ Thunderbolt Displays available for $799 including free shipping. That’s $200 off the cost of new models. Read more
Apple TV (refurbished) now available for only...
The Apple Store has Apple Certified Refurbished 2012 Apple TVs now available for $75 including free shipping. That’s $24 off the cost of new models. Apple’s one-year warranty is standard. Read more
AnandTech Reviews 2013 MacBook Air (11-inch)...
AnandTech is never the first out with Apple new product reviews, but I’m always interested in reading their detailed, in-depth analyses of Macs and iDevices. AnandTech’s Vivek Gowri bought and tried... Read more
iPad, Tab, Nexus, Surface, And Kindle Fire: W...
VentureBeat’s John Koetsier says: The iPad may have lost the tablet wars to an army of Android tabs, but its still first in peoples hearts. Second place, however, belongs to a somewhat unlikely... Read more
Should You Buy An iPad mini Or An iPad 4?
Macworld UK’s David Price addresses the conundrum of which iPAd to buy? Apple iPad 4, iPad 2, iPad mini? Or hold out for the iPad mini 2 or the iPad 5? Price notes that potential Apple iPad... Read more
iDraw 2.3 A More Economical Alternative To Ad...
If you’re a working graphics pro, you can probably justify paying the stiff monthly rental fee to use Adobe’s Creative Cloud, including the paradigm-setting vector drawing app. Adobe Illustrator. If... Read more
New Documentary By Director Werner Herzog Sho...
Injuring or even killing someone because you were texting while driving is a life-changing experience. There are countless stories of people who took their eyes off the road for a second and ended up... Read more
AppleCare Protection Plans on sale for up to...
B&H Photo has 3-Year AppleCare Warranties on sale for up to $105 off MSRP including free shipping plus NY sales tax only: - Mac Laptops 15″ and Above: $244 $105 off MSRP - Mac Laptops 13″ and... Read more

Jobs Board

Sales Representative - *Apple* Honda - Appl...
APPLE HONDA AUTOMOTIVE CAREER FAIR! NOW HIRING AUTO SALES REPS, AUTO SERVICE BDC REPS & AUTOMOTIVE BILLER! NO EXPERIENCE NEEDED! Apple Honda is offering YOU a Read more
*Apple* Developer Support Advisor - Portugue...
Changing the world is all in a day's work at Apple . If you love innovation, here's your chance to make a career of it. You'll work hard. But the job comes with more than Read more
RBB - *Apple* OS X Platform Engineer - Barc...
RBB - Apple OS X Platform Engineer Ref 63198 Country USA…protected by law. Main Function | The engineering of Apple OS X based solutions, in line with customer and Read more
RBB - Core Software Engineer - Mac Platform (...
RBB - Core Software Engineer - Mac Platform ( Apple OS X) Ref 63199 Country USA City Dallas Business Area Global Technology Contract Type Permanent Estimated publish end Read more
*Apple* Desktop Analyst - Infinity Consultin...
Job Title: Apple Desktop Analyst Location: Yonkers, NY Job Type: Contract to hire Ref No: 13-02843 Date: 2013-07-30 Find other jobs in Yonkers Desktop Analyst The Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.