TweetFollow Us on Twitter

Packaging Special Payloads with PackageMaker

Volume Number: 24
Issue Number: 10
Column Tag: PackageMaker

Packaging Special Payloads with PackageMaker

Bringing drivers, libraries, and plug-ins to the OS X target

by José R.C. Cruz


One task that some developers face is to deliver special payloads such as device drivers, frameworks, and codecs to their users. Unlike applications or files, these payloads must reside in specific locations on the target system. They must have the right settings for permissions, UID, and GID. Some payloads require specific hardware to operate. Some require authentication or a specific post-install action.

In this article, we will explore the issues behind delivering these special payloads. First, we will list each payload and look at how to handle each one. Then, we will learn how to check for specific hardware on the target system. Next, we will build a demo package with three payloads, two of which are special. We will then test this package and study its behavior.

As always, the installer project featured here is available from the MacTech website. To get a copy of the project, go to the following URL.:

The Special Payloads

As stated earlier, special payloads need special handling. To correctly install this payload, first know what its needs are and how to address them. Doing so will help avoid any post-install issues such as system hangs, freezes, or even a kernel panic.

The following are three basic groups of special payloads that you will encounter most. Some payloads do not fit into any these groups, but those are few and far between.


The job of a driver is to add or extend system functionality. Drivers in OS X are often in the form of a kernel extension. You can place the driver inside an application bundle or in the directory /System/Library/Extensions. If the latter, prepare each driver as follows.

  • First, set the bundle's UID and GID to root and wheel. Make sure to use the same UID and GID to the bundle's subdirectories and component files.

  • Next, set its permission flags to rwxr-xr-x. Use the same flags for the bundle's subdirectories and executable items. For the component files, however, use the flags rw-r-r-.

Now some drivers work only if the target system has the correct hardware. Others need the system restarted in order to become active. Lastly, since access to /System/Library/Extensions is restricted, users must authenticate the install session.


Libraries carry code and data that provide services to various OS X applications. They can come in several formats, with the most common being the framework bundle.

There are several places wherein to store a framework. Choosing which one to use depends on the framework at hand. For most frameworks, use the directory /Library/Frameworks. This location gives all applications access to the framework code. To limit access only to applications that the user owns, use the directory ~/Library/Frameworks. Both directories are public and as such do not need users to authenticate the install session.

For frameworks that provide system-wide services, use /System/Library/Frameworks. For those meant only for in-house or private use, use the location /System/Library/PrivateFrameworks. Both locations, however, will require users to authenticate the install session. Also, Apple reserves the right to modify either location during every OS X upgrade. Make sure to provide a way to backup any custom frameworks in these locations.

Frameworks that go into the /Library or ~/Library locations can use the user's login name and admin as their UID and GID. Those that go into the /System/Library locations must use root and wheel. As for permission flags, use rwxr-xr-x for the framework, its subdirectories, and its binary files. For any text files inside the framework, set their permission flags to rw-r-r-.

Other libraries use a proprietary file format. They also have their own locations on the target volume. For instance, Python packages use either /Library/Python or ~/Library/Python as their locations. Perl modules, on the other hand, go into either /Library/Ruby or ~/Library/Ruby. And POSIX libraries use the "invisible" directory /usr/lib. The UID and GID for these libraries are root and wheel. Their permissions flags are always set to rwxr-x-r-x.


Plug-ins add custom features or functions to a software client, which can be either an application or a system service. The client loads a plug-in on demand and after its host system has booted up.

Most plug-ins go in specific directories inside either /Library or ~/Library. Each plug-in directory is named after the plug-in service or after the plug-in's client. For instance, osax plug-ins, used by the AppleScript runtime, go into the directory ScriptingAdditions. QuickTime codecs use the similarly named QuickTime directory. Preferences panels are stored in the PreferencesPanes directory. And Dashboard widgets go in the Widgets directory. Consult your project guidelines for the correct directory for your plug-ins.

Also, most plug-ins use the user's login name as their UID, and admin as their GID. As for permission flags, these vary with the type of plug-in. For example, osax plug-ins use rwxrwxrwx for their bundle directories and files. QuickTime codecs use rwxr-xr-x for its subdirectories and binary files, but rw-r-r- for its support files. Again, check your project guidelines for the correct settings.

Checking For Hardware

As stated earlier, some special payloads need the right hardware present on the target platform. So, if you let the package to check the target's hardware, you can reduce the number of unwanted files stored on the target. Fewer unwanted files means more space to store user data. It also means a leaner and more responsive system.

You can perform the hardware check in a number of ways. One way is to use one of the preset conditions in the Requirements Editor. Another way is to use a script to do a sysctl query. A more elegant way is to query the IORegistry with JavaScript.

Using preset conditions

Figure 1 shows the two sets of conditions that you can use for a hardware check. When creating a package with PackageMaker, choose the Requirements tab to specify requirements that this package must meet. The first set (shaded in green) focuses entirely on the host's hardware traits. To use one of the conditions, first select them from the If pop-up menu. Then choose the Boolean operator from the is menu. Next, enter the desired value to the field provided. Or if the condition provides a menu of Boolean flags, choose the right flag from that menu.

Figure 1. The preset conditions for hardware checks

For example, Figure 2 shows two hardware checks using the preset conditions. The one on the left checks to see if there are at least two CPUs present. And the one on the right checks if the hardware supports 64-bit instructions.

Figure 2. Two sample hardware checks

The second set of conditions (shaded in blue) focuses on devices attached to the host platform. Each condition looks for the device by examining one of three hardware buses: FireWire, USB, and PCI. If the device is present on the bus, the condition returns a TRUE; otherwise, it returns a FALSE.

To illustrate, assume your payload uses the FlashGO! USB card reader from Imation Corp. To look for this device, setup the hardware check as shown in Figure 3. If the device is absent, the check can either disable the payload or display an error dialog. Note the name used in the device field. This is the name under which the device appears in the IORegistry. It is not always the same as the product name.

Figure 3. Checking for a USB device

Using system.sysctl()

You can also use the Requirements Editor to run a sysctl query. To do so, choose Results of Sysctl as the check condition. Enter the sysctl node and value in the fields provided, and then choose the Boolean operator from the is pop-up menu. For example, assume your payload works only if the host has a bus frequency of at least 100 MHz. For this check, setup the editor dialog as shown in Figure 4. Here, the sysctl node hw.busfrequency goes in the field labeled value. Then the sysctl value of 100000000 goes in the field next to the Boolean pop-up menu.

Figure 4. Checking the system bus frequency

You can also add several sysctl queries using the Requirements Editor. The package, however, treats the check results in an all or nothing manner. If at least one sysctl check fails, then the entire group of checks also fails. For a more complex check logic, use a custom JavaScript function to do the query.

Listing 1 shows one example of such a function. This function first checks if the host platform has more than one CPU. If the check proves false, the function then checks if the CPU can handle 64-bit processes. Now if the CPU can handle 64-bit tasks, the function returns a TRUE when the CPU speed is greater than 100 MHz. But if the CPU handles only 32-bit tasks, the function returns TRUE only when the CPU speed is at least 200 MHz.

Listing 1. Checking the hardware with system.sysctl()

function check_sysctl() {
   tCPU = system.sysctl('hw.ncpu');
   if (tCPU == 1) {
      tTyp = system.sysctl('hw.cpu64bit_capable');
      tClk = system.sysctl('hw.cpufrequency');
      if (tTyp = 1)
         return (tClk > 1000000000);
         return (tClk > 2000000000);
   else if (tCPU > 1)
      return true;
      return false;

To use the above function, first add the script to the project's Script Repository. Then choose Result of JavaScript as the check condition. Enter the function's name into the function field. Set the Boolean operator and value as shown in Figure 5.

Figure 5. Calling the custom function check_sysctl()

Checking The IORegistry

Sometimes, you want hardware checks that are difficult to do using either a preset condition or a sysctl query. So to do these checks, you will access the IORegistry directly. The IORegistry is a database of services nodes on OS X. Each node can be an active hardware or driver. The IORegistry is also dynamic by design. It updates its list of nodes each time hardware or driver is added or removed. Equally important, the IORegistry shows how the nodes related to each other.

Viewing the IORegistry

To view the IORegistry, use the Xcode utility tool IORegistryExplorer. This tool displays the entire IORegistry as a hierarchical tree on the left panel (Figure 6). Selecting a node on the tree displays that node's properties on the right panel. Nodes that have a triangle widget have child nodes under it. Clicking the widget hides or shows the children for that node.

Figure 6. Main window of the IORegistry tool

The top pane on the window controls how the tool displays the IORegistry. By default, the tool shows all the active nodes on the tree. To view only nodes that belong to a specific category, choose the category from the upper-left pop-up menu (Figure 7). Your choices include IODeviceTree (default), IOFireWire, IOPower, and IOUSB. Also, as stated earlier, the tool uses a hierarchical tree to view the IORegistry. To switch to a columnar view, click the second button near the upper-left corner.

Figure 7. Controls on the IORegistryExplorer tool

The second pop-up menu displays the absolute path of the selected node on the IORegistry. If there is only one instance of the node, this menu displays only one path. But if there are multiple instances of the same node, the menu will show multiple paths. For example, on the iBook/G4 system, selecting the node CHUDProf displays only one path.


But selecting the IONetworkStack node displays four possible paths (Figure 8). Here, a checkmark precedes the path of the selected node. Each instance of IONetworkStack belongs to a different network device. Selecting the path to each instance also selects that node on the IORegistry.

Figure 8. Multiple instances of IONetworkStack

Finally, on the upper-right corner of the pane is the filter field. Use this to show only those nodes that have a certain string. Assume, for example, your target platform has a number of Macally hardware products. To display the nodes for those products, type the string "Macally" into the filter field. The tool then updates its IORegistry display as shown in Figure 9. Note the matching nodes are in bold, whereas their parent nodes are in grey text.

Figure 9. Filtering the IORegistry display

Querying the IORegistry

Use the system.ioregistry() property to query the IORegistry data from the installer package. This property is an instance of the JavaScript object, also named IORegistry (Figure 10). It is available only to the InstallationCheck phase of the install session.

Figure 10. The IORegistry object

The IORegistry object has three sets of functions, all of which return an associative Array as their results. Some functions take the node's name or class as input, but most take the absolute path to the node. You can get this path by using the IORegistryExplorer tool.

The first set of IORegistry functions returns the parents or children of a specific node. For example, assume you want to query the node com_apple_driver_AudioIPCDevice. To get a list of children for this node, use the childrenOf() function. Pass the absolute path to the node as the input string.

   tChild = system.ioregistry("IOService:/IOResources/¬

To get a list of parent nodes, use the parentOf() function.

   tParents = system.ioregistry("IOService:/IOResources/¬

If the node has neither children nor parents, both functions will return a NULL.

The second set of functions searches for a node in the IORegistry. They serve the same task as the filter field on the IORegistryExplorer tool. Use the function matchingName() to search for a node with a given name. Pass the name string as the function's input. For example, the snippet below searches for all nodes with the string "Macally".

   tMacally = system.ioregistry.matchingName("Macally")

If, however, you want nodes belonging to a specific class, use the matchingClass() function. Again, pass the class name as the input string. To illustrate, the following snippet will search for all FireWire nodes.

   t1394 = system.ioregistry.matchingClass("FireWire")

If either search fails, the functions will return a NULL.

The third set consists one function that retrieves the properties for a given node. This function, fromPath(), takes one argument, which is the absolute path to the node. For example, to read the properties of the node CHUDProf, use the function as follows.

   tCHUD = system.ioregistry.fromPath("IOService:/IOResources/CHUDProf")

Again, if the node is absent, the function returns a NULL.

Now, you can read the Array elements in two ways. One way is to access each element via indices. Assume you want to examine all the child nodes of AppleACPIPlatformExpert. Listing 2 shows how you can do so using a for block. You can also use a do...while or a while block to do the same task.

Listing 2. Reading the children nodes of AppleACPIPlatformExpert

   var tSib = 
   if (tSib != null) {
      for (var tIdx = 0; tIdx < tSib.length; tIdx++) {
         var tNod = tSib[tIdx];
         // - process each child node

Another way is to iterate through each Array element using a iterator. This method works best if the Array data is a list of properties. For example, assume you want to examine the properties of CHUDProf. Listing 3 shows how you can do so with the iterator.

Listing 3. Reading the properties of CHUDProf

   var tDev = 
   if (tDev != null) {
      for (var tInf in tDev) {
         var tProp = tDev[tInf]
         // - process each node property         

Building The Package

In this section, you will build a basic installer package of special payloads. You will setup the package using the some of the information featured earlier. For a realistic touch, the payloads will be support software for the Macally USB product, the IceCad graphics tablet. These payloads are as follows.

  • a configuration utility named Macally
  • a StartupItem bundle named TabletApp

  • a kernel driver named TabletDrv.kext

Due to copyright restrictions, the installer project will not include the Macally software. But you can get your copy of the software at the following URL:

Adding payloads

Start by creating a new installer project. On the Install Properties dialog, choose 10.4 as the minimum target platform. You can also try 10.5, though you will find little, if any, change in behavior. For now, the rest of the article assumes a 10.4 target. It also assumes the payloads are inside a directory named macally.

Save the project file as Foobar_Macally. Click the package icon on the payload list to get the Configuration panel for the entire package. Update the panel as shown in Figure 11. Here, the package will display the Custom Install panel to the user. And it will allow users to choose a target volume for the payloads. Save your changes by choosing Save from the File menu.

Now click the + button on the lower-left corner of the payload list. Use the Open File dialog to go to the macally directory and to select the utility Macally Click the Choose button to add the utility to the list. Then display the Configuration panel for that payload (Figure 12). Notice the payload gets /Applications as its destination. Change this to /Applications/Macally Leave the rest of the panel at their default settings. Save your changes when done.

Figure 11. Configuring the entire package

Figure 12. Configuring the application payload Macally

Click the + button again, and add the StartupItem bundle TabletApp to the project. Then bring up the Configuration panel for that payload (Figure 13). This time, the payload gets / as its destination. Since this is incorrect, change the path to /Library/StartupItems. Also, a StartupItem bundle must be loaded at boot-time. So, go to the Restart Action pop-up menu and choose Require Restart as the action. Leave the rest of the settings unchanged and save your changes.

Next, use the same steps to add TabletDrv.kext to the project. Then display the Configuration panel for this payload (Figure 14). Since the payload is a kernel extension, it gets /System/Library/Extensions as its destination. As that location has restricted access, make sure to set the checkbox Require admin authentication. But leave the restart action to None. OS X loads this extension only when it finds the Macally graphics table plugged in.

Figure 13. Configuring the StartupItem payload TabletApp

Figure 14. Configuring the driver payload TabletDrv.kext

Making checks

Next, you will add two simple checks to the package. Start by displaying the Requirements panel for the entire package. Then click the + button to get the editor dialog window. Update the dialog as shown in Figure 15. This check scans the USB bus for the Macally IceCad tablet. If the tablet exists, the check allows the install session to continue. Otherwise, it displays the specified error message.

To add the second check, select the choice for the payload TabletApp. Go to its Configuration panel and make sure the checkboxes Selected and Enabled are set. Now go to the Requirements panel for that choice. Click the + button to get the editor dialog. Update the dialog as shown in Figure 16. This checks examines the system version of the target platform. If the system happens to be 10.4 or older, the check leaves the choice's state unchanged. Otherwise, it disables and deselects the choice. The reason for this check is that StartupItem bundles are now deprecated on 10.5, in favor of LaunchAgents and LaunchDaemons. Since the package also supports 10.4 targets, it must know when to correctly disable this choice.

Figure 15. Checking for the graphics tablet

Figure 16. Checking for the target system

Setting up

Now it is time to set the permission flags, UIDs and GIDs of each payload. Start by selecting the payload Macally IceCad from the payload list. Then click the Contents tab to display that payload's Contents panel. Click the triangle widget next to the payload's name. Repeat the same step until you see all the files contained in the bundle (Figure 17). Select all the files and directories by choosing Select All from the Edit menu.

Figure 17. Setting the permissions, UID, and GID for Macally IceCad.

To set the payload's UID, choose root from the Owner pop-up menu. Conversely, let the GID be the default Group value of admin. Next, carefully select only the directories and bundles that make up the payload. Set the checkboxes Read, Write, and Execute for both Owner and Group. For Others, however, set only the checkboxes Read and Write. Use the same settings for the executable file inside Contents/MacOS. For the rest of the files, set the checkboxes Read and Write for both Owner and Group, but only the Read checkbox for Others. Save your changes when you are done.

Next, select TabletApp from the payload list. Use the Contents panel to display all the directories and files in that payload. Then choose Select All from the Edit menu. For the payload's UID, choose root from the Owner pop-up menu; for the GID, choose wheel from the Group menu. Then set the checkboxes Read, Write, and Execute for the Owner. But set only the Read and Execute checkboxes for both Group and Others.

Finally, select the payload TabletDrv.kext from the list. Go to its Contents panel and display all the items belonging to this payload. Select all the items and set their UID and GID to root and wheel. Next, select only the directories and bundles in the payload. Set the checkboxes Read, Write, and Execute for the Owner, but only Read and Execute for the Group and Others. Now select just the files in the payload. Set the checkboxes Read and Write for the Owner, but only Read for Group and Others. Save your changes immediately.

Package testing

You are now read to test your installer package. Start by choosing Build and Run from the Project menu. When prompt for a package name, enter the name Macally_Demo. PackageMaker then builds a distribution package with the three payloads. It sets the correct permissions, UID, and GID for each payload. Once done, it tells the Installer core utility to open the package and start the install session.

At the start of the session, the first panel you see is the Welcome panel (Figure 18). But this panel appears only when the target has the IceCad graphics tablet attached. If the tablet is absent, an error dialog appears on top of the panel (Figure 19). Clicking the Close button then ends the install session.

Figure 18. The Welcome panel

You can disable the InstallationCheck phase if you do not have the right graphics tablet. First, bring up the check for the tablet into the Requirements Editor (see Figure 3). Then change the check results from TRUE to FALSE.

Figure 19. When the IceCad tablet is absent

Let us assume that you do have the graphics tablet. Click the Continue button to switch to the Destination Select panel (Figure 20). Note the panel presents two possible locations for the payload. For this test, select the first location on the list. Click Continue to proceed to the Custom Install panel.


Sometimes, the package will not display the Destination Select panel, proceeding instead to the next panel. This happens even if there are several mounted volumes and the package allows users to choose one of the volumes as the target. This appears to be a bug in version 3.0.1 of the Installer utility. It is unknown if this same bug is present in later versions.

Figure 20. Choosing a destination

On the Custom Install panel (Figure 21), you will see a list of three payload choices. Note the second choice, TabletApp, is disabled and unselected. In this case, the host system happens to be Leopard (10.5). If the host uses Tiger (10.4), the TabletApp choice will be both enabled and selected by default.

Leave the selections as is and click the Install button. First, the package prompts you to authenticate the install session. Then it installs the two selected payloads onto their respective locations. Once it displays the Conclusion panel, choose Quit Installer from the Installer menu. Switch to the Finder and locate the /Applications directory. In there, you will find the utility Macally Now go to the directory /System/Library/Extensions. Here, you will find the kernel extension TabletDrv.kext. Select each installed payload and choose Get Info from the File menu. Examine the UID, GID, and permission flags for each payload. They should match the ones you have set in the Contents panel for each payload.

Finally, go to the directory /Library/Receipts. Here, you will find two receipt bundles, one for each installed payload. Now if you built package using the new flat-file format, you will not find any receipts for your payloads. Instead, the Installer tool will log the session in its private database named areceipt.db. This makes verifying and undoing an installation more challenging. But that is a topic for another time.

Figure 21. A list of payloads

Concluding Remarks

Special payloads need extra handling when added to an installer package. Otherwise, they may cause problems in the target if they are installed incorrectly. Some payloads need to be in the right location on the target. Some need the right hardware present. Some must have the right permissions set, others the right UID and GID. PackageMaker 3 gives you the means to address these needs. You can set the right permissions, UID, and GID of each payload via the Contents panel. You can use the Requirements Editor to add a simple hardware check or an external script to do complex checks. And you can set the right location and restart action on each payload's Configuration panel.

In the next article, I will explore the concept of an installer plug-in. I will show how to write a simple plug-in and add it to an installer package. Until then, I bid you well.

Bibliography and References

Apple Computers. PackageMaker Users Guide. 2007 Jul 23. Copyright 2007. Apple Computers, Inc. Online:

Apple Computers. Software Delivery Guide. 2006 Jul 24. Copyright 2007. Apple Computers, Inc. Online:

Apple Computers. "IORegistry Class Reference". Installer JavaScript Reference. 2007 Jul 23. Copyright 2007. Apple Computers, Inc. Online:

Apple Computers. "The I/O Registry Explorer". I/O Kit Fundamentals. 2007 May 17. Copyright 2001-2007. Apple Computers, Inc. Online:>

Apple Computers. "Installing Your Framework". Framework Programming Guide. 2006 Nov 07. Copyright 2007. Apple Computers, Inc. Online:

JC is a freelance engineering writer from North Vancouver, British Columbia. He spends his time writing technical articles; tinkering with Cocoa, REALbasic, and Python; and visiting his foster nephew. He can be reached at


Community Search:
MacTech Search:

Software Updates via MacUpdate

NTFS 14.3.318 - $19.95
This latest version supports the new macOS 10.12 Sierra! NTFS breaks down the barriers between Windows and OS X. Paragon NTFS effectively solves the communication problems between the Mac system and... Read more
iFFmpeg 6.2.2 - 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
ForeverSave 2.1.6 - Universal auto-save...
ForeverSave auto-saves all documents you're working on while simultaneously doing backup versioning in the background. Lost data can be quickly restored at any time. Define your preferred time... Read more
BetterTouchTool 1.961 - Customize Multi-...
BetterTouchTool adds many new, fully customizable gestures to the Magic Mouse, Multi-Touch MacBook trackpad, and Magic Trackpad. These gestures are customizable: Magic Mouse: Pinch in / out (zoom... Read more
EtreCheck 3.1.4 - For troubleshooting yo...
EtreCheck is an app that displays the important details of your system configuration and allow you to copy that information to the Clipboard. It is meant to be used with Apple Support Communities to... Read more
Together 3.7 - Store and organize all of...
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
Together 3.7 - Store and organize all of...
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
EtreCheck 3.1.4 - For troubleshooting yo...
EtreCheck is an app that displays the important details of your system configuration and allow you to copy that information to the Clipboard. It is meant to be used with Apple Support Communities to... Read more
Postbox 5.0.9 - Powerful and flexible em...
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
DiskCatalogMaker 6.5.16 - Catalog your d...
DiskCatalogMaker is a simple disk management tool which catalogs disks. Simple, light-weight, and fast. Finder-like intuitive look and feel. Super-fast search algorithm. Can compress catalog data... Read more

Latest Forum Discussions

See All

Silent Depth Submarine Simulation (Game...
Silent Depth Submarine Simulation 1.0 Device: iOS Universal Category: Games Price: $7.99, Version: 1.0 (iTunes) Description: | Read more »
Enneas Saga lets you lead your own demon...
Defend the land of Enneas Continent from the forces of evil in the new fantasy MMORPG from Lyto Mobi: Enneas Saga. Can’t wait? No problem. It’s available to download now on Android devices. | Read more »
Great zombie games in the spirit of Dead...
Dead Rising 4 arrives tomorrow, giving enthusiasts a fresh chance to take selfies with zombies and get up to other ridiculous end-of-the-world shenanigans. To really get into the spirit of things, we've gone and gathered the best zombie games that... | Read more »
Amateur Surgeon 4 Guide: Advanced tips a...
Amateur Surgeon 4 is still tackling the competition at the top of the App Store charts, so if you haven't tried it out yet, you should probably do that right away. If you've been at it for a while, though, perhaps you're ready to start expanding... | Read more »
Amateur Surgeon 4 Guide: Become the worl...
It's time to wield your trusty pizza cutter again, as Amateur Surgeon has returned with a whole fresh set of challenges (and some old, familiar ones, too). Starting anew isn't easy, especially when all you have at your disposal is a lighter, the... | Read more »
Le Parker: Sous Chef Extraordinaire (Ga...
Le Parker: Sous Chef Extraordinaire 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: | Read more »
Telltale Games really is working on a Gu...
Telltale Games' next episodic adventure is indeed Guardians of the Galaxy. A document tied to the voice actors strike suggested that the project was in the work, but now we have direct confirmation following an announcement at the Game Awards that... | Read more »
Amateur Surgeon returns to iOS and Andro...
Amateur Surgeon and its two sequels disappeared from the App Store some time and it was sad days for all. But now, just in time for the holidays, the Adult Swim favorite makes its joyous return in the shape of Amateur Surgeon 4, a remake with... | Read more »
The best board games on mobile
Sometimes you need to ditch all of the high speed, high action games in favor of something a little more traditional. If you don't feel like parting ways from your mobile device, though, there are still plenty of ways to get that old-school fix.... | Read more »
The best Facebook Messenger Instant Game...
Facebook's new Instant Games is now here, meaning you can play games with your friends directly via Facebook. It's a fun new way to connect with friends, of course, but it's also proving to be a solid gaming experience in its own right, with a... | Read more »

Price Scanner via

Slate Tablet Market Share to Fall Below 75% i...
After two years of decline, the tablet market is showing signs of new life as productivity trumps entertainment, and tablets become cost-effective computing devices for both entertainment and... Read more
Yostand Launches Indigogo campaign for iStand...
China-based startup Yostand (meaning ‘your stand’), has announced the launch of its Indigogo campaign for their newly awaited iStand7. This product is a one of a kind iPhone battery case that offers... Read more
Green App – Budget Forecasting Now Available...
Indianapolis, Indiana based CoopToons has announced the release of Green – Budget Forecasting 1.5, an update to their personal budgeting app developed exclusively for iOS devices. Green aims to be a... Read more
New 2016 13-inch 2.0GHz MacBook Pros in stock... has the non-Touch Bar 13″ MacBook Pros in stock today for $150 off MSRP. Shipping is free: - 13″ 2.0GHz MacBook Pro Space Gray (MLL42LL/A): $1349.99 $150 off MSRP - 13″ 2.0GHz MacBook... Read more
15-inch 2.6GHz Silver Touch Bar MacBook Pro o...
Adorama has the new 2016 15″ 2.6GHz Silver Touch Bar MacBook Pro (MLW72LL/A) in stock and available for $2349 including free shipping. Adorama charges sales tax in NY & NJ only. Their price is $... Read more
13-inch MacBook Airs on sale for up to $180 o... has 13″ MacBook Airs on sale for up to $180 off MSRP including free shipping: - 13″ 1.6GHz/128GB MacBook Air (MMGF2LL/A): $869.99 $130 off MSRP - 13″ 1.6GHz/256GB MacBook Air (sku... Read more
13-inch 2.5GHz MacBook Pro (Apple refurbished...
Apple has Certified Refurbished 13″ 2.5GHz MacBook Pros (MD101LL/A) available for $829, or $270 off original MSRP. Apple’s one-year warranty is standard, and shipping is free: - 13″ 2.5GHz MacBook... Read more
Monday roundup of Holiday Mac sales: Up to $3...
Take up to $300 off MSRP on the price of a new Apple Mac at B&H Photo today as part of their Holiday sale. Shipping is free, and B&H charges NY sales tax only. Touch Bar MacBook Pros are in... Read more
12-inch WiFi Apple iPad Pros on sale for up t...
B&H Photo has 12″ WiFi Apple iPad Pros on sale for up to $50 off MSRP, each including free shipping. B&H charges sales tax in NY only: - 12″ Space Gray 32GB WiFi iPad Pro: $749 $50 off MSRP... Read more
9-inch Apple WiFi iPad Pros on sale for $20-$...
B&H Photo has 9.7″ Apple WiFi iPad Pros on sale for $20-$50 off MSRP, each including free shipping. B&H charges sales tax in NY only: - 9″ Space Gray 256GB WiFi iPad Pro: $779.95 $20 off MSRP... 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
Lead *Apple* Solutions Consultant - Apple (...
# Lead Apple Solutions Consultant Job Number: 53586123 Pittsburgh, Pennsylvania, United States Posted: Nov. 28, 2016 Weekly Hours: 40.00 **Job Summary** The Lead ASC Read more
*Apple* Retail - Multiple Positions- Plano,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
*Apple* Retail - Multiple Positions- Kansas...
Job Description:SalesSpecialist - Retail Customer Service and SalesTransform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
*Apple* Retail - Multiple Positions- Chicago...
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.