TweetFollow Us on Twitter

GUI-up your Script

Volume Number: 22 (2006)
Issue Number: 8
Column Tag: Mac in the Shell

GUI-up your Script

OK - Perhaps the GUI is nice every now and then...

by Edward Marczak

Introduction

While I can extol the virtues of life in the shell, I do realize that sometimes, just sometimes, a GUI is more appropriate. Why would I say such a thing? Because there will be scripts that you write primarily to be used by other people. The kind of people that don't keep a terminal window open 100% of the time. On one hand, you've found a great solution to their issue. On the other, you don't want the cure to be more painful than the disease. The wonderful thing about Apple's XCode development environment is that you can take practically any shell solution and turn it into a GUI-based one without too much effort. That's where we'll be heading this month.

What's New in AppleScript

Did I just say AppleScript? Yes, yes I did. The history of AppleScript is outside the scope of this column; it is very lengthy. It is now, however, a mature technology. Even more exciting is the inclusion of "AppleScript Studio" into OS X and XCode.

Now, you won't find an application, or even a submenu that launches anything called "AppleScript Studio." AppleScript Studio refers to the ability of XCode to take an AppleScript app, tie it into all of the other XCode technologies and compile it into a native Cocoa app. This makes creating a basic application mind-blowingly simple. We're going to create a small sample app to prove this.

Fire Up XCode

If you've never launched XCode, now's your chance to dig in. If you're an XCoder already, you may have missed (or ignored) some of the AppleScript options. More importantly, if you've never installed XCode, you'll need to for the rest of this article. While the XCode environment ships with each copy of the OS, the retail disc is a little dated at this point. Bring yourself to <http://developer.apple.com>, sign up for a free account, and download the latest version of XCode (2.3, as of this writing, weighing in at 915MB).

With XCode installed, it's time to launch it. You'll find it at /Developer/Applications:



Figure 1: XCode icon

You may not notice that it's up and running. In its minimalist way, there's no splash screen or other trumpeting of its arrival. Choose New Project from the File menu:



Figure 2: New Project

When presented with the choice of the kind of project, choose "AppleScript Application" and click "Next". Name your project - the example this month is "Backup", if you're following along - and where you want it saved. XCode will create directories for you if necessary. Once you give it the go ahead, you'll be staring at a fresh new project.



Figure 3: Default Project

Lot of stuff - stay cool. In the "Groups & Files" pane, you'll see a 'Scripts' folder. Since we're going to be writing an AppleScript that will front-end a shell script, as you can imagine, this is where the bulk of the action will take place for us. Of course, we need to begin at the beginning. Let's write the shell script.

The Heart of the Matter

The real work will be done by a shell script, so we need to have that in place. This will be a 'lite' version of a solution I really have put in place. However, there were enough things that were specific to the environment in question, that I don't want to reproduce here. Additionally, I won't be getting into any heavy error checking or correction. Nor will I make the claim that this is a perfect fit for any other particular situation. That said, I'll offer this basic script as our base:

#!/bin/bash
ditto -rsrc /Files /Volumes/Backup_Drive/Files

This one-liner uses the OS X native ditto command to copy all files from /Files to /Volumes/Backup_Drive/Files. I'll stick the '-rsrc' switch in there as it only became the default behavior as of 10.4. What if we want to run this on a Panther machine? Use your favorite text editor to create this script, and then save it. Call it "backup.sh". Mark it executable with chmod 770 and test it. You may need to modify the path names, or, for testing purposes, simply copy between two folders on your local drive.

Have it working? Great. Now, we can drag-and-drop this script right into our XCode project. Locate this script in the Finder, and drag it into the Scripts folder. You'll be asked how to reference this file. Ensure that the "Copy items into destination group's folder" is checked, and click add.



Figure 4: Copying a script into XCode

You should see your backup.sh script listed alongside the preloaded AppleScript file. Like so:



Figure 5: Your script has been added

If you've never used XCode before, please do this now: click on the build icon in the toolbar. This will help you understand how XCode lays out your project. Open up the folder where you saved this project. Inside, you'll find a folder named 'build'. Inside of that, you'll find one named 'Debug', and it will contain your Backup.app. See how easy that was? OK, not so fast, right? Although this app actually will run (go on, try it), it won't do anything of use. Right-click (control-click) on the app and select "Show Package Contents". Open the resulting 'Contents' folder, and the 'Resources' folder beneath that. You should see three objects: backup.sh, English.lproj and Scripts. Well, there's our 'backup.sh' file! Now we know where it lives and how to access it.

Get GUI

Back in XCode, toggle the disclosure triangle next to the 'Resources' group. Double-click on the 'MainMenu.nib' file. This will launch Interface Builder, and even more windows will now litter your screen. Click once on the window labeled 'Window'. Let's immediately name it something more relevant. Change the Window Title in the inspector pane, and title the window "Backup". Also, we need to give it an AppleScript name. Change the drop-down menu in the inspector to "AppleScript". Name the window "wMain". Now, look for a button in the 'Cocoa-Controls' pane. Drag it to the lower right-hand corner of our window. You'll see guidelines appear to help you position it. With the button still selected, let's make it say and do something appropriate. Back on the attributes screen, update the button title in the inspector pane. (Change the drop-down menu to get back to the attributes screen). Additionally, change the 'Key equiv.' to '\R' - type it in or use the drop down menu to select 'Return', and check the 'Selected' checkbox. Flip the inspector back to AppleScript, and give this button a name. How about "bBackup"?

Now to begin to tie it together: Making sure that you're still in the AppleScript portion of the inspector, place a check-mark in the 'Action' box, and select the 'Backup.applescript' in the list at the bottom of the Inspector. Save and quit. Not too terrible, right? Of course, now we have to make that AppleScript do something.

I am not, nor will I pretend to be an AppleScript guru. I can deal with the basics well enough, and they are easy to pick up. However, once you start doing this, and you get hooked on it, do yourself a favor and hit some of the many fine AppleScript resources available. This includes Ben Waldie's AppleScript column right here in MacTech. He's also written some excellent books, available through SpiderWorks (http://www.spiderworks.com). There's also <http://www.macscripter.net>, another web-based resource. However, to simply front-end a shell script - no matter how complex - you'll find all you need in this one column. Just do realize that you can do some very complex scripting with AppleScript, and in an all Mac environment is well-worth learning.

With that out of the way, let's continue. Back in XCode proper, double-click on the 'Backup.applescript' in the 'Scripts' group. You'll see that XCode give you some pre-populated comments for you to tailor to this project. But comments don't cause any action! Place these lines into the script:

on clicked theObject
   -- setup
   set myPath to POSIX path of (path to me) as string
   
   -- Do it!
   do shell script quoted form of myPath & "Contents/Resources/backup.sh"
end clicked

As you type this in, all text will be set in a purple mono-spaced font (by default, anyway - you may have changed this preference). Once you save, the parser comes alive to check the validity of the script. Valid strings and recognized keywords get color-coded and set in a different font. What did we just tell our application to do? Actions performed on the button will be sent here since we used Interface Builder to tie an action to this particular script. In this case, we're interested to know when someone clicks on the button.

The first line (set myPath...) sets the "myPath" variable to the path of the application. This lets the user place this app wherever they want on their file system, and we can deal with it at runtime. Next, we call our shell script. AppleScript gained the ability to call scripts with the "do shell script" command. Currently, we know where our app lives and have stored that in a variable, myPath. Earlier, we verified where our script lives inside our application bundle. Now we know where to go relative to the app. We can launch our script from the "Contents/Resources" folder below "myPath".

Is it really this simple? Let's find out. First: go load up your /Files directory with some files and folders. Then, back in XCode, click on the "Build and Go" icon in the toolbar. A build window will appear and give you build status. Once complete, you'll see the window that we created earlier in Interface Builder with its one lonely button. As you can see, it is the default button, and has the Aqua default pulsing glow. Go ahead and click the "Backup" button. Our app will run our shell script buried in the application bundle. Depending on how much stuff you loaded into the /Files directory, this may take a minute. Do notice, though, that while the underlying script is running, the button stops pulsing. Once the script finishes up, the button will pulse again. Press Apple-Q or select "Quit NewApplication" from the "Backup" menu.

The answer, then, is "yes! It is that simple." Of course, not only did we not write a very friendly application, there are some other things we need to take into consideration. However, if all you ever want is a one-button method of running a shell-script, now you have the framework to do so. This isn't anything I'd hand a client, of course.

Version 1.1

Before I continue to spill letters onto the page, there's a much more important source before we continue. "do shell script" is addressed in detail in Apple's Technote TN2065. This is a must read. URL in the references at the end of this article.

Moving along, we need to create better feedback for the client when they run our application. Double-click on the MainMenu.nib file once again (in XCode). You should see our application's window displayed by default. If not, double-click the "Window" icon in the "MainMenu.nib (English)" window. Drag a progress indicator from the Cocoa-Controls window onto our main window - place it just above the backup button, and stretch it horizontally to the width of the window. Then, with it still selected, change the drop-down menu in the inspector to "AppleScript". Give this control a name...like, "pMainProgress". (I used to code in VB and RB and, yes, Hungarian notation is driven pretty deep into my brain). We need this name so we can refer to the control in code. Save and quit Interface Builder.

Once again, we're in the position of writing code that will actually make that progress bar do something. Fortunately, AppleScript makes it pretty trivial. You'll see why we need to name objects so AppleScript can reference them. Here's one of the lines we'll need to add:

set uses threaded animation of progress indicator "pMainProgress" of window "wMain" to true

(While this may wrap in print, you should type it as all one single line with no line break).

Since we can have multiple windows, each with multiple progress bars and other objects, we need to be specific. We need to set the "uses threaded animation" property of the progress bar. Ah, which progress bar? The one we called "pMainProgress". Well, on which window? "wMain"! AppleScript's goal of being English-like works in its favor most of the time. Other times, you can get some pretty bizarre sentences. We'll place all of our code right in the on clicked section, because we only want the progress bar to animate while the backup is running. The fully updated code follows (and look for the start and stop of the progress bar):

on clicked theObject
   -- setup
   set myPath to POSIX path of (path to me) as string
   -- Start progress bar
   set uses threaded animation of progress indicator "pMainProgress" of window "wMain" to true
   tell progress indicator "pMainProgress" of window "wMain" to start
   
   -- Do it!
   do shell script quoted form of myPath & "Contents/Resources/backup.sh"
   -- Stop progress bar
   tell progress indicator "pMainProgress" of window "wMain" to stop
   set uses threaded animation of progress indicator "pMainProgress" of window "wMain" to false
   
end clicked

(Again, these lines wrap in print, but they should not be artificially broken when you type them).

Our progress bar commands "wrap" the do shell script. Time for the test: Apple-S (save) and Apple-R (build and Run). Make sure that your source folder is populated, and click on "Backup". Progress bar moves while it's working, and stops once it's done. Fantastic.

What if there's a problem? We really want to trap for errors. Change the "Do it" section to read thusly:

   -- Do it!
   try
      do shell script quoted form of myPath & "Contents/Resources/backup.sh"
   on error number 255
      display dialog "Sorry, an error occurred.  I can't make the copy."
   end try

As you can surmise, this allows us to try a command that may fail, without bombing out - we get to control the process. Here, I show a basic try block. We try to run the script. If it runs properly, returning a zero, all's good and we continue on. If there's a problem, we show a dialog box that explains that there has been a problem. Try blocks can certainly get much more elaborate.

What might be a reason that we'd have an error in our script? Perhaps we're asking it to backup areas of the file system that we don't have access to? In that case, you can have your script run with administrator privileges. You do this with the....wait for it..."with administrator privileges" parameter. Alter the do shell script line to read like this:

do shell script quoted form of myPath & "Contents/Resources/backup.sh" 
with administrator privileges

By itself, with no additional parameters, this will present the user with the familiar dialog box asking for an admin password when the app is run.



Figure 6: Our app asking for authentication

You can preload your script with a username and password. However, I DO NOT RECOMMEND THIS. Clear? To tie this back into last month's column, it would be trivial for someone to run strings across the resulting binary and gather the admin level id and password you provided. If you're daring enough to risk it, find the instructions in the Apple 'do shell script' technote referenced earlier (but seriously: don't).

One little thing that TN2065 does not mention: there is a default timeout on all AppleScript commands, including do shell script, of two minutes. If you believe your script may run for longer - for whatever reason - use a with timeout block:

with timeout of 300 do
   do shell script ...
end timeout

Unfortunately, there is no setting that will just let it do its thing indefinitely (OK, perhaps not a terrible thing). If a command does timeout, a timeout error is thrown (-1712). So do make sure you use a value large enough to let your script run to completion. Even if that's "99999".

One for the road

We'll add one more object to our window: A text field with the current status. Double-click on MainMenu.nib, and once Interface Builder is running, click on the Cocoa-Text icon in the object palette:



Figure 7: Cocoa-Text icon

Drag two "System Font Text" fields to the main window. Place one in the upper left (use the guides), and the second right next to it. Double-click on the first, and type "Status:" into the text field. Double-click on the second and type "Idle" into its text field. With the second still selected, Apple-8 your way to the AppleScript attributes, and name this field "efStatus". We should also clean this window up a bit while we're here, no? Drag the progress bar straight up until the guides appear under the text fields we just created. Do the same for the single button, and stop when the guides appear under the progress bar. Size the window itself appropriately, again using the guides. Save and quit Interface Builder.

Again, we need to make that text field perform an appropriate action. Here's how we can do so. In the "setup" section, add this line:

set the contents of text field "efStatus" of window "wMain" to "Copying files..."
...and just after the try block, add this line:
set the contents of text field "efStatus" of window "wMain" to "Backup Complete."

Save (Apple-S), build and run (Apple-R) the project with the changes. Nice.

Finally

Last thing I'll mention: If you really want to make this professional, you'll probably want to fix up the app menus to show the app's real name (not "New Application") and add a custom icon. Let's tackle the icon first. For this, you'll need Icon Composer. You'll find that with the developer tools in /Developer/Applications/Utilities. You'll need to have your artwork complete before using this utility - Icon Composer is not a drawing program. It will, though, read in Photoshop files directly. Drag your artwork to the 128x128 pane, scale it if needed. From there, drag the 128x128 to the 48x48, scale it and let the program extract the mask. Rinse and repeat for the last two sizes. Apple-S to save. Make sure "Save into bundles" is checked, and save the file. You can then take this file and drag it into the "Resources" section of the XCode project. Choose the "Project" menu and click on the "Properties" tab. Type in the name of your icon file (I left mine "icons.icns" in the example below), and as soon as you press return, you'll see a thumbnail representation of your application icon.



Figure 8: Project properties and setting an application icon.

To update the menus, we need to double-click on the MainMenu.nib once again and launch Interface Builder. You should notice a small menubar floating just underneath the window we've been editing. If not, simply double-click on the "Main Menu" icon in the main window of Interface Builder. Editing the menu is as simple as double-clicking on each item you want to rename. You can alternatively accomplish this with the inspector pane, but this method will update the inspector as well.



Figure 9: Menu editing in action.

Quit and save. Let's build this thing into a 'real' app. In XCode, choose the "Project" menu, and then change the "Active Build Configuration" to "Release". Save and build (Apple-B) the app. The last line of the Build Results window will tell you where to pick up your Universal Binary application! Go get it and double-click to run. Exiting, huh? You can now distribute this application, and it contains everything that it needs to run - your shell script (the point of this entire exercise, remember) is bundled inside.



Figure 10: Our final application, running as a universal binary.

Keep it simple

The goal of this article was to introduce the oft-overlooked capability to easily create a GUI for a shell script using tools that Apple provides for free. While many are aware of this capability, I find it "oft-overlooked" by shell scripters, anyway. As mentioned earlier in the article, this is certainly not an exhaustive look at everything you can do, nor does it even begin to approach "best practices" (such as exhaustive error checking in a try-block, creating a proper info.plist, or even dealing with script output). If this introduction intrigues you, there are many, many places to increase your knowledge and further this path.

While I realize that this will run very much after the fact, this publication will appear during WWDC, which will be less lively without Michael Bartosh. Friend, fellow tech, fellow author and more, he will be sorely missed. Let's all remember to raise a glass - even a virtual one - in remembrance. Speaking of WWDC, I'm present to raise a real glass with anyone interested. See you at Dave's.

Media of the month: I've been too tied up in Citrix tech docs and Microsoft Group Policy to recommend anything appropriate here from a technical perspective. Actually...that may provide the perfect segue: OS X provides Windows interoperability by using the open source Samba project. By itself, Samba is an ambitious and deep project. Cleverly, Apple provides O'Reilly's entire "Using Samba, Second Edition" preloaded onto your Mac! Launch Safari and point your browser to <file:///usr/share/swat/using_samba/toc.html>. This tends to be another 'oft-overlooked' resource.

I was fortunate to meet many MacTech readers at MacWorld in January, and I hope to meet more at WWDC 2006. If you're unable to attend, look for our reports from the show. In any case, I'll see you in print next month!

References

Just about everything at http://developer.apple.com

Especially Tech Note 2065: http://developer.apple.com/technotes/tn2002/tn2065.html

The Tao of AppleScript, Derrick Schneider (yes, this came out in 1994 and shipped with a floppy of examples. AppleScript basics just haven't changed that much).

Resources

Mac Scripter: http://macscripter.net/


Ed Marczak owns and operates Radiotope, a technology consulting company. Radiotope helps separate technology issues from policy issues, cool-tech from needed-tech. Guide your decision at http://www.radiotope.com

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Viber 11.9.1 - Send messages and make fr...
Viber lets you send free messages and make free calls to other Viber users, on any device and network, in any country! Viber syncs your contacts, messages and call history with your mobile device, so... Read more
Vallum 3.3.2 - $15.00
Vallum is a little tool that helps you monitor and block apps connections and throttle apps bandwidth. It is able to intercept connections at the application layer, and hold them while you decide... Read more
Microsoft OneNote 16.31 - Free digital n...
OneNote is your very own digital notebook. With OneNote, you can capture that flash of genius, that moment of inspiration, or that list of errands that's too important to forget. Whether you're at... Read more
Apple Pages 8.2.1 - Apple's word pr...
Apple Pages is a powerful word processor that gives you everything you need to create documents that look beautiful. And read beautifully. It lets you work seamlessly between Mac and iOS devices, and... Read more
Numbers 6.2.1 - Apple's spreadsheet...
With Apple Numbers, sophisticated spreadsheets are just the start. The whole sheet is your canvas. Just add dramatic interactive charts, tables, and images that paint a revealing picture of your data... Read more
f.lux 39.9873 - Adjusts the color of you...
f.lux makes the color of your computer's display adapt to the time of day, warm at night and like sunlight during the day. Ever notice how people texting at night have that eerie blue glow? Or wake... Read more
Deeper 2.5.0 - Enable hidden features in...
Deeper is a personalization utility for macOS which allows you to enable and disable the hidden functions of the Finder, Dock, QuickTime, Safari, iTunes, login window, Spotlight, and many of Apple's... Read more
NTFS 15.5.71 - Provides full read and wr...
NTFS breaks down the barriers between Windows and macOS. Paragon NTFS effectively solves the communication problems between the Mac system and NTFS. Write, edit, copy, move, delete files on NTFS... Read more
MTR 5.3.0.0 - The Mac's oldest and...
MTR (was MacTheRipper)--the Mac's oldest and smartest DVD-backup app. MTR - the complete toolbox, not a one-trick, point-and-click extractor. MTR is intended for making fair-use, backup copies of... Read more
Keynote 9.2.1 - Apple's presentatio...
Easily create gorgeous presentations with the all-new Keynote, featuring powerful yet easy-to-use tools and dazzling effects that will make you a very hard act to follow. The Theme Chooser lets you... Read more

Latest Forum Discussions

See All

Black Desert Mobile gets an official rel...
Pearl Abyss has just announced that its highly-anticipated MMO, Black Desert Mobile, will launch globally for iOS and Android on December 11th. [Read more] | Read more »
Another Eden receives new a episode, cha...
Another Eden, WFS' popular RPG, has received another update that brings new story content to the game alongside a few new heroes to discover. [Read more] | Read more »
Overdox guide - Tips and tricks for begi...
Overdox is a clever battle royale that changes things up by adding MOBA mechanics and melee combat to the mix. This new hybrid game can be quite a bit to take in at first, so we’ve put together a list of tips to help you get a leg up on the... | Read more »
Roterra Extreme - Great Escape is a pers...
Roterra Extreme – Great Escape has been described by developers Dig-It Games as a mini-sequel to their acclaimed title Roterra: Flip the Fairytale. It continues that game's tradition of messing with which way is up, tasking you with solving... | Read more »
Hearthstone: Battlegrounds open beta lau...
Remember earlier this year when auto battlers were the latest hotness? We had Auto Chess, DOTA Underlords, Chess Rush, and more all gunning for our attention. They all had their own reasons to play, but, at least from where I'm standing, most... | Read more »
The House of Da Vinci 2 gets a new gamep...
The House of Da Vinci launched all the way back in 2017. Now, developer Blue Brain Games is gearing up to deliver a second dose of The Room-inspired puzzling. Some fresh details have now emerged, alongside the game's first official trailer. [Read... | Read more »
Shoot 'em up action awaits in Battl...
BattleBrew Productions has just introduced another entry into its award winning, barrelpunk inspired, BattleSky Brigade series. Whilst its previous title BattleSky Brigade TapTap provided fans with idle town building gameplay, this time the... | Read more »
Arcade classic R-Type Dimensions EX blas...
If you're a long time fan of shmups and have been looking for something to play lately, Tozai Games may have just released an ideal game for you on iOS. R-Type Dimensions EX brings the first R-Type and its sequel to iOS devices. [Read more] | Read more »
Intense VR first-person shooter Colonicl...
Our latest VR obsession is Colonicle, an intense VR FPS, recently released on Oculus and Google Play, courtesy of From Fake Eyes and Goboogie Games. It's a pulse-pounding multiplayer shooter which should appeal to genre fanatics and newcomers alike... | Read more »
PUBG Mobile's incoming update bring...
PUGB Mobile's newest Royale Pass season they're calling Fury of the Wasteland arrives tomorrow and with it comes a fair chunk of new content to the game. We'll be seeing a new map, weapon and even a companion system. [Read more] | Read more »

Price Scanner via MacPrices.net

New 2019 16″ MacBook Pros on sale for $100 of...
Apple Authorized Reseller Adorama has new 2019 16″ MacBook Pros on sale today for $100 off Apple’s MSRP, each including free shipping. In addition, Adorama charges sales tax for NY & NJ residents... Read more
Apple Watch Series 3 GPS models on sale for l...
Amazon has Apple Watch Series 3 GPS models on sale starting at only $179. There prices are the lowest we’ve ever seen for these models from any Apple reseller. Choose Amazon as the seller rather than... Read more
iOS Bug In Facebook News Feed Lets Device Ca...
NEWS: 11.15.19- Users of the Facebook social media platform’s mobile app running on iOS devices won’t, like, this piece of news one bit in where a bug in the News Feed gave access to the camera... Read more
16″ MacBook Pros on sale! Preorder at Amazon...
Apple’s new 16″ MacBook Pros were only introduced yesterday, but Amazon is already offering a $100 discount on preorders. Prices for the base 6-Core 16″ MacBook Pros start at $2299: – 2019 16″ 2.6GHz... Read more
Use our exclusive MacBook Price Trackers to f...
Our Apple award-winning MacBook price trackers are the best place to look for the best sales & lowest prices on new and clearance MacBook Airs and MacBook Pros–including Apple’s new 16″ MacBook... Read more
New November Verizon iPhone deal: Get an iPho...
Verizon has the 64GB iPhone Xr on sale for 50% off for a limited time, plus they will include a free $200 prepaid MasterCard and a free Amazon Echo Dot. That reduces their price for the 64GB iPhone... Read more
Apple cuts prices on clearance, refurbished 2...
Apple has clearance 2018 15″ 6-Core Touch Bar MacBook Pros, Certified Refurbished, now available starting at only $1829. Each model features a new outer case, shipping is free, and an Apple 1-year... Read more
Up to $450 price drop on clearance 15″ MacBoo...
B&H Photo has dropped prices Apple’s 2019 15″ 6-Core and 8-Core MacBook Pros by $400-$450 off original MSRP, starting at $1999, with free overnight shipping available to many addresses in the US... Read more
Here’s how to save $200 on Apple’s new 16″ Ma...
Apple has released details of their Education discount associated with the new 2019 16″ 6-Core and 8-Core MacBook Pros. Take $200 off the price of the new 8-Core model (now $2599) and $200 off the 16... Read more
Price drop! 2019 15″ 2.6GHz 6-Core MacBook Pr...
Focus Camera has dropped their price for clearance 2019 15″ 2.6GHz 6-Core Space Gray MacBook Pros by $400 to $1999 shipped. Apple’s original MSRP for this model was $2399. Focus charges sales tax for... Read more

Jobs Board

Best Buy *Apple* Computing Master - Best Bu...
**746655BR** **Job Title:** Best Buy Apple Computing Master **Job Category:** Sales **Store NUmber or Department:** 002518-Atlantic Center-Store **Job Description:** Read more
*Apple* Mobility Pro - Best Buy (United Stat...
**744973BR** **Job Title:** Apple Mobility Pro **Job Category:** Store Associates **Store NUmber or Department:** 000949-Rochester Hills-Store **Job Description:** Read more
AV Systems Engineer at *Apple* - Theorem, L...
Job Summary Apple Retail Technology is looking for an Audio Visual Systems Engineer to design and implement scalable, next-generation A/V solutions for Apple ?s Read more
Nurse Practitioner - Field Based (San Bernard...
Nurse Practitioner - Field Based (San Bernardino, CA, Apple Valley, Hesperia) **Location:** **United States** **New** **Requisition #:** PS30312 **Post Date:** 3 Read more
Best Buy *Apple* Computing Master - Best Bu...
**746510BR** **Job Title:** Best Buy Apple Computing Master **Job Category:** Store Associates **Store NUmber or Department:** 001407-Milford-Store **Job Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.