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

GarageSale 7.0.7 - Create outstanding eB...
GarageSale is a slick, full-featured client application for the eBay online auction system. Create and manage your auctions with ease. With GarageSale, you can create, edit, track, and manage... Read more
SpamSieve 2.9.28 - Robust spam filter fo...
SpamSieve is a robust spam filter for major email clients that uses powerful Bayesian spam filtering. SpamSieve understands what your spam looks like in order to block it all, but also learns what... Read more
Thunderbird 45.7.1 - Email client from M...
As of July 2012, Thunderbird has transitioned to a new governance model, with new features being developed by the broader free software and open source community, and security fixes and improvements... Read more
Opera 43.0.2442.991 - High-performance W...
Opera is a fast and secure browser trusted by millions of users. With the intuitive interface, Speed Dial and visual bookmarks for organizing favorite sites, news feature with fresh, relevant content... Read more
OnyX 3.2.4 - Maintenance and optimizatio...
OnyX is a multifunction utility that you can use to verify the startup disk and the structure of its system files, to run miscellaneous maintenance and cleaning tasks, to configure parameters in the... Read more
VueScan 9.5.71 - Scanner software with a...
VueScan is a scanning program that works with most high-quality flatbed and film scanners to produce scans that have excellent color fidelity and color balance. VueScan is easy to use, and has... Read more
Slack 2.5.1 - Collaborative communicatio...
Slack is a collaborative communication app that simplifies real-time messaging, archiving, and search for modern working teams. Version 2.5.1: New The way we load teams you don't view often has been... Read more
HandBrake 1.0.3 - Versatile video encode...
HandBrake is a tool for converting video from nearly any format to a selection of modern, widely supported codecs. Features Supported Sources VIDEO_TS folder, DVD image or real DVD (unencrypted... Read more
Vivaldi 1.7.735.46 - An advanced browser...
Vivaldi is a browser for our friends. In 1994, two programmers started working on a web browser. Our idea was to make a really fast browser, capable of running on limited hardware, keeping in mind... Read more
Vivaldi 1.7.735.46 - An advanced browser...
Vivaldi is a browser for our friends. In 1994, two programmers started working on a web browser. Our idea was to make a really fast browser, capable of running on limited hardware, keeping in mind... Read more

Last week on Pocket Gamer
If you’re wondering what’s going on in the wider world of portable gaming, our sister site PocketGamer has you covered. Each week we like to check in on the PG team and see what they’ve been preoccupied with. From the latest on the Nintendo Switch... | Read more »
Mudd Masher arrives this week
Atooi Games, the minds behind Totes the Goat and Mutant Mudds, have a new game in the works -- Mudd Masher. The game, a hybrid of the independent studio's first two titles, is expected to launch this week on March 2. [Read more] | Read more »
The best sales on the App Store this wee...
The App Store has quite an exciting lineup of discount games this week that range across a variety of genres. It's a great opportunity to catch up on some of the premium games you may have been holding off on -- and some you can even grab for free... | Read more »
The best new games we played this week
Ah, here we are again at the close of another busy week. Don't rest too easy, though. We had a lot of great new releases in mobile games this week, and now you're going to have to spend all weekend playing them. That shouldn't be too much of a... | Read more »
Rollercoaster Tycoon Touch Guide: How to...
| Read more »
Rabbids Crazy Rush Guide: How to unlock...
The Rabbids are back in a new endless running adventure, Rabbids Crazy Rush. It's more ridiculous cartoon craziness as you help the little furballs gather enough fuel (soda) to get to the moon. Sure, it's a silly idea, but everyone has dreams --... | Read more »
Tavern Guardians (Games)
Tavern Guardians 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: Tavern Guardians is a Hack-and-Slash action game played in the style of a match-three. You can experience high pace action... | Read more »
Slay your way to glory in idle RPG Endle...
It’s a golden age for idle games on the mobile market, and those addictive little clickers have a new best friend. South Korean developer Ekkorr released Endless Frontier last year, and players have been idling away the hours in the company of its... | Read more »
Tiny Striker: World Football Guide - How...
| Read more »
Good news everyone! Futurama: Worlds of...
Futurama is finding a new home on mobile in TinyCo and Fox Interactive's new game, Futurama: Worlds of Tomorrow. They're really doing it up, bringing on board Futurama creator Matt Groening along with the original cast and writers. TinyCo wants... | Read more »

Price Scanner via MacPrices.net

13-inch 2.7GHz Retina MacBook Pro on sale for...
B&H Photo has the 2015 13″ 2.7GHz/128GB Retina Apple MacBook Pro on sale for $150 off MSRP. Shipping is free, and B&H charges NY tax only: - 13″ 2.7GHz/128GB Retina MacBook Pro (MF839LL/A): $... Read more
13-inch 1.6GHz/256GB MacBook Air on sale for...
Newegg has the 13″ 1.6GHz/256GB MacBook Air (MMGG2LL/A) on sale for $1029.99 including free shipping. Their price is $170 off MSRP, and it’s the lowest price available for this model. Choose Newegg... Read more
Apple refurbished Apple TVs available for up...
Apple has Certified Refurbished 32GB and 64GB Apple TVs available for up to $30 off the cost of new models. Apple’s standard one-year warranty is included with each model, and shipping is free: -... Read more
27-inch 3.3GHz 5K iMac on sale for $2099, sav...
B&H Photo has the 27″ 3.3GHz 5K Apple iMac on sale for $2099.99 including free shipping plus NY sales tax only. Their price is $200 off MSRP. Amazon also has the 27″ 3.3GHz 5K iMac on sale for $... Read more
21-inch iMacs on sale for up to $111 off MSRP
B&H Photo has select 21″ Apple iMacs on sale for up to $110 off MSRP, each including free shipping plus NY sales tax only: - 21″ 2.8GHz iMac: $1189 $110 off MSRP - 21″ 1.6GHz iMac: $999 $100 off... Read more
12-inch 1.2GHz Retina MacBooks on sale for $2...
Newegg has the 12″ 1.2GHz Space Gray Retina MacBook (sku MLH82LL/A) on sale for $1349.99 including free shipping. Their price is $250 off MSRP, and it’s the lowest price available for this model.... Read more
13-inch MacBook Airs on sale for $100 off MSR...
B&H Photo has 13″ MacBook Airs on sale for $100 off MSRP. Shipping is free, and B&H charges NY sales tax only: - 13″ 1.6GHz/128GB MacBook Air (MMGF2LL/A): $899 $100 off MSRP - 13″ 1.6GHz/... Read more
9-inch 32GB Silver iPad Pro on sale for $549,...
B&H Photo has the 9.7″ 32GB Silver Apple iPad Pro on sale for $549 for a limited time. Shipping is free, and B&H charges NY sales tax only. Their price is $50 off standard MSRP for this model... Read more
13-inch 2.0GHz Apple MacBook Pros on sale for...
B&H has the non-Touch Bar 13″ 2.0GHz MacBook Pros in stock today and on sale for $100 off MSRP. Shipping is free, and B&H charges NY sales tax only: - 13″ 2.0GHz MacBook Pro Space Gray (... Read more
15-inch Touch Bar MacBook Pros on sale for up...
B&H Photo has the new 2016 15″ Apple Touch Bar MacBook Pros in stock today and on sale for up to $150 off MSRP. Shipping is free, and B&H charges NY sales tax only: - 15″ 2.7GHz Touch Bar... Read more

Jobs Board

*Apple* Solutions Consultant - Apple (United...
# Apple Solutions Consultant Job Number: 55676865 Los Angeles, California, United States Posted: Feb. 22, 2017 Weekly Hours: 40.00 **Job Summary** As an Apple Read more
Programmer/Editor *Apple* Music Dance - App...
# Programmer/Editor Apple Music Dance Job Number: 55565967 Culver City, California, United States Posted: Feb. 23, 2017 Weekly Hours: **Job Summary** Apple Music Read more
Digital Marketing Specialist - *Apple* iClo...
# Digital Marketing Specialist - Apple iCloud Job Number: 54729233 Culver City, California, United States Posted: Feb. 22, 2017 Weekly Hours: 40.00 **Job Summary** Read more
Marketing Specialist, iTunes & *Apple*...
# Marketing Specialist, iTunes & Apple Music Job Number: 55704205 Culver City, California, United States Posted: Feb. 23, 2017 Weekly Hours: 40.00 **Job Summary** Read more
*Apple* Wireless Lead - T-ROC - The Retail O...
…of knowledge in wireless sales and activations to the Beautiful and NEW APPLE Experiencestore within MACYS. THIS role, APPLE Wireless Lead, isbrandnewas MACYS Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.