TweetFollow Us on Twitter

Aug 99 Getting Started

Volume Number: 15 (1999)
Issue Number: 8
Column Tag: Getting Started

Printing

By Dan Parks Sydow

How a Mac program sends document data to a printer

In the previous few Getting Started articles we've focused on the use of files to provide users of your Macintosh applications with the means to save program output. This month we'll look at a second data-saving technique - printing. By adding printing capabilities to your program, both text and graphics can be sent to any printer that's attached to the user's computer.

Printing Basics

In this article you'll see how to write a program that displays the two standard printing dialog boxes found in most Mac programs. The Printing Style dialog box, shown in Figure 1, allows the user to select page preferences such as page orientation. The Printing Job dialog box, pictured in Figure 2, lets the user specify the print quality and the page range. For reasons explained ahead, the dialog boxes you see on your Mac may look somewhat different than the ones shown here.



Figure 1.A typical Printing Style dialog box.



Figure 2.A typical Printing Job dialog box.

Your program can display both the Printing Style and Printing Job dialog boxes through the use of Printing Manager routines. Like other Toolbox managers, the Printing Manager is a collection of system software routines. Unlike the other managers, the code that makes up each Printing Manager routine isn't found in ROM or in the System File. Rather, the Toolbox printing routines are nothing more than empty shells, or stub routines. When your application makes a call to a Toolbox printing function, the program is directed to code that exists in a printer resource file. Printer resource files enable the Printing Manager to work with all printers that come with a Macintosh printer driver.

When an application calls a routine from a manager other than the Printing Manager, the program jumps to Toolbox code that originates in ROM or in the System File. The code that makes up that one routine - whatever routine it is - is then carried out. If the call is to, say, Line(100, 0), QuickDraw draws a line 100 pixels long to the current port. This is true regardless of the kind of monitor hooked up to the Mac. For printers, this “one generic code works on all” principle doesn't apply. There are countless third-party printers that can be hooked up to a Macintosh, and no uniform standard of how Toolbox calls should be handled by a printer. So Apple leaves it up to the manufacturer of each printer to supply the code that makes the printing functions work. This code is found in the printer resource file that accompanies a printer that is Mac-compatible.

Every printer that works with a Macintosh comes supplied with a printer resource file. This file, which is placed in the Extensions folder in the System Folder, holds the code that actually carries out Printing Manager routines. The file, which has a name that often includes the name of the printer, must be present in order for the printer to function. Since each type of printer has its own printer resource file, and since a Macintosh can have more than one printer connected to it, a Mac can have more than one printer resource file. The printer (and thus the printer resource file) that a Macintosh uses is governed by the Chooser program found under the Apple menu.

The printer resource file holds resources of several types. Resources of type PDEF are printer definition functions - they hold the compiled code that executes when a Printing Manager function is called. When a Mac application makes a call to a Printing Manager routine the call is routed to the printer resource file. There, the code that makes up one of the many PDEF resources is loaded and executed. By having each printer manufacturer support all the same Printing Manager routines, the burden of worrying about which printer is connected to a user's system is lifted from the Macintosh software developer. When you write an application that calls Printing Manager routines, you won't have to consider the type of printer that any one user might have. Instead, just make the function call. It will be up to the printer resource file to handle that function call as is appropriate for that printer.

Printing Manager Basics

Like all of the Toolbox managers, the Printing Manager consists of a wealth of functions. But to get started with printing, you'll need to use only a handful of them.

The Print Record

Before printing, your application must create a print record. This record holds information specific to the printer being used, such as its resolution, and information about the document that is to be printed, such as scaling, page orientation, and the number of copies to print.

In C, the print record is represented by a struct of the type TPrint. Before any printing takes place, your application must allocate memory for a TPrint structure and obtain a handle - a THPrint handle - to that memory. By the way, the T in THPrint stands for type, and the H stands for handle - you'll see this notation used throughout the functions of the Printing Manager. You can make a call to the Memory Manager routine NewHandle() or NewHandleClear() to reserve the needed memory and to receive a handle to that memory. Include the size of a print record as the parameter and cast the returned generic pointer to a THPrint handle.

THPrint	printRecord;
printRecord = (THPrint)NewHandleClear( sizeof (TPrint) );

After creating a new print record, call the Printing Manager routine PrintDefault() to fill the record with default values. These values will serve as initial values until the user selects Page Setup and Print from the File menu of your application. The values entered in the corresponding dialog boxes will overwrite some or all of the values supplied by PrintDefault().

PrintDefault( printRecord );

Printing Manager Functions

Knowledge of less than a dozen Printing Manager functions is all that's needed to get your Mac application printing. As you read this section, note that each of the three Open functions is paired with a Close function: calls to PrOpen(), PrOpenDoc(), and PrOpenPage() are balanced with calls to PrClose(), PrCloseDoc() and PrClosePage(), respectively.

The code to execute Printing Manager functions resides in a resource file, so your program needs to open this resource file before its code can be accessed. The Printing Manager function PrOpen() prepares the current printer resource file for use. The current printer is whichever printer was last selected in the Chooser. Preparation consists of opening both the Printing Manager and the printer resource file for the current printer. When finished with the resource file, a call to PrClose() closes the Printing Manager and the printer resource file.

PrOpen();
// printing-related code here
PrClose();

PrOpenDoc() initializes a printing graphics port. This graphics port isn't associated with any window - it's associated with the printer. When a window's graphics port is current (by way of a call to SetPort()), drawing takes place on the screen. When a printing graphics port is current (by way of a call to PrOpenDoc()), drawing operations are routed to the printer. Once a printing graphics port is current, all QuickDraw commands are sent to the printer.

When passed a handle to a print record, PrOpenDoc() allocates a new printing graphics port and returns a TPPrPort to the application. The TPPrPort is a pointer to a printing graphics port. PrOpenDoc() requires a second and third parameter, each of which can normally be set to nil. The second parameter can be used when an application wants to pass in a pointer to an existing printing graphics port, and the third parameter can be used to allocate a particular area in memory to serve as an input and output buffer.

PrCloseDoc() closes a printing graphics port. Make a single call to PrCloseDoc() after the last page of a document has been sent to the printer. Pass PrCloseDoc() the pointer to the printing graphics port that was returned by PrOpenDoc().

TPPrPort	printerPort;
printerPort = PrOpenDoc( printRecord, nil, nil );
// print page(s) here
PrCloseDoc( printerPort );

PrOpenPage() is used to begin printing a single page of a document. Pass PrOpenPage() the pointer to the printing graphics port that was obtained in the PrOpenDoc() call. The second parameter is used only for deferred printing - a delayed printing feature that is normally used only on older printers. You can usually set this parameter to nil. After a call to PrOpenPage() is made, all the QuickDraw commands necessary to output one page of a document should be made. After that, call PrClosePage().

PrClosePage() signals the end of the current page. Once a call to PrClosePage() is made, the Printing Manager will stop accumulating QuickDraw calls. PrClosePage() requires a single parameter - the pointer to the printing graphics port that was returned by PrOpenDoc().

PrOpenPage( printerPort, nil );
// QuickDraw calls that define what's to be printed
PrClosePage( printerPort );  

Before printing, you'll want to give the user the opportunity to specify printing style options. A call to PrStlDialog() displays a Printing Style dialog box that allows the user to do just that. If your application has a Page Setup menu item, make a call to PrStlDialog() in response to a user's selection of this menu item. The Printing Style dialog box is defined in the resource file of the printer driver, so its exact look is dependent on the printer in use - this is why a Printing Style dialog box that you view may not look just like the one shown back in Figure 1.

The PrStlDialog() function requires a handle to a TPrint record as its one parameter. If the user clicks the Printing Style dialog box OK button, the values entered in that dialog box (such as page orientation) will be placed in the TPrint record. PrStlDialog() will then return a value of true. If the user clicks the Cancel button, the TPrint record will be unaffected and the routine will return a value of false.

PrStlDialog( printRecord );

Displaying the Printing Style dialog box saves document printing information, but not the number of copies or the range of pages to print. To do that, call PrJobDialog(). This routine will display the Printing Job dialog box. Like the Printing Style dialog box, the look of the Printing Job dialog box is defined in the printer resource file. A call to PrJobDialog() should be made in response to a user's selection of the Print menu item in your application.

PrJobDialog() accepts a handle to a TPrint record as its only parameter. A mouse click on the OK button results in the values in the dialog box (such as number of copies to print) being entered into the TPrint record. PrJobDialog() then returns a value of true to the application. A click on the Cancel button leaves the TPrint record untouched and returns a value of false to the program.

Boolean		doPrint;
doPrint = PrJobDialog( printRecord );
if ( doPrint == false )
	// handle case of user canceling printing

PrintPict

This month's program is PrintPict. To provide you with a very concise, straightforward example of the primary functions of the Printing Manager, PrintPict is a simple, non-menu-driven program. When run, PrintPict displays the Printing Style dialog box - the dialog box normally brought on by choosing Page Setup from the File menu. After clicking the OK button, the program dismisses that dialog box and displays the Printing Job dialog box - the dialog box normally brought on by choosing Print from the File menu. After clicking the Print button, the program dismisses that dialog box and sends the printing job to the printer. After that the program quits. Without menus and without giving the user any control of what to print, the PrintPict program certainly doesn't qualify as user-friendly. But, much more importantly, it does show you, in just a page or two of code, how to make use of the Printing Manager.

Creating the PrintPict Resources

Start the project by creating a new folder named PrintPict in your CodeWarrior development folder. Launch ResEdit, then create a new resource file named PrintPict.rsrc. Make sure to specify the PrintPict folder as the resource file's destination. The resource file will hold resources of the types shown in Figure 3.



Figure 3.The PrintPict resources.

The one ALRT and one DITL resource are used to define the program's error-handling alert. The only other resource needed is a single PICT. It's this picture that will be printed by the PrintPict program. Feel free to use any picture of any reasonable size here. If you have a color printer, go ahead and include a color picture so that you can verify that the PrintPict program prints in color.

Creating the PrintPict Project

Start CodeWarrior and choose New Project from the File menu. Use the MacOS:C_C++:MacOS Toolbox:MacOS Toolbox Multi-Target project stationary for the new project. You've already created a project folder, so uncheck the Create Folder check box before clicking the OK button. Name the project PrintPict.mcp, and make sure the project's destination is the PrintPict folder.

Add the PrintPict.rsrc resource file to the new project. Remove the SillyBalls.rsrc file. Go ahead and remove the ANSI Libraries folder from the project window if you want - the project doesn't use any of these libraries.

Create a new source code window by choosing New from the File menu.. Save the window, giving it the name PrintPict.c. Now choose Add Window from the Project menu to add this empty file to the project. Remove the SillyBalls.c placeholder file from the project window. You're all set to type in the source code.

To save yourself some typing, go to MacTech's ftp site at ftp://ftp.mactech.com/src/mactech/volume15_1999/15.08.sit. There you'll find the PrintPict source code file available for downloading.

Walking Through the Source Code

Because the PrintPict program isn't event-driven, the listing is shorter than our other example listings. PrintPict.c starts with a couple of constants. kALRTResID defines the ID of the ALRT resource used to define the error-handling alert. kPICTResID defines the ID of the PICT resource that holds the picture to print.

/********************* constants *********************/
#define 		kALRTResID			128
#define		kPICTResID			128

PrintPict declares just one global variable. The THPrint variable gPrintRecord is the print record that holds information about the currently selected printer. While in PrintPict we could get away with declaring this variable local to main(), it's been declared global for future use. If we expand upon the PrintPict program we'll put the print record to use in a variety of routines. For instance, if we later implement a File menu that includes a Print item, then the display of the printing job dialog box will no doubt be handled by a separate application-defined function. A call to PrJobDialog() requires the print record as a parameter.

/****************** global variables *****************/
THPrint		gPrintRecord;

Next come the program's function prototypes.

/********************* functions *********************/
void		ToolBoxInit( void );
void		DrawToPort( void );
void		DoError( Str255 errorString );

The main() function begins with the declaration of a couple of variables. The TPPrPort variable printerPort is a pointer to a printing graphics port. This variable will get its value from a call to PrOpenDoc(). The Boolean variable doPrint tells the program whether the Printing Job dialog box was dismissed with a click on the Print or the Cancel button. Next, the Toolbox is initialized by way of a call to ToolBoxInit().

/********************** main *************************/
void		main( void )
{
	TPPrPort		printerPort;
	Boolean		doPrint;
	ToolBoxInit();

A new print record is then created. A call to PrOpen() prepares the current printer resource file for use. PrintDefault() fills the new print record with default values.

	gPrintRecord = (THPrint)NewHandleClear( sizeof( TPrint ) );
	PrOpen();
	PrintDefault( gPrintRecord );

Next, the Printing Style dialog box is displayed. The call to PrStlDialog() does all the work of monitoring the user's actions in this dialog box. In a full-featured program we'd make this call in response to the user choosing Page Setup from the File menu.

	PrStlDialog( gPrintRecord );

Once the Printing Style dialog box is dismissed, a call to PrJobDialog() displays the Printing Job dialog box. If the user clicks the Print button, PrJobDialog() returns a value of true, and the program continues on. If the user cancels printing, the program ends. In your own application you won't need to abruptly exit should the user cancel printing - you'll typically just carry on.

	doPrint = PrJobDialog( gPrintRecord );
	if ( doPrint == false )
		DoError( "\pUser canceled printing" );

If printing is to take place, the program calls PrOpenDoc() to initialize a printing graphics port. A pointer to the new port is returned and saved in the variable printerPort.

	printerPort = PrOpenDoc( gPrintRecord, nil, nil );

A call to PrOpenPage() begins the printing of a page. After this call all subsequent QuickDraw commands are routed to the printer. While the QuickDraw calls could have appeared here in main(), we'll group them in an application-defined function named DrawToPort().

	PrOpenPage( printerPort, nil );
	DrawToPort( kPICTResID );

We'll look at DrawToPort() just ahead. Regardless of the contents of that routine, once DrawToPort() returns, the printing of a page is complete - so we can wrap things up. A call to PrClosePage() balances the previous call to PrOpenPage(). Similarly, a call to PrCloseDoc() balances the prior call to PrOpenDoc(). Finally, a call to PrClose() pairs with the earlier call to PrOpen(), and closes the Printing Manager and the printing resource file.

	PrClosePage( printerPort );  
	PrCloseDoc( printerPort );
	PrClose();
}

As expected, ToolBoxInit() is identical to previous versions.

/******************** ToolBoxInit ********************/
void		ToolBoxInit( void )
{
	InitGraf( &qd.thePort );
	InitFonts();
	InitWindows();
	InitMenus();
	TEInit();
	InitDialogs( nil );
	InitCursor();
}

The DrawToPort() function holds the code that defines what is to be printed. PrintPict prints a picture, so the code in DrawToPort() loads a PICT resource to memory and then draws that picture. A call to GetPicture() moves the PICT code to memory.

void DrawToPort( void )
{
 	PicHandle	pict;
	Rect				rect;
	short			width;
	short			height;
	short			L, R, T, B;
	pict = GetPicture( kPICTResID );

Next, the size of the picture is determined. The picFrame field of the picture record referenced by the handle pict supplies that information. A little offsetting is done in case the picFrame rectangle boundaries aren't located at (0, 0).

	rect = (**pict).picFrame;
	width = rect.right - rect.left;
	height = rect.bottom - rect.top;

Now we determine where on the page we want the picture printed. The upper-left corner of the page is at coordinate (0, 0). By setting up a rectangle with a upper-left coordinate at (75, 50) we're telling the program to start the picture 75 pixels from the left of the page and 50 pixels from the top of the page.

	L = 75;
	R = L + width;
	T = 50;
	B = T + height;
	SetRect( &rect, L, T, R, B );

A call to DrawPicture() draws the picture. The current port has been set to the printer, so that's where "drawing" takes place. Finally, a call to ReleaseResource() frees the memory occupied by the picture.

	DrawPicture( pict, &rect ); 
	ReleaseResource( (Handle)pict );
} 

We've placed all the printing code in this one function for a good reason - it makes it easy to experiment. After successfully compiling and running the program you may want to replace the contents of DrawToPort() with other QuickDraw calls, such as a few calls to MoveTo() and Line(). Calls to DrawString() work too. DoError() is unchanged from prior versions. A call to this function results in the posting of an alert that holds an error message. After the alert is dismissed the program ends.

/********************** DoError **********************/
void		DoError( Str255 errorString )
{
	ParamText( errorString, "\p", "\p", "\p" );
	StopAlert( kALRTResID, nil );
	ExitToShell();
}

Running PrintPict

Run PrintPict by selecting Run from CodeWarrior's Project menu. After compiling the code and building a program, CodeWarrior runs the program. The Printing Style dialog box will automatically open. Look it over, make some changes if you'd like (including scaling the size of the picture), then click the OK button. After the style dialog box is dismissed, the Printing Job dialog box appears. Click the Print button and the dialog box is dismissed. The program quits, and a short time later your printer prints out a picture.

Till Next Month...

The PrintPict program provides a look at the very basics of sending information to a printer. Use your newfound knowledge of the Printing Manager to add Page Setup and Print commands to your program's File menu. In response to a print command you'll want to send the information from the frontmost window to the printer. Your program should already hold the code necessary to update a window, so your program already contains most of the code necessary to print! When a print command is issued, you'll specify that the port to "draw" to should be the printer - not the window. For the details on how to do this, browse through the Imaging With QuickDraw volume of Inside Macintosh. Or, wait until next month's issue of MacTech...

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

BBEdit 11.1.1 - Powerful text and HTML e...
BBEdit is the leading professional HTML and text editor for the Mac. Specifically crafted in response to the needs of Web authors and software developers, this award-winning product provides a... Read more
CrossOver 14.1.3 - Run Windows apps on y...
CrossOver can get your Windows productivity applications and PC games up and running on your Mac quickly and easily. CrossOver runs the Windows software that you need on Mac at home, in the office,... Read more
Little Snitch 3.5.3 - Alerts you about o...
Little Snitch gives you control over your private outgoing data. Track background activity As soon as your computer connects to the Internet, applications often have permission to send any... Read more
OmniGraffle Pro 6.2.3 - Create diagrams,...
OmniGraffle Pro helps you draw beautiful diagrams, family trees, flow charts, org charts, layouts, and (mathematically speaking) any other directed or non-directed graphs. We've had people use... Read more
OmniFocus 2.2 - GTD task manager with iO...
OmniFocus helps you manage your tasks the way that you want, freeing you to focus your attention on the things that matter to you most. Capturing tasks and ideas is always a keyboard shortcut away in... Read more
Cocktail 8.4 - General maintenance and o...
Cocktail is a general purpose utility for OS X that lets you clean, repair and optimize your Mac. It is a powerful digital toolset that helps hundreds of thousands of Mac users around the world get... Read more
PDFKey Pro 4.3 - Edit and print password...
PDFKey Pro can unlock PDF documents protected for printing and copying when you've forgotten your password. It can now also protect your PDF files with a password to prevent unauthorized access and/... Read more
Kodi 15.0.beta1 - Powerful media center...
Kodi (was XBMC) is an award-winning free and open-source (GPL) software media player and entertainment hub that can be installed on Linux, OS X, Windows, iOS, and Android, featuring a 10-foot user... Read more
DiskCatalogMaker 6.4.12 - 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
Macs Fan Control 1.3.0.0 - Monitor and c...
Macs Fan Control allows you to monitor and control almost any aspect of your computer's fans, with support for controlling fan speed, temperature sensors pane, menu-bar icon, and autostart with... Read more

Moleskine Timepage – Calendar for iCloud...
Moleskine Timepage – Calendar for iCloud, Google & Exchange 1.0 Device: iOS iPhone Category: Productivity Price: $4.99, Version: 1.0 (iTunes) Description: The most elegant calendar for your pocket and wrist, Timepage is a... | Read more »
QuizUp Gets Social in its New Update
Plain Vanilla Corp has released a new and improved version of their popular trivia game, QuizUp. The app now emphasizes social play so you can challenge friends from all over the world. [Read more] | Read more »
The Deep (Games)
The Deep 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: Swipe Controls Delve into the deep in this retro rogue-like! Swipe to move your diver around and keep away from the enemies as you... | Read more »
Battle of Gods: Ascension (Games)
Battle of Gods: Ascension 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: TURN-BASED TACTICAL COMBATFight tactical battles against the forces of Hades! In Battle of Gods: Ascension you play... | Read more »
Shadowmatic's Latest Update Adds a...
Shadowmatic's shadowy shadow-ness is getting a little shadowy-er thanks to a recent update that adds an Arcade Mode. [Read more] | Read more »
Sunrise Calendar and Slack Have Assimila...
Wunderlist is perhaps one of the most populat and beloved productivity apps on the App Store - and now it's gone and incorporated itself into other useful services like Sunrise Calendar and Slack. [Read more] | Read more »
Crossy Road Devs Hipster Whale are Bring...
Hipster Whale, the minds behind the rather popular (and rather great) Crossy Road, have teamed-up with Bandai Namco to create PAC-MAN 256: an absolutely bonkers looking maze runner chaser thing. | Read more »
Meet the New Spotify Music
Spotify Music  has a lot going on. They're introducing 3 new modes to serve all your musical needs, with the "Now" start page  gives you curated playlists based on your particular tastes. As you listen the app will learn more about your tastes and... | Read more »
What the Apple Watch Gets Right, and Wha...
| Read more »
Celebrate PAC-MAN's 35th Birthday W...
BANDAI NAMCO Entertainment America is celebrating PAC-MAN's 35th anniversary by releasing updates for PAC-MAN and PAC-MAN Lite for iOS. [Read more] | Read more »

Price Scanner via MacPrices.net

What Would the ideal Apple Productivity Platf...
For the past four years I’ve kept a foot in both the Mac and iPad camps respectively. my daily computing hours divided about 50/50 between the two devices with remarkable consistency. However, there’... Read more
PageMeUp 1.2.1 Ten Dollar Page Layout Applica...
Paris, France-based Softobe, an OS X software development company, has announced that their PageMeUp v. 1.2.1, is available on the Mac App Store for $9.99. The license can be installed on up to 5... Read more
Eight New Products For USB Type-C Application...
Fresco Logic, specialists in advanced connectivity technologies and ICs, has introduced two new product families targeting the Type-C connector recently introduced across a number of consumer... Read more
Scripps National Spelling Bee Launches Buzzwo...
Scripps National Spelling Bee fans can monitor the action at the 2015 Spelling Bee with the new Buzzworthy app for iOS, Android and Windows mobile devices. The free Buzzworthy app provides friendly... Read more
13-inch 2.5GHz MacBook Pro on sale for $120 o...
B&H Photo has the 13″ 2.5GHz MacBook Pro on sale for $979 including free shipping plus NY sales tax only. Their price is $120 off MSRP, and it’s the lowest price for this model (except for Apple’... Read more
27-inch 3.3GHz 5K iMac on sale for $1899, $10...
B&H Photo has the new 27″ 3.3GHz 5K iMac on sale for $1899.99 including free shipping plus NY tax only. Their price is $100 off MSRP. Read more
Save up to $50 on iPad Air 2, NY tax only, fr...
B&H Photo has iPad Air 2s on sale for up to $50 off MSRP including free shipping plus NY sales tax only: - 16GB iPad Air 2 WiFi: $469 $30 off - 64GB iPad Air 2 WiFi: $549.99 $50 off - 128GB iPad... Read more
Updated Mac Price Trackers
We’ve updated our Mac Price Trackers with the latest information on prices, bundles, and availability on systems from Apple’s authorized internet/catalog resellers: - 15″ MacBook Pros - 13″ MacBook... Read more
New 13-inch 2.9GHz Retina MacBook Pro on sale...
B&H Photo has the 13″ 2.9GHz/512GB Retina MacBook Pro on sale for $1699.99 including free shipping plus NY tax only. Their price is $100 off MSRP, and it’s the lowest price for this model from... Read more
Apple refurbished 2014 MacBook Airs available...
The Apple Store has Apple Certified Refurbished 2014 MacBook Airs available starting at $679. An Apple one-year warranty is included with each MacBook, and shipping is free: - 11″ 1.4GHz/128GB... Read more

Jobs Board

*Apple* Solutions Consultant - Retail Sales...
**Job Summary** As an Apple Solutions Consultant (ASC) you are the link between our customers and our products. Your role is to drive the Apple business in a retail Read more
*Apple* Watch SW Application Project Manager...
**Job Summary** The Apple Watch software team is looking for an Application Engineering Project Manager to work on new projects for Apple . The successful candidate Read more
Engineering Manager for *Apple* Maps on the...
…the Maps App Team get to take part in just about any new feature in Apple Maps, often contributing a majority of the feature work. In our day-to-day engineering work, we Read more
Senior Software Engineer - *Apple* SIM - Ap...
Changing the world is all in a day039s work at Apple . If you love innovation, here039s your chance to make a career of it. You039ll work hard. But the job comes with Read more
Lead *Apple* Solutions Consultant - Retail...
**Job Summary** Job Summary The Lead ASC is an Apple employee who serves as the Apple business manager and influencer in a hyper-business critical Reseller's store Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.