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
$103.30
Apple Inc.
+0.80
MSFT
$45.09
Microsoft Corpora
-0.34
GOOG
$577.33
Google Inc.
+5.73

MacTech Search:
Community Search:

Software Updates via MacUpdate

TextSoap 7.4.0 - Flexible text editing u...
TextSoap is for people who work with text. TextSoap effortlessly cleans up text from endlessly different formats. Wash away unwanted characters, spaces, tabs. Fix paragraphs with hard returns at the... Read more
NetShade 6.0.2 - Browse privately using...
NetShade is an Internet security tool that conceals your IP address on the web. NetShade routes your Web connection through either a public anonymous proxy server, or one of NetShade's own dedicated... Read more
Mac DVDRipper Pro 5.0 - Copy, backup, an...
Mac DVDRipper Pro is the DVD backup solution that lets you protect your DVDs from scratches, save your batteries by reading your movies from your hard disk, manage your collection with just a few... Read more
pwSafe 3.1 - Secure password management...
pwSafe provides simple and secure password management across devices and computers. pwSafe uses iCloud to keep your password databases backed-up and synced between Macs and iOS devices. It is... Read more
StatsBar 1.8 - Monitor system processes...
StatsBar gives you a comprehensive and detailed analysis of the following areas of your Mac: CPU usage Memory usage Disk usage Network and bandwidth usage Battery power and health (MacBooks only)... Read more
Path Finder 6.5.5 - Powerful, award-winn...
Path Finder is a file browser that combines the familiar Finder interface with the powerful utilities and innovative features. Just a small selection of the Path Finder 6 feature set: Dual pane... Read more
QuarkXPress 10.2.1 - Desktop publishing...
With QuarkXPress, you can communicate in all the ways you need to -- and always look professional -- in print and digital media, all in a single tool. Features include: Easy to Use -- QuarkXPress is... Read more
Skype 6.19.0.450 - Voice-over-internet p...
Skype allows you to talk to friends, family and co-workers across the Internet without the inconvenience of long distance telephone charges. Using peer-to-peer data transmission technology, Skype... Read more
VueScan 9.4.41 - 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
Cloud 3.0.0 - File sharing from your men...
Cloud is simple file sharing for the Mac. Drag a file from your Mac to the CloudApp icon in the menubar and we take care of the rest. A link to the file will automatically be copied to your clipboard... Read more

Latest Forum Discussions

See All

Modern Combat 5 Gets a Major Multiplayer...
Modern Combat 5 Gets a Major Multiplayer Update Posted by Jessica Fisher on September 2nd, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Alien Creeps TD Review
Alien Creeps TD Review By Jennifer Allen on September 2nd, 2014 Our Rating: :: EXPENSIVE DEFENSESUniversal App - Designed for iPhone and iPad Alien Creeps TD would be a fun if unremarkable Tower Defense game, but its heavy focus on... | Read more »
The Journey Down: Chapter Two Review
The Journey Down: Chapter Two Review By Jennifer Allen on September 2nd, 2014 Our Rating: :: DARK YET ENTICINGUniversal App - Designed for iPhone and iPad It’s a little dark, in every sense of the word, but The Journey Down:... | Read more »
Function Space, a Social Network App for...
Function Space, a Social Network App for Science, Launches on iOS Posted by Ellis Spice on September 2nd, 2014 [ permalink ] | Read more »
Stupidfast – How Taylor Martinez Switche...
How do you make an Endless Running game more than just another Endless Running game? By adding real life prizes to it, of course! That’s the thinking behind StupidFast: a game designed for football enthusiasts, and the brainchild of former college... | Read more »
Little Raiders: Robin’s Revenge Review
Little Raiders: Robin’s Revenge Review By Jennifer Allen on September 2nd, 2014 Our Rating: :: CASUAL RAIDINGUniversal App - Designed for iPhone and iPad Combining simple combat with village building is a potent combination for... | Read more »
Treasure Tombs: Ra Deal Coming from Bulk...
Treasure Tombs: Ra Deal Coming from Bulkypix and Dark Tonic This Fall Posted by Jessica Fisher on September 2nd, 2014 [ permalink ] Dark Tonic and | Read more »
Pirate Bash Review
Pirate Bash Review By Nadia Oxford on September 2nd, 2014 Our Rating: :: BAD PIRATES, GOOD TIMESUniversal App - Designed for iPhone and iPad Pirate Bash’s turn-based battles add an intriguing twist to a typical physics game.   | Read more »
Tiny Tower Vegas Review
Tiny Tower Vegas Review By Jennifer Allen on September 2nd, 2014 Our Rating: :: STEADY DEVELOPMENTUniversal App - Designed for iPhone and iPad Build a huge tower again but Vegas-style in Tiny Tower Vegas.   | Read more »
The Manhattan Project Review
The Manhattan Project Review By Andrew Fisher on September 2nd, 2014 Our Rating: :: ROCKET SCIENCEUniversal App - Designed for iPhone and iPad The Manhattan Project offers a great Euro-style gameplay experience, but it is totally... | Read more »

Price Scanner via MacPrices.net

Apple refurbished iPads available for up to $...
Apple is offering Certified Refurbished iPad Airs for up to $140 off MSRP. Apple’s one-year warranty is included with each model, and shipping is free. Stock tends to come and go with some of these... Read more
Are We Now In The Post-Post-PC Era?
A longtime and thoroughgoing laptop aficionado, I was more than a little dismayed by Steve Jobs’s declaration back in 2010 when he sprang the iPad on an unsuspecting world. that we’d entered a “post-... Read more
PC Outlook Improves, But 2014 Shipments Still...
According to the International Data Corporation (IDC) Worldwide Quarterly PC Tracker, worldwide PC shipments are expected to fall by -3.7 percent in 2014. To hat’s actually an improvement from the... Read more
IDC Lowers Tablet Sales Projections for 2014...
Following a second consecutive quarter of softer than expected demand, International Data Corporation (IDC) has lowered its worldwide tablet plus 2-in-1 forecast for 2014 to 233.1 million units. The... Read more
Apple now offering refurbished 21-inch 1.4GHz...
The Apple Store is now offering Apple Certified Refurbished 21″ 1.4GHz iMacs for $929 including free shipping plus Apple’s standard one-year warranty. Their price is $170 off the cost of new models,... Read more
Save $50 on the 2.5GHz Mac mini, on sale for...
B&H Photo has the 2.5GHz Mac mini on sale for $549.99 including free shipping. That’s $50 off MSRP, and B&H will also include a free copy of Parallels Desktop software. NY sales tax only. Read more
Save up to $300 on an iMac with Apple refurbi...
The Apple Store has Apple Certified Refurbished iMacs available for up to $300 off the cost of new models. Apple’s one-year warranty is standard, and shipping is free. These are the best prices on... Read more
The Rise of Phablets
Carlisle & Gallagher Consulting Group, a businesses and technology consulting firm focused solely on the financial services industry, has released an infographic depicting the convergence of... Read more
Bad Driver Database App Allows Good Drivers t...
Bad Driver Database 1.4 by Facile Group is a new iOS and Android app that lets users instantly input and see how many times a careless, reckless or just plain stupid driver has been added to the... Read more
Eddy – Cloud Music Player for iPhone/iPad Fre...
Ukraine based CapableBits announces the release of Eddy, its tiny, but smart and powerful cloud music player for iPhone and iPad that allows users to stream or download music directly from cloud... Read more

Jobs Board

*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
Senior Event Manager, *Apple* Retail Market...
…This senior level position is responsible for leading and imagining the Apple Retail Team's global event strategy. Delivering an overarching brand story; in-store, Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.