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

Bookends 12.7.9 - Reference management a...
Bookends is a full-featured bibliography/reference and information-management system for students and professionals. Bookends uses the cloud to sync reference libraries on all the Macs you use.... Read more
Dash 4.0.0 - Instant search and offline...
Dash is an API documentation browser and code snippet manager. Dash helps you store snippets of code, as well as instantly search and browse documentation for almost any API you might use (for a full... Read more
TrailRunner 3.8.834 - Route planning for...
TrailRunner is the perfect companion for runners, bikers, hikers, and all people wandering under the sky. Plan routes on a geographical map. Import GPS or workout recordings and journalize your... Read more
Dash 4.0.0 - Instant search and offline...
Dash is an API documentation browser and code snippet manager. Dash helps you store snippets of code, as well as instantly search and browse documentation for almost any API you might use (for a full... Read more
Bookends 12.7.9 - Reference management a...
Bookends is a full-featured bibliography/reference and information-management system for students and professionals. Bookends uses the cloud to sync reference libraries on all the Macs you use.... Read more
TrailRunner 3.8.834 - Route planning for...
TrailRunner is the perfect companion for runners, bikers, hikers, and all people wandering under the sky. Plan routes on a geographical map. Import GPS or workout recordings and journalize your... Read more
iFFmpeg 6.2.5 - Convert multimedia files...
iFFmpeg is a comprehensive media tool to convert movie, audio and media files between formats. The FFmpeg command line instructions can be very hard to master/understand, so iFFmpeg does all the hard... Read more
DaisyDisk 4.4 - $9.99
DaisyDisk allows you to visualize your disk usage and free up disk space by quickly finding and deleting big unused files. The program scans your disk and displays its content as a sector diagram... Read more
iFFmpeg 6.2.5 - Convert multimedia files...
iFFmpeg is a comprehensive media tool to convert movie, audio and media files between formats. The FFmpeg command line instructions can be very hard to master/understand, so iFFmpeg does all the hard... Read more
DaisyDisk 4.4 - $9.99
DaisyDisk allows you to visualize your disk usage and free up disk space by quickly finding and deleting big unused files. The program scans your disk and displays its content as a sector diagram... Read more

RPG Djinn Caster (Games)
RPG Djinn Caster 1.0.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0.0 (iTunes) Description: SPECIAL PRICE 38% OFF(USD 7.99 -> USD 4.99)!!!A Fantasy Action RPG of far foreign lands! Summon the Djinns and rise to... | Read more »
Alto's Odyssey gets its first trail...
There's finally video evidence of Alto's Odyssey, the follow up to the 2015 App Store hit, Alto's Adventure. It looks just as soothing and atmospheric as Alto's last outing, but this time players will be journeying to the desert. Whereas Alto's... | Read more »
Last week on Pocket Gamer
What’s going on in the wider world of portable gaming? Each week we ask that question of our sister website Pocket Gamer. The PG team covers iOS gaming, just like 148Apps, but it also strays into the world of Android games and handheld consoles... | Read more »
Pokémon GO Generation 2 evolution guide
At long last, Niantic Labs finally unleashed the Generation 2 Pokémon into the wild. Pokémon GO trainers are scrambling to grab up this new set of 80 Pokémon. There are some special new tricks required to catch all of these new beasties, though.... | Read more »
The best new games we played this week
It feels as though the New Year got off to a creaking start as far as mobile games go, but that's changed over the past few weeks. The last few days alone have seen the debut of a number of wonderful games, so we thought we'd take the time to... | Read more »
Recruit more scallywags and discover new...
Get ready to show off your sea legs all over again in Oceans & Empires’ new grand update, which aims to make the act of rising to the role of seven seas ruler even more fresh and appealing, thanks to a richness of new content on both iOS and... | Read more »
Mage the Ascension: Refuge (Games)
Mage the Ascension: Refuge 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: The groundbreaking roleplaying game Mage: The Ascension manifests in our turbulent present with Refuge, an... | Read more »
Vampire: Prelude (Games)
Vampire: Prelude 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: The classic roleplaying game Vampire: The Masquerade returns to digital games with a Prelude of things to come. Experience a... | Read more »
Digby Forever Guide: How to dig to the d...
Digby Forever is a sparkling homage to arcade classics, and while you may be tiring of the number of arcade games being thrown at you, this endless digger finds many ways to stand out from the rest of the pack. The game manages to be challenging... | Read more »
The best sales on the App Store this wee...
It's been quite the week in mobile games, but if the latest releases(there were some pretty darn good ones, in case you missed out) aren't really doing the trick, perhaps some of these discounted games will. Many of these premium games had their... | Read more »

Price Scanner via

13-inch 2.0GHz Space Gray MacBook Pro on sale...
Adorama has the non-Touch Bar 13″ 2.0GHz Space Gray MacBook Pro in stock today for $100 off MSRP. Shipping is free, and Adorama charges NY & NJ sales tax only: - 13″ 2.0GHz MacBook Pro Space Gray... Read more
13-inch Touch Bar MacBook Pros on sale for $1...
B&H Photo has select 2016 Apple 13″ Touch Bar MacBook Pros in stock today and up to $100 off MSRP. Shipping is free, and B&H charges NY sales tax only: - 13″ 2.9GHz/512GB Touch Bar MacBook... Read more
KSI-1802R SX Disinfect-able Keyboard With Wav...
KSI has unveiled a new, innovative medical keyboard, the KSI-1802R SX, at HIMSS 2017, running February 19-22 in Orlando, Florida. KSI-1802R SX is the only keyboard that combines dual factor... Read more
15-inch Touch Bar MacBook Pros on sale for up...
Amazon has 15″ Touch Bar MacBook Pros in stock today and on sale for up to $150 off MSRP including free shipping: - 15″ 2.7GHz Touch Bar MacBook Pro Space Gray: $2720.38 $79 off MSRP - 15″ 2.7GHz... Read more
Apple’s Education discount saves up to $300 o...
Purchase a new Mac or iPad using Apple’s Education Store and take up to $300 off MSRP. All teachers, students, and staff of any educational institution qualify for the discount. Shipping is free: -... Read more
13-inch 1.6GHz/256GB MacBook Air on sale for...
Newegg has the 13″ 1.6GHz/256GB MacBook Air (MMGG2LL/A) on sale for $1029.99 including free shipping. Their price is $170 off MSRP, and it’s the lowest price available for this model. Choose Newegg... Read more
Save up to $600 with Apple refurbished Mac Pr...
Apple has Certified Refurbished Mac Pros available 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 following... Read more
12-inch 1.1GHz Retina MacBooks on sale for $1...
B&H has 12″ 1.1GHz Retina MacBooks on sale for $150 off MSRP. Shipping is free, and B&H charges NY sales tax only: - 12″ 1.1GHz Space Gray Retina MacBook: $1149 $150 off MSRP - 12″ 1.1GHz... Read more
InTouch Health Expands iOS And Windows Produc...
Specialty telehealth enterprise provider InTouch Health has announced an expanded range of FDA Class I listed medical devices and software solutions for ambulatory, non-acute and non-emergent... Read more
iMobie Airs World’s 1st iCloud Manager with M...
iMobie Inc., an Apple-related software company, announced their newly-updated iPhone manager AnyTrans with exclusive feature to sync and manage contents across multiple iCloud accounts. With it,... Read more

Jobs Board

*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
Manager *Apple* Systems Administration - Pu...
Req ID 3315BR Position Title Manager, Apple Systems Administration Job Description The Manager of Apple Systems Administration oversees the administration and Read more
*Apple* Technician - nfrastructure (United S...
Let’s Work Together Apple Technician This position is based in Portland, ME Life at nfrastructure At nfrastructure, we understand that our success results from our 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
Manager *Apple* Systems Administration - Pu...
Req ID 3315BR Position Title Manager, Apple Systems Administration Job Description The Manager of Apple Systems Administration oversees the administration and Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.