TweetFollow Us on Twitter

Rhapsody In Purple

Volume Number: 14 (1998)
Issue Number: 3
Column Tag: Rhapsody

Rhapsody in Purple

by Karl Kraft

An overview of the several ways to patch applications in Rhapsody, with various levels of bravery


Rhapsody may have an OS 8 look and feel, but under the hood it is running a completely different engine. While this new engine may sweep away some of our most beloved Mac items, like loadable "system" code in the form of INITs and CDEVs, their Rhapsody equivalents are by no means non-existent, or even difficult to implement. In fact modifications to the system and to applications under Rhapsody can be done in a clean and safe manner using high level constructs.

This article seeks to explain how a Rhapsody application comes to have a particular look and feel, and ultimately how to modify the look and feel of not only your applications, but all applications on the system. The overall effect of the source in the article is to change the background color of windows to an awful shade of purple.

How Programs Launch in Rhapsody

When a user thinks of an application, he usually thinks of a single software package, such as "ClarisWorks", which is actually a collection of templates, fonts, applications, help files, and other miscellaneous items.

When most developers thinks of an application, the target is more specific, usually a single binary image that contains executable code. Under Mac OS, this executable would also have a resource fork with various resources bound to the application.

Under Rhapsody, an application consists of many more parts, each of which is either executed or interpreted by the system as a whole. The most basic parts are:

  1. The executable file, which includes loading instructions for individual processor families, and basic information such as the application's icon. Under Rhapsody, this comes in a format called "mach-o".
  2. Resources in the form of images, property-lists, string files, and others.
  3. NeXT Interface Builder or "nib" files, that define the layout and connection of objects in the interface.
  4. Various frameworks and dynamic libraries supplied by Apple Computer, such as AppKit, Foundation and System.
  5. The Window Server, a separate program that handles all the drawing and PostScript imaging.
  6. The many utility and server programs that run on the machine such as AKServer (short for AppKit Server), a program that helps handle the pasteboard.
  7. The mach kernel and underlying operating system.

Together these pieces offer you, the Macintosh hacker, dozens of places where a patch can be applied both for your projects, and applications delivered in a compiled form.

Simple Non-Code Patches

Even if you aren't a programmer, you shouldn't have much trouble figuring out how to use interface builder to modify an application. This can be useful when a sysadmin type desires to remove functionality from an application, or perform interface butchery.

Using Viewer, the Rhapsody equivalent to Finder, select an application such as For this example, pretend that you have have been ordered to prevent users from changing their preferences in this application. Note: Defaults can be changed in ways besides the preferences panel, but the type of people who would try this stunt would seldom think out the total impact of their interface butchery.

Start by making a copy of, and storing it in a safe place. You might need it to recover from your actions. is actually a folder that contains the various resources and executable pieces of the Terminal application. Through the magic of Viewer, folders with the .app extension appear as single files. You can invoke stronger magic by selecting, and then picking "Open As Folder" from Viewer's File menu. This should reveal a folder with three items, a file called Terminal, which is the actual executable image, a folder with a header file for communicating with Terminal, and a folder called Resources. The Resources folder contains all the resources for the application, such as images, nib files, string files, and property lists.

Descending into the Resources folder, you should find a folder titled English.lproj. The lproj extension indicates a language project, which contains all the localizable items for this application. This is often just about every resource in the application. Even images are localizable, because the concept they represent can be conveyed differently in each language. An image of a dollar sign might be localized to a Yen symbol for the Japanese language project.

Inside English.lproj you strike paydirt, a nib file that is cleverly named Terminal.nib. You can open this nib file in interface builder by double clicking on the nib file icon.

Note: and all the resources grouped with it are not modifiable by a regular user. You need to be either logged in as root, or working on a copy of that belongs to you.

Using Interface Builder, you can navigate through the Terminal menu structure until you find the Preferences menu item. Since nib files contain not only interface objects but also their connections, you can discover what method is called when this menu item is clicked. Using the Inspector, and selecting connections, you should discover that it is connected to the File's Owner object, and calls the method preferences:.

Simply picking disconnect from the connections inspector will render this item impotent, leaving a boring menu item that does nothing. Perhaps a dash of purple will help spice up things . Using Interface Builder, you can add a panel to the application, with some nice purple text, that says "This item is disabled". You can see a sample of my panel in Figure 1.

Figure 1.

Hold down the control key, and drag a line from the Preferences menu item to the title bar of the newly created panel, and the connection inspector will appear. Set the connection to makeKeyAndOrderFront:.

Now save all your mischief and give it a try. If you did it right, picking Preferences should bring up your new preferences panel, and frighten the user from every picking an un-authorized menu item again.

You can edit just about any resource in this manner. Images, property lists, and other resources can be modified by simply using the appropriate editor. You can also use this technique to localize an application that has not been localized to a desired language by the developer. Simply copy English.lproj to Esperanto.lproj, and edit away. The changes you make in Esperanto.lproj will be seen by any user whose default language choice is set to Esperanto before English.

Color Me Purple All Over

What if you desire a more drastic change? What if you want all the windows in your application to have a purple background? One option would be to carefully check every time a window is created, and set its background color to purple.

In a small application that might work. A few windows means a few lines of code. However, I know of several OPENSTEP applications that have on the order of several hundred nib files, and hundreds of windows that can be created on the fly. Such a manual technique would be troublesome, because you would eventually miss a window, and its gray background would just look atrocious compared to all the glorious purple windows spread across the screen.

There is a better way, and in this example, you will convert TextEdit to produce purple panels and windows. While you read this next section, grab a copy of the source to TextEdit from /NextDeveloper/Examples/AppKit/ from the Rhapsody Developer Release, and start the project building.

One of the great advantages of Objective-C is the ability to completely override a class by a technique known as posing. In posing, a class (ie: PurpleWindow) assumes the identity of its superclass, such as NSWindow. In Figure 2 a simple class tree shows where NSPanel and PurpleWindow are both subclasses of NSWindow. After PurpleWindow begins posing as NSWindow, the class tree is changed to that of Figure 3.

Figure 2.

Figure 3.

By using this technique, you can not only subclass an existing class, but make the implementation of your class the default implementation for the super class and all it's subclasses. This saves you from the trouble and difficulty of having to write a separate subclass for NSWindow, NSPanel, and other windows that you may not even know exist.

To see this in action, use ProjectBuilder to create a new class called PurpleWindow. ProjectBuilder will create two files for you, an .m file (methods) and an .h file (headers). A quick look at the header shows that ProjectBuilder thinks PurpleWindow is a subclass of NSObject rather than NSWindow. Edit the header file to read:

#import <AppKit/AppKit.h>
implementation PurpleWindow:NSWindow

Now the question is, how do you get PurpleWindows to have a purple background? If you think that the compiler should just figure it out from the prefix of "Purple", you are going to be sorely disappointed. You need to pick some method of NSWindow, override it, and then call a method to set the purple color. For starters, write the method that sets the background color to purple.

  [self setBackgroundColor:[NSColor purpleColor]];

Now all that is left is to call becomePurple sometime early in the creation of a window, before it is displayed. A particularly tempting target is makeKeyAndOrderFront:. This method is called to put a window on screen, and make it the key window (the window which accepts keyboard events). So you should dutifully write:

-(void) makeKeyAndOrderFront:sender;
  [self becomePurple];
  [super makeKeyAndOrderFront:sender];

Now whenever a PurpleWindow receives the makeKeyAndOrderFront: message it should change its background color to purple, and then have NSWindow actually put the window on screen.

Note: makeKeyAndOrderFront: probably isn't the best place to actually make this patch. I picked it as an example because it is well known, quick and easy for developers to understand.

If you typed everything correctly, you should be able to compile your new modified TextEdit, and give it a test. The change should have absolutely no effect at this point. Simply creating a subclass of NSWindow does not make it automatically pose as NSWindow, nor does it cause all windows to become PurpleWindows. At this point, the only way you will get a PurpleWindow, is if you create one in InterfaceBuilder, or programmitcally.

To start the actual posing takes a single line:

[PurpleWindow poseAsClass:[NSWindow class]];

Your decision at this point is where to insert this line in your project. After you start the posing, all calls to NSWindow methods will instead be sent to PurpleWindow. Because of this, the ideal circumstance is to perform the posing before any NSWindow objects are created. This will guarantee that all NSWindow objects in your application are actually PurpleWindow objects.

The earliest point in the execution of your application would be the function main(), found in the file Edit_main.m. By making this line the first line in main(), it will take place before any objects are created. Inserting this early in main() produces:

#import <AppKit/NSApplication.h>
#import "PurpleWindow.h"

int main(int argc, const char *argv[]) {
  [PurpleWindow poseAsClass:[NSWindow class]];
 return NSApplicationMain(argc, argv);

Build the project again, run and test. You should find that document windows have no noticeable change. At first this may disappoint you, but the reason is that the white background of the document window comes from the NSText object that completely covers the background. You will need to look at windows with some background visible, such as the Info panel, the Preferences panel, and the Find panel. These should look like Figure 4.

Figure 4.

Posing can be a valuable tool, and a dangerous weapon. Careless and unnecessary use can make programs difficult to debug and create strange effects. If all you need is some purple windows for your application, you would probably be better off with just using a subclass. Reserve the power of posing for patching class that you lack source for, such as the Appkit, and always keep the posing down to a minimum.

Posing in a Friendly Executable

If you can pose in your application, can you pose in an application where the source is not available? To pose, you need:

  1. Your class to be linked into the target application.
  2. A call relatively early on, where you can engage the actual posing action.

Some applications will make this task easy for you. These "friendly" applications support the loading and linking of dynamic code in the form of bundles. Examples include ProjectBuilder, InterfaceBuilder, Viewer, and Mail. All of these applications load bundles in one form or another.

For the next example, the goal is to make windows in the ProjectBuilder application use the same PurpleWindow as we used in TextEdit, but this time I'll assume you don't have the complete source to ProjectBuilder or Yellow Box.

The application ProjectBuilder, supports the ability to load Bundles of code and resources than can receive a notification when a project is opened, closed, an other various useful things.

A bundle is much like an INIT in that it offers a section of executable code and resources like images, all packaged as a single unit. The biggest difference between these two is that an INIT contains code to patch the Macintosh System on startup, and a bundle contains loadable code for a single application. Another difference is that the loading of INITs happens automatically, provided that they are in the proper place. Bundles are usually only loaded by applications that explicitly look for them.

Bundles are created using the same tools, and a process very similar to building applications. You start by creating a new Project in Project Builder, but pick the type Bundle instead of Application. You can then add and edit classes to your bundle, build, and test.

For the building of ProjectBuilder bundles, the task is made a little easier by a preference template that can be found at This template is a ProjectBuilder bundle ready for use in ProjectBuilder, with a default interface and class that only needs a small portion of work to be useable. To start, copy the template project to some place convenient, like your home directory, and then open it in ProjectBuilder. This type of project does not have nay interface, so all the work is done in ProjectBuilder.

You now need to edit the basic class. As you can see there are several methods already created for the template that perform the basic task of grabbing information from the ProjectBuilder application and setting up the notification center to call methods on certain events. One of these methods is called setup:. According to the documentation, this method is called when the PBBundleHost first loads the bundle. This looks like a good place to start your PurpleWindow posing as NSWindow. Insert this simple code snippet in the method builderStarted:

 [PurpleWindow poseAsClass:[NSWindow class]];

You will also need to add PurpleWindow.h to the list of headers imported by the PBTemplate class. Add this line at the top of the file PBTemplate.m.

#import "PurpleWindow.h"

Don't forget to add PurpleWindow to the list of classes to be compiled into this Bundle. You can add it to the project by selecting the classes suitcase in the current project, and then dragging PurpleWindow.m from the Workspace, or the PupleWindow application, to the classes suitcase.

If everything was done correctly, you should be able to build the application with no warnings or errors. If it worked, use the options button in the build panel to change the build type from "bundle" to "install". This will copy the bundle to ~/Library/ProjectBuilder.

Now that the bundle has been installed you can add it to the list of bundles that PBBundleHost will load by selecting Bundles in the Preferences panel of Project Builder. It won't be loaded right away though, you need to quit ProjectBuilder and relaunch in order for the bundle to be loaded.

When you launch ProjectBuilder, you should be able to bring up the Find panel and it should have a purple window as shown in Figure 5. If not, something is wrong. Check to make sure that the project was built and installed correctly, and that all the source code changes have been made to the bundle.

Figure 5.

If you play with this new creation for a while, you will notice a few important things related to the goals stated in the very beginning of this journey:

The first is that it works. It is possible to write code that significantly modifies an application's framework even if you do not have source for the framework, or the application. We were able to patch at the level of the high-level framework, rather than at a low-level machine trap.

It is a clean patch. The code doesn't have to patch a half-dozen points to constantly detect windows and convert the background to purple. And the patch only applied to the application that loaded it. It is easy to see that if the bundle was bogus, it would only affect the single application that loaded it.

Application or Bundle, the code was identical. PurpleWindow wasn't modified in this example at all. You merely copied it from a previous project. This is part of what made it such a clean patch. You can design new classes to augment the AppKit in an application, and then apply these classes to other applications.

The patch fell short in two very important goals:

The patch only applies after the bundle is loaded. In the case of ProjectBuilder, this was before any windows were created. However an application like Preferences does not load the executable code from the bundle until it is actually needed. A system wide PurpleWindow patch is not going to do much good if the user has to push a button in every app to get it going.

The patch only applies to ProjectBuilder, which is a "cooperative" application. You still don't have a way to get the executable code of the bundle linked into just any running application. Even the actual API for how a bundle interacts with an application is different for each application, so the bundle you have created works only in ProjectBuilder.

Both of these problems can be easily solved if programmers would band together and create a common API, and agree to have a common directory where bundles could be located. Similarly, world peace could be easily achieved if you just get the leaders of the world to agree on a few things. There are more developers than world leaders.

An Exploitable Link

This article started with a list of what makes up an application, and indicated that each of these was a target point for modification. So far you have modified the resources, interface files, and the executable itself in source code form. While each of these points has advantages and can help in the overall goal, they don't deliver the ideal hoped for: a patch to all applications that run on the system. If there is a way to make patch every application, it must lay in the other items, such as the frameworks, window server, server programs, or the kernel.

The kernel has facilities to allow loadable code and drivers, similar to the way that Preferences allows you to load bundles, and since every program links to the kernel, it seems like the ideal place to find the abilities required for this venture. However, developing source code that dynamically loads into the kernel takes a great deal of discipline, and debugging takes a great deal of patience and usually two machines. Also since code running in the kernel space can do anything, a much greater chance exists to trash your operating system beyond repair.

Server programs like AKServer primarily serve in interprocess communication between applications and in providing system resources. They have no facility for loadable code, which results in a more difficult patch. They are not going to do much to bring us closer to the goal.

With a little work, functions can be sent to the WindowServer, however they must be written in PostScript, and they tend to be limited to affecting how the drawing or windows are presented, such as changing the shape or color of the cursor.

This leaves frameworks, which also have no provision for loading code. However, there is a weak point in how frameworks are loaded that can be exploited.

How Frameworks Work

In the final step of compiling any Rhapsody program, the linker is passed a list of frameworks that the program requires for execution. This list is then embedded within a portion of the executable file. When a file is passed to the operating system for execution, it finds the needed frameworks, dynamically links them to the executable, and then actually executes the program. If a common framework was replaced with a framework that loaded bundles, it should be possible to make any application behave as a cooperative application like ProjectBuilder.

To find out what Frameworks are common, you can examine various applications using the AppEdit application, or the command line tool "otool". Casual examination shows that three frameworks are used by every application. These three frameworks are called System, Foundation, and Appkit, and are all located in /NextLibrary/Frameworks.

The System framework encompasses all basic operating system calls, such as read() and write(). If this framework was modified, it would affect not only applications but every executable file including command line tools and startup procedures. Patching this framework is possible, but an error could be difficult to recover from. Without a valid System.framework, your computer can not even start up.

The next possible framework is Foundation. While not used by as many command line programs, it is used by some, and therefore has many of the same problems as System.framework.

That leaves AppKit.framework, which is a good choice overall. There are no boot programs depending on it, and if you totally destroy the framework, it is possible to repair the damage by booting into single-user mode. Appkit.framework also make sense, as most patches would be targeted towards applications' look and feel. It also has another benefit missing from Foundation and System. To patch applications. you need to load bundles at some point early in the application's life. One of the very first objects instantiated in an application is the NSApplication class, and this class lives in Appkit.framework. Of course, it is possible to make the patches in the System or Foundation frameworks, just with a greater risk.

It would be possible to patch the actual binary code of the Appkit framework, however, such a low level patch is not needed. Instead you can move the Appkit framework to a new location, and then create a new "patch" framework. If the "patch" framework is placed where the operating system looks for Appkit.framework, then launched applications will bind to the "patch" framework, if the patch Framework is compiled to depend on the new Appkit framework in its new location, both the patch framework, and the Appkit framework would be loaded whenever a new application is launched.

The Adventure Begins

This procedure is not for the weak, timid, tired, forgetful or easily worried. Don't try this on a system that has important data. You would be well advised to read this entire section from start to finish and understand it before placing your fingers on the keyboard. Also, between the time this was written and the time you read it, the layout of files may have changed drastically, check the Ensuing web site for any errata. Above all else, don't come complaining to me when you find your system no longer boots.

In this process you will end up with three frameworks:

  • OldKit. This is the original AppKit as supplied by Apple, modified to run as either AppKit or OldKit.
  • NewKit. This will be the new version of AppKit that you make using Project Builder.
  • AppKit. This is what the system thinks is the one true AppKit and can be toggled back and forth between OldKit and NewKit.

Moving the Appkit framework ( or any important framework) is a quick way to disable a system, but it is necessary to get things rolling. You will need to either login as root, or become root using the superuser command. As root, and using the command line, execute the following commands:

cd /NextLibrary/Frameworks

This will get your current working directory to be the place for the rest of these commands.

mkdir OldKit.framework

This creates a new folder called OldKit that will hold the original Appkit.

 (cd AppKit.framework; gnutar -cf - . ) | (cd OldKit.framework; gnutar -xf - ) 

This whopper of a command copies the contents of AppKit to OldKit, and preserves as much of the directory structure as possible. Frameworks tend to have a great deal of links, and using the copy command will use more than twice the disc space. This command may take several minutes depending on how speedy your hard drives are.

cd OldKit.framework

Change into the OldKit framework for the rest of the commands

ln -s Versions/B/OldKit OldKit

This creates an alias called OldKit in the current directory that links to where the actual copy of OldKit will reside.

cd Versions/B
cp AppKit OldKit

This copies the file AppKit to OldKit. This is done so that you can have a pristine copy of AppKit when AppKit.framework is linked to OldKit.framework.

At this point OldKit.framework would seem to be ready to go, however there is a small bit of binary editing that needs to be done first. When applications are compiled to use OldKit, the actual OldKit file you just created will be examined, and inside is a string that identifies the path to this framework, which is still set to AppKit. To see this string you can type the command

otool -L OldKit

You must change this string so that NewKit can successfully link to OldKit. To change the string use a hex editor like HexEdit or you can download a program called App2Old that specifically patches AppKit to OldKit at After you edit the file, use otool to make sure the change was made.

Now that this has been done, you have a new framework called OldKit that is functionally identical to AppKit, just with a different name. In the mean time, the original AppKit framework still exists, and applications launched at this point still use the AppKit.framework.

You now need to create a new AppKit framework that accomplishes two tasks.

  1. 1. Augment the Applications class to activate the posing.
  2. 2. Link to OldKit, so that original AppKit classes are available at runtime.

The framework is created in much the same way as an Application or bundle. From ProjectBuilder, create a new project, and select the type of Framework. You then need to edit several variables and configuration files to prepare the project for compiling. Add the OldKit framework by adding it to the frameworks suitcase. Edit the file Makefile.postamble and change the following lines, so that the versions of this kit match the original AppKit.


You now need to find a convenient place to start the posing. A framework does not have a main() function, so you need some Objective-C method called early in the life of the Application. The ideal choice is to make an initialize method for your posing category of Application.

While not the very first method called in the life of an application, it does happen very early, and usually before any nibs are loaded. Create a new class file called Application_Patch.m, and modify the header to be a category of Application. The add an implementation of the method initialize to the m file.


@interface Application(Patch)

@implementation Application(Patch)
  [PurpleWindow poseAsClass:[NSWindow clas s]];

The final source for this project, is the familiar PurpleWindow class, which you can copy from the previous example used in ProjectBuilder. If you compile and install, you should find a new framework in ~/Library/Frameworks called AppKit.framework, this is the patched AppKit.framework. Using AppEdit or otool, you should be able to see that this framework relies on the OldKit framework.

You are now ready to install this new framework as the default AppKit framework. By running these commands you can put your machine in to a very unstable state. Since you will be removing the AppKit to a new location, the system will be unable to find any AppKit resources that it may need, such as an open, save or font panels. If you try to use any system resources in AppKit.framework that are not already loaded, you may find that you program hangs.

From the command line type the following as root:

cd /NextLibrary/Frameworks
cp -r ~/AppKit/AppKit.framework NewKit

This copies NewKit from your personal library to the system library.

mv AppKit.framework safety
This moves AppKit.framework to a folder named safety

ln -s NewKit AppKit.framework

This creates an alias for NewKit called AppKit.framework,

At this point you should be able to launch new applications and find that familiar, yet somewhat sickening shade of purple. If Applications won't launch any more, relink AppKit to OldKit, and then proceed to debug by checking the console for messages.

Don't play around too much. The system at this point is still very unstable. When the current running applications were launched, (like Viewer, ProjectBuilder, Terminal), they started using AppKit.framework to load system resources. Those resources are now in OldKit, and if you try to print, open or save files, or anything else that needs a system resource, you may be lucky to get an error message, more likely you will wedge things pretty bad.

It would seem therefore that if you logged out and logged in, or rebooted, your entire system would be patched and you would be done. However, some of the early login process requires resources in Appkit.framework, and they are not forgiving about the fact that the AppKit is not there. If you reboot at this point you will not be able to login.

That said, you can fix this minor problem by changing the Resources directory of NewKit to point to the Resources of OldKit.

cd /NextLibrary/Frameworks/NewKit
rm -rf Resources
ln -s ../OldKit/Resources Resources

After rebooting, everything should return to "normal", and you should have a very purple operating system to play with. Congratulations.


When I originally wrote this hack during MacHack '97, it actually worked a bit differently. Instead of the patches being part of the patched AppKit, they were loadable bundles in much the same way as ProjectBuilders loadable bundres. A front end called HackManager allowed the user to pick which patches were applied to which applications. While the overall design was more flexible, and enabled the user to turn off the patch (something missing from this example), it suffered a great deal from slow launching applications. Each time an application was loaded, several dozen bundles would have to be read into memory as well, and then applied to the running application.

Hopefully, Apple will develop some plan for dealing with system wide patches like the example given. However, their most recent FAQ on Rhapsody suggests that the entire idea of modifying the system as a whole is going to be avoided.

Karl Kraft,, has written several applications for OPENSTEP, the operating system on which Rhapsody is based, and is currently working on The CodeBook, an interactive book for learning the Yellow Box framework.


Community Search:
MacTech Search:

Software Updates via MacUpdate

Merlin Project 4.2.0 - Project managemen...
Merlin Project is the leading professional project management software for OS X. If you plan complex projects on your Mac, you won’t get far with a simple list of tasks. Good planning raises... Read more
Skim 1.4.28 - PDF reader and note-taker...
Skim is a PDF reader and note-taker for OS X. It is designed to help you read and annotate scientific papers in PDF, but is also great for viewing any PDF file. Skim includes many features and has a... Read more
RapidWeaver 7.3.2 - Create template-base...
RapidWeaver is a next-generation Web design application to help you easily create professional-looking Web sites in minutes. No knowledge of complex code is required, RapidWeaver will take care of... Read more
Together 3.8.1 - Store and organize all...
Together helps you organize your Mac, giving you the ability to store, edit and preview your files in a single clean, uncluttered interface. Features Smart storage. With simple drag-and-drop... Read more
Apple MainStage 3.3 - Live performance t...
Apple MainStage makes it easy to bring to the stage all the same instruments and effects that you love in your recording. Everything from the Sound Library and Smart Controls you're familiar with... Read more
Apple iOS 10.3 - The latest version of A...
iOS 10 is the biggest release of iOS ever. A massive update to Messages brings the power of the App Store to your conversations and makes messaging more personal than ever. Find your route with... Read more
Postbox 5.0.12 - Powerful and flexible e...
Postbox is a new email application that helps you organize your work life and get stuff done. It has all the elegance and simplicity of Apple Mail, but with more power and flexibility to manage even... Read more
Apple Keynote 7.1 - Apple's present...
Easily create gorgeous presentations with the all-new Keynote, featuring powerful yet easy-to-use tools and dazzling effects that will make you a very hard act to follow. The Theme Chooser lets you... Read more
Apple Pages 6.1 - Apple's word proc...
Apple Pages is a powerful word processor that gives you everything you need to create documents that look beautiful. And read beautifully. It lets you work seamlessly between Mac and iOS devices, and... Read more
Apple Numbers 4.1 - Apple's spreads...
With Apple Numbers, sophisticated spreadsheets are just the start. The whole sheet is your canvas. Just add dramatic interactive charts, tables, and images that paint a revealing picture of your data... Read more

The best deals on the App Store this wee...
Deals, deals, deals. We're all about a good bargain here on 148Apps, and luckily this was another fine week in App Store discounts. There's a big board game sale happening right now, and a few fine indies are still discounted through the weekend.... | Read more »
The best new games we played this week
It's been quite the week, but now that all of that business is out of the way, it's time to hunker down with some of the excellent games that were released over the past few days. There's a fair few to help you relax in your down time or if you're... | Read more »
Orphan Black: The Game (Games)
Orphan Black: The Game 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: Dive into a dark and twisted puzzle-adventure that retells the pivotal events of Orphan Black. | Read more »
The Elder Scrolls: Legends is now availa...
| Read more »
Ticket to Earth beginner's guide: H...
Robot Circus launched Ticket to Earth as part of the App Store's indie games event last week. If you're not quite digging the space operatics Mass Effect: Andromeda is serving up, you'll be pleased to know that there's a surprising alternative on... | Read more »
Leap to victory in Nexx Studios new plat...
You’re always a hop, skip, and a jump away from a fiery death in Temple Jump, a new platformer-cum-endless runner from Nexx Studio. It’s out now on both iOS and Android if you’re an adventurer seeking treasure in a crumbling, pixel-laden temple. | Read more »
Failbetter Games details changes coming...
Sunless Sea, Failbetter Games' dark and gloomy sea explorer, sets sail for the iPad tomorrow. Ahead of the game's launch, Failbetter took to Twitter to discuss what will be different in the mobile version of the game. Many of the changes make... | Read more »
Splish, splash! The Pokémon GO Water Fes...
Niantic is back with a new festival for dedicated Pokémon GO collectors. The Water Festival officially kicks off today at 1 P.M. PDT and runs through March 29. Magikarp, Squirtle, Totodile, and their assorted evolved forms will be appearing at... | Read more »
Death Road to Canada (Games)
Death Road to Canada 1.0 Device: iOS Universal Category: Games Price: $7.99, Version: 1.0 (iTunes) Description: Get it now at the low launch price! Price will go up a dollar every major update. Update news at the bottom of this... | Read more »
Bean's Quest Beginner's Guide:...
Bean's Quest is a new take on both the classic platformer and the endless runner, and it's free on the App Store for the time being. Instead of running constantly, you can't stop jumping. That adds a surprising new level of challenge to the game... | Read more »

Price Scanner via

13-inch MacBook Airs, Apple refurbished, in s...
Apple has Certified Refurbished 2016 13″ MacBook Airs available starting at $849. An Apple one-year warranty is included with each MacBook, and shipping is free: - 13″ 1.6GHz/8GB/128GB MacBook Air: $... Read more
12-inch Retina MacBooks on sale for $1199, sa...
B&H has 12″ 1.1GHz Retina MacBooks on sale for $100 off MSRP. Shipping is free, and B&H charges NY sales tax only: - 12″ 1.1GHz Space Gray Retina MacBook: $1199 $100 off MSRP - 12″ 1.1GHz... Read more
Save up to $260 with Apple refurbished 12-inc...
Apple has Certified Refurbished 2016 12″ Retina MacBooks available for $200-$260 off MSRP. Apple will include a standard one-year warranty with each MacBook, and shipping is free. The following... Read more
13-inch 2.7GHz Retina MacBook Pro on sale for...
B&H Photo has the 2015 13″ 2.7GHz/128GB Retina Apple MacBook Pro on sale for $170 off MSRP. Shipping is free, and B&H charges NY tax only: - 13″ 2.7GHz/128GB Retina MacBook Pro (MF839LL/A): $... Read more
15-inch 2.2GHz Retina MacBook Pro on sale for...
B&H Photo has the 2015 15″ 2.2GHz Retina MacBook Pro (MJLQ2LL/A) on sale for $1799.99 including free shipping plus NY sales tax only. Their price is $200 off MSRP. Read more
Save up to $160 with Apple refurbished 9-inch...
Apple has Certified Refurbished 9″ and 12″ Apple iPad Pros available for up to $160 off the cost of new iPads. An Apple one-year warranty is included with each model, and shipping is free: - 32GB 9″... Read more
Apple Chip Foundry TSMC To Begin A11 System-o...
Digitimes’ Steve Shen is reporting today that according to the Chinese-language Economic Daily News (EDN), chipmaker and major Apple supplier foundery Taiwan Semiconductor Manufacturing Company (TSMC... Read more
MacX MediaTrans 3.5 iOS Data Transfer Spring...
MacXDVD Software has announced general availability of the latest MacX MedTrans 3.5, featuring a new user interface (UI). MacX MediaTrans is ann iPhone manager that enables free data transfer between... Read more
Regular Price $19.95 DupeZap 4 Finder For OS...
Hyperbolic Software has announced the release of DupeZap 4.0.2, their modern duplicate finder developed exclusively for macOS. DupeZap 4 is an utility for Mac owners seeking to reclaim disk space... Read more
B-Eng Releases SSD Health Check for MVNe for...
Fehraltorf, Switzerland based B-Eng has announced the release and immediate availability of SSD Health Check for MVNe for MacBook Pro, their app that delivers important data and insights for MVNe... Read more

Jobs Board

Fulltime aan de slag als shopmanager in een h...
Ben jij helemaal gek van Apple -producten en vind je het helemaal super om fulltime shopmanager te zijn in een jonge en hippe elektronicazaak? Wil jij werken in Read more
*Apple* Mobile Master - Best Buy (United Sta...
**492889BR** **Job Title:** Apple Mobile Master **Location Number:** 000886-Norwalk-Store **Job Description:** **What does a Best Buy Apple Mobile Master do?** Read more
*Apple* Mobile Master - Best Buy (United Sta...
**492472BR** **Job Title:** Apple Mobile Master **Location Number:** 000470-Seattle-Store **Job Description:** **What does a Best Buy Apple Mobile Master do?** Read more
*Apple* Mobile Master - Best Buy (United Sta...
**492562BR** **Job Title:** Apple Mobile Master **Location Number:** 000853-Jackson-Store **Job Description:** **What does a Best Buy Apple Mobile Master do?** Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.