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/.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Firefox 37.0 - Fast, safe Web browser. (...
Firefox offers a fast, safe Web browsing experience. Browse quickly, securely, and effortlessly. With its industry-leading features, Firefox is the choice of Web development professionals and casual... Read more
Arq 4.11 - Online backup to Google Drive...
Arq is super-easy online backup for the Mac. Back up to your own Google Drive storage (15GB free storage), your own Amazon Glacier ($.01/GB per month storage) or S3, or any SFTP server. Arq backs up... Read more
MacFamilyTree 7.3.4 - Create and explore...
MacFamilyTree gives genealogy a facelift: it's modern, interactive, incredibly fast, and easy to use. We're convinced that generations of chroniclers would have loved to trade in their genealogy... Read more
Yummy FTP 1.10.2 - FTP/SFTP/FTPS client...
Yummy FTP is an FTP + SFTP + FTPS file transfer client which focuses on speed, reliability and productivity. Whether you need to transfer a few files or a few thousand, schedule automatic backups, or... Read more
VueScan 9.5.08 - 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
Iridient Developer 3.0.1 - Powerful imag...
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
Air Video Server HD 2.1.0 - Stream video...
Air Video Server HD streams videos instantly from your computer on your iPhone, iPad, iPod touch or Apple TV. No need to worry about converting or transferring files. We took everything that was... Read more
Duplicate Annihilator 5.7.5 - Find and d...
Duplicate Annihilator takes on the time-consuming task of comparing the images in your iPhoto library using effective algorithms to make sure that no duplicate escapes. Duplicate Annihilator... Read more
BusyContacts 1.0.2 - Fast, efficient con...
BusyContacts is a contact manager for OS X that makes creating, finding, and managing contacts faster and more efficient. It brings to contact management the same power, flexibility, and sharing... Read more
Capture One Pro 8.2.0.82 - RAW workflow...
Capture One Pro 8 is a professional RAW converter offering you ultimate image quality with accurate colors and incredible detail from more than 300 high-end cameras -- straight out of the box. It... Read more

2K Announces WWE 2K, Mobile's First...
It seems like this month has been pretty big for wrestling. First Wrestlemania, then 2K has announces that they're releasing  WWE 2K for iOS. It's a simulation-based WWE game where you'll get to play with several WWE superstars such as John Cena, ... | Read more »
How the Apple Watch Could Change the Fac...
The Apple Watch is still a ways out, but my previous musings on the wearable’s various features got me thinking: what might it be like a year after launch? Two years? Five years? What if it becomes a symbiotic part of the iOS framework to the point... | Read more »
Pie In The Sky: A Pizza Odyssey (Games)
Pie In The Sky: A Pizza Odyssey 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: A game about delivering pizza. In space. | Read more »
Chosen Gives Hopeful Singers, Songwriter...
If YouTube videos and reality TV shows like The Voice have taught us one thing, it’s that there are a lot of people out there who are anxious to show the world their talents. And if they’ve taught us a second thing, it’s that there’s an almost... | Read more »
Android's Popular OfficeSuite Now A...
Once only available for Android devices, OfficeSuite has finally landed on the app store. The Mobile Systems app lets you view, edit, create, and share Word, Excel, and PowerPoint documents as well as convert them to/from PDFs. It's touted as being... | Read more »
Warhammer: Arcane Magic is Coming Soon,...
Turbo Tape Games has announced that they're joining forces with Games Workshop to bring the turn-based strategy board game, Warhammer: Arcane Magic, to life on the iOS. | Read more »
Fast & Furious: Legacy's Creati...
| Read more »
N-Fusion and 505's Ember is Totally...
| Read more »
These are All the Apple Watch Apps and G...
The Apple Watch is less than a month from hitting store shelves, and once you get your hands on it you're probably going to want some apps and games to install. Fear not! We've compiled a list of all the Apple Watch apps and games we've been able to... | Read more »
Appy to Have Known You - Lee Hamlet Look...
Being at 148Apps these past 2 years has been an awesome experience that has taught me a great deal, and working with such a great team has been a privilege. Thank you to Rob Rich, and to both Rob LeFebvre and Jeff Scott before him, for helping me... | Read more »

Price Scanner via MacPrices.net

Adobe Brings Powerful Layout-Design Capabilit...
Adobe today announced the availability of Adobe Comp CC, a free iPad app that enables rapid creation of layout concepts for mobile, Web and print projects. With Comp CC, designers can rough out and... Read more
Apple offering refurbished 27-inch 5K iMacs f...
The Apple Store is offering Apple Certified Refurbished 27″ 3.5GHz 5K iMacs for $2119 including free shipping. Their price is $380 off the price of new models, and it’s the lowest price available for... Read more
16GB iPad mini on sale for $199, save $50
Walmart has 16GB iPad minis (1st generation) available for $199.99 on their online store, including free shipping. Their price is $50 off MSRP. Online orders only. Read more
New 128GB MacBook Airs on sale for $50 off MS...
 B&H Photo has 128GB 11″ and 13″ 2015 MacBook Airs on sale today for $50 off MSRP including free shipping plus NY sales tax only: - 11″ 1.6GHz/128GB MacBook Air (Model #MJVM2LL/A): $849 $50 off... Read more
13-inch 2.6GHz Retina MacBook Pro (refurbishe...
The Apple Store has Apple Certified Refurbished 13″ 2.6GHz/128GB Retina MacBook Pros available for $979 including free shipping. Original MSRP for this model was $1299. Read more
Save up to $600 with Apple refurbished Mac Pr...
The Apple Store is offering Apple Certified Refurbished Mac Pros for up to $600 off the cost of new models. An Apple one-year warranty is included with each Mac Pro, and shipping is free. The... Read more
Samsung Galaxy S 6 and Galaxy S 6 edge U.S. P...
Samsung Electronics America, Inc. has announced the Galaxy S 6 and Galaxy S 6 edge will be available in the U.S. beginning April 10, with pre-orders being accepted now. “We have completely reimagined... Read more
13-inch 2.5GHz MacBook Pro (refurbished) avai...
The Apple Store has Apple Certified Refurbished 13″ 2.5GHz MacBook Pros available for $829, or $270 off the cost of new models. Apple’s one-year warranty is standard, and shipping is free: - 13″ 2.... Read more
Save up to $80 on iPad Air 2s, NY tax only, f...
 B&H Photo has iPad Air 2s on sale for $80 off MSRP including free shipping plus NY sales tax only: - 16GB iPad Air 2 WiFi: $469.99 $30 off - 64GB iPad Air 2 WiFi: $549.99 $50 off - 128GB iPad... Read more
iMacs on sale for up to $205 off MSRP
B&H Photo has 21″ and 27″ iMacs on sale for up to $205 off MSRP including free shipping plus NY sales tax only: - 21″ 1.4GHz iMac: $1019 $80 off - 21″ 2.7GHz iMac: $1189 $110 off - 21″ 2.9GHz... Read more

Jobs Board

DevOps Software Engineer - *Apple* Pay, iOS...
**Job Summary** Imagine what you could do here. At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring 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
Sr. Technical Services Consultant, *Apple*...
**Job Summary** Apple Professional Services (APS) has an opening for a senior technical position that contributes to Apple 's efforts for strategic and transactional Read more
Lead *Apple* Solutions Consultant - Retail...
**Job Summary** Job Summary The Lead ASC is an Apple employee who serves as the Apple business manager and influencer in a hyper-business critical Reseller's store Read more
*Apple* Pay - Site Reliability Engineer - Ap...
**Job Summary** Imagine what you could do here. At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.