TweetFollow Us on Twitter

Counting To X

Volume Number: 15 (1999)
Issue Number: 3
Column Tag: ExplainIt

Counting to X

by Dave Evans and Mark Turner

Ten Steps Toward Carbon Compatibility

Carbon is the basic element in Apple's plan to take Mac OS applications into the next millennium. Together with Mac OS X, Carbon delivers exactly what developers have been asking for -; an easy way of allowing Mac applications to enjoy all the advantages of a memory protected, preemptively scheduled, multitasking operating system.

A preliminary version of the Carbon SDK has already been released to members of the Apple Developer Program, but even if you're not a member, there's a lot you can do now to make your transition to Mac OS X easier. And the good news is that these changes will also provide a better experience for your customers running Mac OS 8. In this article we'll discuss ten steps you can take to prepare for Carbon. But first, a brief overview of Carbon and why it's important that you prepare for it now.

Carbon Defined

Carbon is a set of APIs that run on both Mac OS 8 and Mac OS X. It's a hybrid that includes over 70 percent of the existing Mac OS APIs, covering about 95 percent of the functions used by applications. Because it includes most of the functions you rely on today, converting to Carbon is relatively painless. And by weeding out or modifying certain difficult-to-support functions, Carbon provides a more streamlined and stable base for application development.

What this means for you is that by making a small investment in Carbon, your programs will gain these benefits when running under Mac OS X:

  • Greater stability.
    Preemptive multitasking and protected address spaces will help prevent other people's bugs from crashing your application. (It goes without saying that there are no bugs in your code!)
  • Improved responsiveness.
    Because all applications are guaranteed processing time through preemptive scheduling, you don't have to worry about being locked out by another program that's hogging the CPU. And since Mac OS X and Carbon are 100% PowerPC native, there's no 68K emulation and no mode-switching overhead to slow down your applications.
  • Efficient use of system resources.
    Your application isn't limited to a fixed heap size and can dynamically allocate memory and other system resources based on actual needs rather than predetermined values.

Although your current applications will continue to run unmodified in Mac OS X through a technology code-named the Blue Box, they won't enjoy all the performance and reliability enhancements of Mac OS X until you update them for Carbon.

That all sounds great, but the best part is that you don't have to wait for Mac OS X to appreciate the benefits of Carbon. By cleaning up old code and adopting Carbon-compatible APIs, your applications will run more reliably on today's Mac OS while taking advantage of the latest Apple technologies and human interface improvements.

Nothing's free in this world, and Carbon is no exception. It'll cost you about two weeks work to update a typical application. But by preparing for Carbon now, your applications will not only run better on Mac OS 8, they'll be ready to rock when Mac OS X rolls out later this year.

Carbon Coding

Okay, time to roll up your sleeves, fire up your Mac, and give your app a tune-up.

I. Read the Carbon Paper

Before you change a single line of code, you should read Transitioning to Mac OS X: An Overview of the Carbon Programming Interface. This white paper explains why Carbon is so important, and defines Apple's goals for the project. It also lists the expected level of support for all existing Mac OS APIs. You'll find the Carbon Paper, and a lot of other helpful information, on the Carbon web site at http://developer.apple.com/macosx/carbon/.

While you're visiting the web site, be sure to check out the official Carbon Specification for the most up-to-date list of supported APIs. Then download the Carbon Dater tool, because we're going to talk about it next.

II. Run Carbon Dater

If you completed Step I, you already know that Apple's Carbon Dater tool provides a detailed report of your code's current Carbon compliance level. (If you didn't follow Step I, shame on you! Go back and read the Carbon Paper.) Carbon Dater works by examining PEF containers in application binaries and CFM libraries. It compares the list of Mac OS symbols your code imports against Apple's database of Carbon-supported functions and issues a spiffy report formatted in HTML.

In addition to analyzing your Mac OS function calls, Carbon Dater tries to identify any attempts to read or write directly to low-memory, and it also reports if any of your resources have the system heap bit set. Carbon applications don't have access to the system heap in Mac OS X, so you can't load resources there.

As we discuss in Step IV, all access to low-memory system global data must be through accessor functions. Because many of today's accessor functions are simply macros that implement a load or store to memory, Carbon Dater can't determine if your low-memory accesses are illegal -; it's up to you to make sure you're using the proper functions.

Apple is working very hard to make the Carbon transition an easy one, and the Carbon Dater statistics bear this out. As Figure 1 shows, of the thousands of applications tested, the average compliance level is over 95 percent.


Figure 1. Carbon Dater Results

For step-by-step instructions on running Carbon Dater and interpreting the results, see the Getting Started column, Carbon: Getting Ready for Mac OS X, in the January 1999 issue of MacTech.

III. Use the Most Recent Universal Headers

Okay, so you've read up on Carbon, tested your application, and most likely discovered that it's pretty close to 95 percent compatible. What do you do next? Sync up with the latest Universal Header files!

You can start by downloading the current headers from Apple's web site. As of this writing, Apple has released version 3.2 of the Universal Headers, incorporating all the new technologies in Mac OS 8.5. In addition to new APIs, there are minor changes from previous 3.x versions. For example, the KeyMap definition has changed from an array of longs to an array of Uint32 values. Be sure to read the release notes for more information about what has changed.

After successfully building your application on the current headers, you should download and install the Carbon headers. The Carbon headers incorporate additional changes, including new conditionals to use when building Carbon applications and new APIs to replace some of the older functions that aren't supported in Carbon.

The Carbon headers eventually will be rolled into future versions of the Universal Headers, and you can use them for building non-Carbon applications today. To build a Carbon application, just add the following statement to one of your source files before including any of the Carbon headers:

#define TARGET_CARBON 1

The TARGET_CARBON conditional specifies that the included header files should allow only Carbon-compatible APIs and data structures. When you throw this switch and rebuild, you're likely to get a number of errors and warnings from the compiler. For now, stifle the urge to hack your way through those errors. You'll save yourself a lot of time if you read the rest of this article and address each issue methodically.

IV. Avoid Using Low-Memory Globals

Low-memory globals are system and application global data located below the system heap in Mac OS 8. They typically fall between the hexadecimal addresses $100 and $2800. Since the transition to PowerPC, Apple has provided accessor routines for getting and setting these global variables. Prior to that, you would simply dereference the absolute address of the global to modify it.

Carbon applications still have access to many of the low-memory globals, although in some cases the scope and impact of the global has changed. But in all cases, Carbon applications must use the supplied accessor routines to examine or change global variables. Attempting to access them directly with an absolute address will crash your application when running on Mac OS X.

The complete list of low-memory globals supported in Carbon hasn't been published yet, but you'll be better prepared if you take the time now to review your use of low memory. The transition to Carbon will be easier if you follow these guidelines:

  • Use high-level Toolbox calls instead of low-memory accessors whenever possible.
  • If a high-level call is not available, use an accessor function.
  • Rely on global data only from Toolbox managers supported in Carbon.

Make your best guess about the last point until Apple publishes a definitive list. For example, because the driver-related calls in the Device Manager are not supported in Carbon, low-memory accessors like LMGetUTableBase are not likely to be available. Similarly, direct access to hardware is not supported in Carbon, so calls like LMGetVIA will no longer be useful.

Some low-memory accessors have Toolbox equivalents -; applications must switch to these Toolbox calls instead. For example, use GetMouse instead of LMGetMouse, Ticks instead of LMGetTicks, and MemError instead of LMGetMemErr.

V. Go Native

Because Carbon requires 100% native PowerPC code, you must remove any dependencies on 68K instructions. Unless you have written your application entirely in assembly language, this should not be a big issue for your main application code. Where you are more likely to have 68K code is in custom definition procedures (defprocs) and plug-ins.

Custom defprocs (for example, MDEFs, CDEFs, and LDEFs) must be compiled as PowerPC code and no longer can be stored in resources. Carbon will introduce new variants of CreateWindow and similar calls (NewControl, NewMenu, etc.) that will take a universal ProcPtr for a definition procedure. Instead of providing a WDEF in a resource, you would instead call a new Toolbox routine that might look something like this:

OSStatus CreateCustomWindow(WindowClass windowClass, 
      WindowAttributes attributes, const Rect *bounds, 
      WindowDefUPP customProc, WindowPtr *outWindow);

For all Mac OS functions that expect definition procedures in resources today, there will be new routines to specify the custom procedure. But before you spend a lot of time updating old defprocs, you should think about whether there is any need to continue rolling your own interface elements. New APIs like the Appearance Manager and Navigation Services may provide all the features you want.

That said, if you want to compile custom defprocs into your code today, the following snippet shows a clever way to do it. This will not work in the future for Carbon applications on Mac OS X, but for a Mac OS 8 application, it will allow defprocs in native code using stub routines as shown here.

// Using a 6-byte stub WDEF resource (ID 128 for example),
// fill in a 680x0 'jmp' opcode and the address of a UPP
// to the native definition proc. Note: NewWindowDefProc
// will allocate memory in Mac OS 8.x

Handle theStub;
theStub = GetResource('WDEF', 128);
if (theStub && *theStub)
{
   WindowDefUPP theProcUPP;

   theProcUPP = NewWindowDefProc(&MyWDEF);
   *((long *) (*theStub + 2)) = theProcUPP;
   *((short *) *theStub) = 0x4EF9;

   // We just modified code, flush the emulator cache
   FlushCodeCacheRange(*theStub, 6);
}

VI. Get Used to Opaque Toolbox Data Structures

Some familiar Toolbox data structures are not directly accessible in Carbon. There are new functions to inspect the contents of these opaque structures. For example, you can no longer dereference a CGrafPtr to inspect the contents of the GrafPort structure. Instead of addressing a port bounds rectangle directly with &myport->bounds, you must call the new routine GetPortBounds(myport, &myrect) with a local variable for the result. For each accessible element of an opaque data structure there is a corresponding new routine for getting or setting that element.

Supporting opaque Toolbox structures likely will take some work in your code. To begin with, you probably will have to create new local variables for return results. Almost all accessor functions return a copy of the data and not a pointer to the actual data. This passing of data by value instead of by reference requires that you allocate space for results either in memory or as local variables on the stack. For efficiency, you should place calls to accessors strategically in your code and use them minimally.

Window records are opaque in Carbon, and are not just extended versions of GrafPorts. Windows and ports are no longer synonymous, and code that treats them interchangeably will crash on Mac OS X. For example, the following statement casts a WindowPtr to a GrafPtr:

SetPort( (GrafPtr) myWindow );          // don't do this!

Look familiar? Code like this will cause you grief in the future because your program will compile and run just fine on Mac OS 8 but crash on Mac OS X. The right way to get the port for a window is with the GetWindowPort function, like this:

SetPort( GetWindowPort( myWindow ));   // do this instead

Another practice to avoid is hanging your own data off the end of Toolbox structures. For example, because the internal representation of a window record is no longer visible, you can't save private data by adding it to the end of the window record and passing a pStorage value to NewWindow. In Carbon, you must pass NULL in the pStorage field. If you need extra storage for windows, keep a reference to your data in the refCon field. If you are currently using pStorage in this way, switching to refCon is something you can do today to prepare for Carbon.

The upside to these changes is that Apple can take steps to ensure that the internal representation of data is aligned in memory for fastest access, and new elements can be added for Carbon-specific features. With opaque data structures in Carbon, the Toolbox easily can be extended in the future.

Not all data structures are opaque in Carbon, though. TextEdit data in a TERecord, for example, still is directly accessible. The Apple Event AEDesc structure also is directly accessible, but the type of the dataHandle in the structure is opaque. Some data structures were not made opaque because they're so simple, like the AEDesc structure, and others because the Toolbox component is not expected to change in the future. This is why the TERecord is not opaque, as TextEdit will be replaced outright by a Unicode aware text engine.

VII. Adopt Supported Technologies

A number of Mac OS functions are not being carried forward in Carbon. For these you must adopt Apple's suggested replacement functions or find other ways of accomplishing those functions. Carbon is a work in progress, and you may run across a few APIs that are listed as unsupported in Carbon but for which replacement APIs or workarounds are not yet defined. If you feel strongly that Apple should support an API that is listed as unsupported or under evaluation in the Carbon Specification, make your voice heard by sending e-mail to <carbon@apple.com>.

Three important Carbon-supported technologies that you should adopt today are the Appearance Manager, Navigation Services, and Open Transport. The Appearance Manager coordinates the look and feel of the Mac OS human interface and provides a rational and supported API for adding custom interface elements.

Navigation Services replaces the venerable Standard File Package, and is shipping now in Mac OS 8.5. Using sample code provided in the Navigation Services SDK (available on Apple's web site), we were able to replace all the Standard File calls in AppleWorks in one day. You also should read Keith Mortensen's excellent article on the subject in the August 1998 issue of MacTech.

Open Transport replaces MacTCP and classic AppleTalk in Carbon. If you have not already adopted OT, now is definitely the time. First introduced in System 7.5.2, Open Transport has evolved into a mature, efficient, and extensible networking architecture capable of saturating 100Mbit Ethernet.

VIII. Don't Patch Traps

You cannot patch traps in Mac OS X for one simple reason: there is no trap table. Because the operating system is PowerPC native, no 68K trap table is needed. Unlike Mac OS 8, most calls to Mac OS X Toolbox functions are implemented as a jump directly to the specified routine. In Mac OS 8 you can patch traps to intercept Toolbox calls and modify their behavior, but with no central dispatch mechanism to hook into, this is not possible in Mac OS X.

Consequently, GetTrapAddress, SetTrapAddress, and related functions are not available in Carbon. You can, of course, conditionalize your code and continue to patch traps when running under Mac OS 8, but your programs will be much easier to maintain if you avoid patching entirely.

Apple is considering a variety of mechanisms to allow programmatic extensibility. The goal is to provide you with system-level APIs for altering certain default behaviors. If you have suggestions or specific requirements that you would like Apple to support, send them to <carbon@apple.com>.

For now you should take a close look at any trap patches in your code and ask yourself if they could be replaced with another approach. Instead of patching ExitToShell, for example, try using a CFM termination proc for your main fragment.

IX. Draw Only Within Your Own Windows

Because Mac OS X is a truly preemptive system, any number of applications may be drawing into their windows at the same time. And of course, a user may be dragging a window or other object around the screen while background applications are drawing in their windows. In order to make all this work, Carbon applications must play by these rules:

First, you should no longer try to draw outside of your windows. In the past you could call the GetWMgrPort function and use that port to draw anywhere on the screen. This port no longer exists in Mac OS X. If you were using this technique for custom dragging or zooming feedback, use DragWindow or other Drag Manager functions instead.

Second, if you draw directly into the bitmap of your windows (without using QuickDraw) you must wrap those blits with two new calls that will tell the Window Manager to get out of the way. We are still working on these functions, so for now you might just want to insert some comments to remind you that you eventually must update this kind of code for Carbon.

X. Manage Memory Efficiently

Memory management does not change much for Carbon applications running on Mac OS 8. You will need all the code you use today to manage heap fragmentation, low memory situations, and stack depth.

However, there are some things you must do to perform well when running in a Mac OS X environment. In that world, your application will run in a very different heap structure with different allocation behavior. Your memory will not tend to move as much and your stack will be far away from your heap, with guard pages below it. The most significant change you must make is in determining amounts of free memory and stack space available.

In the future, when your Carbon application is intended to run only on Mac OS X, you will be able to take full advantage of new memory behavior. You might switch from handle-based to pointer-based allocations, for example. But as long as your application runs on Mac OS 8, you should prepare for the same issues you always have.

The functions FreeMem, PurgeMem, MaxMem, and StackSpace are all available in Carbon. You should, however, think about how and why you are using them. You will probably want to consider additional code to better tune your performance.

The FreeMem, PurgeMem, and MaxMem functions behave as expected when your Carbon application is running on Mac OS 8, but they are almost meaningless when it is running on Mac OS X, where you have essentially unlimited virtual memory. Although you can still use these calls to ensure that your memory allocations will not fail, you should not use them to allocate all available memory. Allocating too much virtual memory will cause excessive page faults and reduce system performance. Instead, determine how much memory you really need for your data, and allocate that amount.

Before Carbon you would use the StackSpace function to determine how much space was left before the stack collided with the heap. This routine could not be called at interrupt time, but was useful for preventing heap corruption in code using recursion or deep call chains. But, since a Carbon application may have different stack sizes under Mac OS 8 and Mac OS X, the StackSpace function is no longer very useful. You should not rely on it for your logic to terminate a recursive function. It might still be useful as a safety check to prevent heap corruption, but for terminating runaway recursion you should consider passing a counter or the address of a stack local variable instead of calling StackSpace.

The Carbon API does not include any subzone creation or manipulation routines. If you use subzones today to track Toolbox or plug-in memory allocations, you will have to use a different mechanism. For plug-ins, you might switch to using your own allocator routines. To prevent leaks of Toolbox data, make sure all Toolbox allocations are matched with the appropriate dispose calls.

The Carbon API also removes the definition of zone headers. You no longer can modify the variables in a zone header to change the behavior of Toolbox routines like MoreMasters. Simply call MoreMasters multiple times instead, which will allocate 128 master pointers each time.

Summary

Everything you do now to make your application run great on Mac OS 8 is a step toward Carbon compatibility. Adopting the Appearance Manager, Navigation Services, and Open Transport is a great way to start. And by following the steps outlined in this article, your transition to Carbon will be that much easier.

While it has been our experience that a typical application can be "Carbonized" in a couple of weeks, a lot depends on how zealously you have followed Apple's programming recommendations in the past. If you have not cracked a copy of Inside Macintosh in a couple of years, or do not remember the last time you synchronized with Apple's latest header release, it might take you a bit longer to whip your code into shape. All the more reason to get started early!


Dave Evans is an engineer on the Carbon team and Mark Turner is a technical writer at Apple Computer.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

calibre 2.69.0 - Complete e-book library...
Calibre is a complete e-book library manager. Organize your collection, convert your books to multiple formats, and sync with all of your devices. Let Calibre be your multi-tasking digital librarian... Read more
Evernote 6.9.1 - Create searchable notes...
Evernote allows you to easily capture information in any environment using whatever device or platform you find most convenient, and makes this information accessible and searchable at anytime, from... Read more
jAlbum Pro 13.5 - Organize your digital...
jAlbum Pro has all the features you love in jAlbum, but comes with a commercial license. You can create gorgeous custom photo galleries for the Web without writing a line of code! Beginner-friendly... Read more
jAlbum 13.5 - Create custom photo galler...
With jAlbum, you can create gorgeous custom photo galleries for the Web without writing a line of code! Beginner-friendly, with pro results - Simply drag and drop photos into groups, choose a design... Read more
Google Chrome 53.0.2785.143 - Modern and...
Google Chrome is a Web browser by Google, created to be a modern platform for Web pages and applications. It utilizes very fast loading of Web pages and has a V8 engine, which is a custom built... Read more
Chromium 53.0.2785.143 - Fast and stable...
Chromium is an open-source browser project that aims to build a safer, faster, and more stable way for all Internet users to experience the web. Version 53.0.2785.143: [Security Fix] High CVE-2016-... Read more
QuickBooks 2015 16.1.7.1524 R8 - Financi...
Save 20% on QuickBooks Pro for Mac today through this special discount link QuickBooks 2015 helps you manage your business easily and efficiently. Organize your finances all in one place, track... Read more
Sierra Cache Cleaner 11.0.1 - Clear cach...
Sierra Cache Cleaner is an award-winning general purpose tool for macOS X. SCC makes system maintenance simple with an easy point-and-click interface to many macOS X functions. Novice and expert... Read more
Default Folder X 5.0.7 - Enhances Open a...
Default Folder X attaches a toolbar to the right side of the Open and Save dialogs in any OS X-native application. The toolbar gives you fast access to various folders and commands. You just click on... Read more
Safari Technology Preview 10.1 - The new...
Safari Technology Preview contains the most recent additions and improvements to WebKit and the latest advances in Safari web technologies. And once installed, you will receive notifications of... Read more

Pumped BMX 3: Beginner tips and tricks
There’s a whole lot more to Pumped BMX 3 than meets the eye. Your goal is to perform a wide array of sweet flips and tricks, but that’s easier said than done. It takes well practiced timing and coordination, and the game doesn’t really explain that... | Read more »
Cybird’s latest release - BFB Champions...
Launched in the UK in early September, BFB Champions’ newest update is loaded with great new features, and looks set to outshine the original version by taking it out of soft launch and giving it a new lease of life. | Read more »
3 apps to boost your focus
As someone who works from home, my workspace is a minefield of distraction. Cats, tasty snacks, the wind blowing past my window, that cleaning that I suddenly can’t put off any longer. If I let distraction takes its course, I find that soon half... | Read more »
Pumped BMX 3 (Games)
Pumped BMX 3 1.0 Device: iOS Universal Category: Games Price: $3.99, Version: 1.0 (iTunes) Description: The final instalment of the smash hit #1 rated BMX game is here! Following on from the insane success of Pumped BMX 2, Pumped 3... | Read more »
4 games like Burly Men at Sea to inspire...
Burly Men at Sea is out today and it looks a treat. It tells the tale of three Scandinavian fishermen who leave the humdrum of their daily lives to go exploring. It’s a beautiful folksy story that unfurls as you interact with the environment... | Read more »
3 reasons you need to play Kingdom: New...
Developed by a tag team of indie developers - Thomas "Noio" van den Berg and Marco "Licorice" Bancale - Kingdom is a vibrant medieval fantasy adventure that casts players as a king or queen who must expand their empire by exploring the vasts lands... | Read more »
JoyCity have launched a brand new King o...
Great news for all of you Game of Dice fans out there - JoyCity have just released a brand new limited edition pack with a really cool twist. The premise of Game of Dice is fairly straightforward, asking you to roll dice to navigate your way around... | Read more »
Burly Men at Sea (Games)
Burly Men at Sea 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: Burly Men at Sea is a folktale about a trio of large, bearded fishermen who step away from the ordinary to seek adventure. | Read more »
3 tips for catching the gnarliest waves...
Like a wave breaking on the shore, Tidal Rider swept its way onto the App Store charts this week settling firmly in the top 10. It’s a one-touch high score-chaser in which you pull surfing stunts while dodging seagulls and collecting coins. The... | Read more »
The beginner's guide to destroying...
Age of Heroes: Conquest is 5th Planet Games’ all new turn-based multiplayer RPG, full of fantasy exploration, guild building, and treasure hunting. It’s pretty user-friendly as far as these games go, but when you really get down to it, you’ll find... | Read more »

Price Scanner via MacPrices.net

CAZE Annouces New Zero 5 Case for Jet Black i...
Hong Kong basd CAZE has announced Zero 5 case for iPhone 7/ 7 Plus, one of the world’s thinnest clear hard cases, measuring just 0.5 millimeters. CAZE has been producing and improving the Zero 5... Read more
Nest Egg Inventory App for iOS Offers Conven...
Campbell, California based Winprogger LLC has announced the release and immediate availability of Nest Egg – Inventory 4.1.22, an important update to their easy-to-use, yet comprehensive inventory... Read more
Factor4, LLC Launches Apple iOS and Android G...
Factor4, LLC, which offers gift and loyalty services to the SMB marketplace, has released free mobile applications that enable merchants to process via all Apple and Android devices. The Apple and... Read more
15-inch Retina MacBook Pros on sale for $200...
B&H Photo has 15″ Retina Apple MacBook Pros on sale for $200 off MSRP. Shipping is free, and B&H charges NY tax only: - 15″ 2.2GHz Retina MacBook Pro: $1799 $200 off MSRP - 15″ 2.5GHz Retina... Read more
Apple refurbished iMacs available for up to $...
Apple has Certified Refurbished 2015 21″ & 27″ iMacs available for up to $350 off MSRP. Apple’s one-year warranty is standard, and shipping is free. The following models are available: - 21″ 3.... Read more
Check Apple prices on any device with the iTr...
MacPrices is proud to offer readers a free iOS app (iPhones, iPads, & iPod touch) and Android app (Google Play and Amazon App Store) called iTracx, which allows you to glance at today’s lowest... Read more
Apple price trackers, updated continuously
Scan our Apple Price Trackers for the latest information on sales, bundles, and availability on systems from Apple’s authorized internet/catalog resellers. We update the trackers continuously: - 15″... Read more
Apple refurbished 2016 13-inch MacBook Airs a...
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: - 2016 13″ 1.6GHz/8GB/128GB MacBook... Read more
1.4GHz Mac mini on sale for $449, save $50
Adorama has the 1.4GHz Mac mini on sale for $50 off MSRP including free shipping plus NY & NJ sales tax only: - 1.4GHz Mac mini (Apple sku# MGEM2LL/A): $449 $50 off MSRP To purchase a mini at... Read more
Apple refurbished 2015 13-inch MacBook Airs a...
Apple has Certified Refurbished 2015 13″ MacBook Airs available starting at $759. An Apple one-year warranty is included with each MacBook, and shipping is free: - 2015 13″ 1.6GHz/4GB/128GB MacBook... Read more

Jobs Board

Systems Architecture Prototyping - *Apple*...
Changing the world is all in a day's work at Apple . If you love innovation, here's your chance to make a career of it. You'll work hard. But the job comes with more Read more
*Apple* Retail - Multiple Positions- Akron,...
Job Description:SalesSpecialist - Retail Customer Service and SalesTransform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
Hardware Design Validation Engineer - *Apple...
Changing the world is all in a day's work at Apple . If you love innovation, here's your chance to make a career of it. You'll work hard. But the job comes with more Read more
Systems Architecture Prototyping - *Apple*...
Changing the world is all in a day's work at Apple . If you love innovation, here's your chance to make a career of it. You'll work hard. But the job comes with more Read more
*Apple* Retail - Multiple Positions- South B...
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.