TweetFollow Us on Twitter

Designing Interface Builder Palettes

Volume Number: 19 (2003)
Issue Number: 6
Column Tag: Programming

Designing Interface Builder Palettes

Simple To Advanced Palette Design

by Ed VanVliet

Introduction

Anytime you have a reusable user interface component you should consider integrating it into Interface Builder as a palette so it is readily accessible. This article describes how to make a simple Interface Builder palette and also explains some design issues encountered for more advanced palettes via the graph palette that was implemented at VVI(R). By way of introduction, Figure 1 shows the graph palette being used in an example application project.


Figure 1: The Graph Interface Builder Palette In Use

To make such an application, launch Project Builder and make a new Application-based project. That project includes the Interface Builder nib file called MainMenu.nib. Double click that nib file from within Project Builder to open it. That nib file contains an Application Menu and Main Window by default as shown in Figure 1. Drag a new Pie Chart from the Graph Palette to the Main Window of the project, resized it accordingly and finally use the Graph View Inspector to change the pie chart to a line graph representation, as shown on the Main Window in Figure 1. Then save the project to the disk. That is all that is needed to add a basic graph to an application.

The aim of this article is to describe how easy it is to make a palette similar to that used above, to trim off a few rough edges that you will encounter when you make your own Interface Builder palette and then to describe an advanced palette design. But, before going into those details lets first complete the example application just described by adding data to it.

Completing The Graph Project

The only thing left to do in the application described above is to add your own data to the graph while the application runs. To do that, add a new controller class, called EX_Controller, to the project using File > New File > Objective-C class. Then add the ivar EX_test_view to its interface in the file EX_Controller.h and add the following code section to its implementation in the file EX_Controller.m:

- (void)awakeFromNib
{
   NSString *inputString, *stringFormat;
   NSString *mainTitle, *xTitle, *yTitle;
   unsigned chartType;
   double value1, value2, value3, value4;
/* The following define the attributes of the column chart. */
   chartType = VP_COLUMN_OUTPUT_TYPE;
   mainTitle = @"This Is My Main Title";
   xTitle = @"My X-Axis";
   yTitle = @"My Y-Data!";
/* The following data is hardcoded, but could have come from any source, such as a database 
server. */
   value1 = 100.0;
   value2 = 50.0;
   value3 = 77.0;
   value4 = 22.0;
/* The attributes and data above are formatted into a string according to the specifications in 
the documentation. */
   stringFormat = @"%@&%@&%@&%f,%f,%f,%f";
   inputString = [NSString stringWithFormat:stringFormat
      , mainTitle, xTitle, yTitle
      , value1, value2, value3, value4];
/* The following updates the view with the input string and type information, which will enable 
the graph view to update to the new graph when needed. */
   [EX_test_view VPN_update_using_input_string:inputString
      output_type:chartType];
}

The graph view definitions are maintained in the Vvidget_VP framework, so import that framework at the top of EX_Controller.m using this code:

#import <Vvidget_VP/Vvidget_VP>;

Finally, include that Vvidget_VP framework as a framework to link against in the application project.

Then double click MainMenu.nib to launch Interface Builder read in the EX_Controller class definition (Using Class > Read Files ...) , instantiate it and connect the EX_test_view outlet of that instantiation to the graph view. Then rebuild the project, launch the resulting application and see the data on the graph. Notice that a pie chart was dragged from the palette, it was changed to a line graph using the Graph View Inspector in Interface Builder and the example application changed that to a column chart when it executed. This example project and the graph palette may be downloaded at http://www.vvi.com/download/vvidgetuser.

Notice how easy it was to make the graph and how virtually no description of programming or underlying implementation was needed. The next sections correct this situation by first explaining how to make your own palette and then giving a high-level overview of the graph palette design in order to show how a large project may be handled in Interface Builder.

Making A Simple Palette

Use Project Builder to make a palette from scratch. Launch Project Builder, choose File > New Project and select Standard Apple Plug-ins > IBPalette. Then name it and save it. I saved it as the name MyIBView, so the result is a project with that name. In that project are a few premade class files and nib files as shown in Figure 2. The objective of a palette is to quickly set states of a controlled object, so the next step is to add some state information to the object controlled by the palette.


Figure 2: MyIBView Project Builder and the MyIBViewPalette Interface Builder files

There are three types of objects (Classes) in the palette, MyIBView, MyIBViewPalette and MyIBViewInspector. MyIBView is a view class and the palette is responsible for defining that class and making and modifying views (instances) of that class. A view is a rectangular area that draws in a window so the next step is to implement that functionality.

MyIBView is declared in the file MyIBView.h. That file must be modified to declare some sort of state information. The state used in this example is a background color. To add that state implement the interface of the class like this:

@interface MyIBView : NSView
{
   NSColor *backgroundColor;
}
@end

The file MyIBView.m defines the implementation of the MyIBView, and that is where view-related code that gets executed by the palette should be placed. The main thing the view does is draw a background. Drawing for a view is accomplished by the method named drawRect: so add this method:

- (void)drawRect:(NSRect)aRect
{
   [backgroundColor set];
   NSRectFill([self bounds]);
}

The view must initialize its state, which is done by this method:

- (id)initWithFrame:(NSRect)aRect
{
   [super initWithFrame:aRect];
   backgroundColor = [[NSColor redColor] retain];
   return self;
}

Because the view state will be stored in an application-related Interface Builder nib file the view must be able to store and retrieve its state using the standard Cocoa coder. The following methods do that:

- (id)initWithCoder:(NSCoder *)decoder
{
   self = [super initWithCoder:decoder];
   backgroundColor = [[decoder decodeObject] retain];
   return self;
}
- (void)encodeWithCoder:(NSCoder *)coder
{
   [super encodeWithCoder:coder];
   [coder encodeObject:backgroundColor];
}

Finally, the view needs to be able to allow external objects (calling code, such as an Inspector) to set and get its state. That is accomplished by these methods:

- (void)setBackgroundColor:(NSColor *)aColor
{
   if(aColor != backgroundColor)
   {
      [backgroundColor release];
      backgroundColor = aColor;
      [self setNeedsDisplay:YES];
   }
}
- (NSColor *)backgroundColor
{
   return backgroundColor;
}

If the view gets removed then it must be able to release its resources. That is accomplished by the dealloc method:

- (void)dealloc
{
   [backgroundColor release];
   [super dealloc];
}

A view will be removed (released) if the window it is on is closed (and the window is marked to release), if it is cut from the Interface Builder window it is on, or some other condition like that so it is important to release its resources.

That is all that is needed to define the state and functionality of the view. The next step is to locate that view on the palette itself. The palette interface configuration is maintained in an Interface Builder file called MyIBViewPalette.nib. Find that file within the project and double click it and drag out a CustomView (from the Cocoa-Containers palette) onto the Palette Window. Click on that CustomView, type Apple-5 and in the resulting Custom Class Inspector find MyIBView and click it. The CustomView will now instantiate as a MyIBView instance, which means the drawRect: method and other code implemented above will be executed by the palette when it is run. Save the nib file and build the result in Project Builder. You are done making the palette, so make sure to quit Interface Builder and Project Builder.

Testing The Simple Palette With An Example Application

Using the Finder locate the palette, named MyIBView.palette, that you just built. Normally it is in the build subfolder of the palette project. Double click MyIBView.palette to launch Interface Builder and to add the palette to the list of palettes to use in Interface Builder. See the resulting red rectangle in the Palette window of Interface Builder? That is your view drawing there. You can now add it to your own applications when you want to.

To make an example application, first quit Interface Builder. Then launch Project Builder, choose File > New Project and select Application > Cocoa Application. Click Next and save it as MyApplication. MyApplication has a file called MainMenu.nib in the Resource Folder of the project. Double click that to launch Interface Builder, drag your red rectangle onto the resulting window and then save it. You cannot run it yet because, while Interface Builder can execute MyIBView through the loaded palette plug-in, MyApplication cannot because it is a completely separate program. You must first create the MyIBView class in the MyApplication project. To do that click on the Classes folder then click File > New File and choose Objective-C NSView subclass, then name it as MyIBView and click Finish. The results are two files called MyIBView.m and MyIBView.h. Add to the content of those files the same lines of code that you did for the corresponding files in the MyIBView palette project. Then build and run your application from Project Builder. When run, a window comes forward with the red rectangle defined by the MyIBView instance.

You have just made a palette and a custom application that uses that palette to do some drawing. To extend it, go back to the palette project and add additional state and implementation code. Repeat that process until you get the type of drawing you want. The next sections describe how to refine the palette a bit and then describe some of the broader issues encountered in a more advanced palette implementation.

Adding An Attribute Inspector To The Simple Palette

Notice that the view of class MyIBView in Interface Builder has no Attributes Inspector. That is because you did not add any controls to the inspector in the MyIBView palette project. To do that launch your MyIBView project, go to the Resources folder and double click the file named MyIBViewInspector.nib to launch Interface Builder. Within the Class tab follow the class hierarchy to IBInspector where you will find something like this:

NSObject > IBInspector > _ROJECTNAMEASIDENTIFIERIjinspector

You need to change the last part to MyIBViewInspector to make things work, obviously a small template parsing problem while making new IB palettes (This bug is in version 2.3 of Interface Builder and may be fixed in later versions). Then click on the Instance tab, click on the File's Owner and in the Custom Class inspector click MyIBViewInspector. Now you will be able to make connections, add new outlets and actions, etc. to the File's Owner.

The palette controls the view of class MyIBView. That view has a background color as its only added attribute. So, a likely improvement is to add a control that modifies color. To do that drag a color well onto the Inspector Window, control drag from that color well to the File's Owner and then connect the color well's target outlet to the ok: action of the File's Owner. Then save the nib file and quit Interface Builder. In MyIBViewInspector.m modify this code:

- (void)ok:(id)sender
{
   /* Your code Here */
      [super ok:sender];
}
to this:
- (void)ok:(id)sender
{
   id myView = [self object];
   [myView setBackgroundColor:[sender color]];
   [super ok:sender];
}

The color well's action is the ok: method which, by the implementation above, will modify the background color of the view. Everything is done so rebuild the MyIBView project. Next, launch your MyApplication project, double click MainMenu.nib to launch Interface Builder again (this time it loads with the new inspector), click on your red view and type Apple-1 to bring forward the Attributes inspector. This time it has a color well on it. Click on the color well frame to bring forward the color panel. Change the color and watch the color attribute change in the color well and, because the target of the well is the ok: method, which forwards the action to your view, your view's background color also changes.

You have built a palette, made an example application using that palette and extended the palette to permit a state change of your own view within Interface Builder. That is a pretty good start, but a lot of improvements and design issues have yet to be touched upon. The next sections outline some of those issues.

Some Problems With The Simple Palette

The simple palette has already come a long way and it is a good starting point, but there are quite a few problems with it, some of which are listed here:

  • The declaration and definition of MyIBView are maintained in two places. They are in the palette project and separately in the example application project and for every new project that uses that view class they have to be placed there too. That can cause a code maintenance issue. To solve this problem you can make a third project which is a framework and move the declaration and definition of MyIBView to that framework and then link the palette, the example application and any future projects to that framework.

  • The implementation of the ok: method assumes the sender is a color well. That is problematic because if the inspector is updated to have two controls then the sender can be either one of the controls. There are a few ways around this issue, the easiest is to assign each control to an ivar of the inspector and then to test which ivar the sender is. The other option is to make additional action methods and make each one of those a target of only one control, such as this:

- (void)changeBackgroundColor:(id)sender
{
   id myView = [self object];
   [myView setBackgroundColor:[sender color]];
   [super ok:sender];
}
  • If you add new states to MyIBView and implement their store in the coding methods then MyApplication project will stop working. That is because the states were previously stored in the MainMenu.nib file as defined by the old version of the coding methods which are inconsistent with the new version of the coding methods. The state coding methods shown above rely on the old-style coding where the implementer needs to manage versioning manually. The newer key-value type archiving solves this problem to some extent. This issue is easily dealt with, but it is something that needs to be kept in mind while iterating a palette design. The easiest solution is to iterate the palette design to a final product without making an example project, release the palette at that version and then deal with versioning issues in a future release, but not necessarily while iterating the design of the palette.

  • Many non-essential details, such as declaring the method prototypes in header files and implementing attribute loading code in the inspector have not been shown here and are left to the reader to implement.

    Other than that, the simple palette project is ready to be extended by adding more state variables (ivars), attribute set and get methods, coding additional states, adding more controls to the inspector and, finally, because it's all about drawing, to use that state information for drawing in the view's rectangular region.

    Design Of The Graph Palette

    The example palette described above is a handful of lines long, pretty small. But what happens when the attributes, features and code grows? How does the paradigm scale and how would it need to be changed to accommodate scale-dependent issues when the code base approaches a million lines of code? The programming environment on Mac OS X permits an arbitrary amount of code to be loaded into Interface Builder as Frameworks and Bundles so conceivably anything can be inserted into Interface Builder. Early on one of our palette implementations loaded all of our frameworks, initialized our whole environment and gave access to attributes that were many times greater than all of those available in Interface Builder by default. The system depended on running two independent document and inspector systems in parallel. It worked reasonable well, but suffered from a major design flaw: it gave the ultimate flexibility to solve a vast amount of problems, but did not solve the pertinent problem well. That is because users of the palette typically did not ask "how can I adjust that attribute?", rather they ask: "how can I get a line plot" or similar final result.

    After many other design attempts a client server implementation was chosen. That system, called the Peer Visual(TM) Server, is diagrammed in Figure 3. The server is capable of handling about 1000 simultaneous requests. Some are transitory such as requests from web browsers and some are dedicated like requests from an Interface Builder view. For each graph dragged from the palette to the application windows, such as in Figure 1, a new dedicated connection is made. The connections are load balanced amongst several servers (2 by default) and delegated to different threads within the servers. The multi-process, threaded and parallel nature of the implementation means that a multi-CPU computer is used to its fullest extent by the Interface Builder views. The other major benefit to this design is that the client applications do not have to load in the frameworks that make the graphs because they reside in another process space.


    Figure 3: Peer Visual Server And The Interface Builder Palette

    The design also incorporates a server monitor that starts the servers on demand, checks for valid connections, rolls over servers in the case of an error, and in the unlikely event that generating a graph encounters a terminal error the Monitor restarts a server for a client. This gives added protection to applications using this system, i.e.: an error on the server side will not terminate the client side process. This also has a good programming benefit in that there are no namespace, process address space, or run time resource conflicts between the client and the server.

    The server is fully programmable, extensible and has access to all the attributes of the frameworks it depends on. That means the server can be extended to make nearly any type of report or graphic and access any database or other data source all while maintaining the infrastructure of the client server model and Interface Builder implementation, so that conceivably all output of the frameworks can be inserted into Interface Builder without the problematic issues encountered in the earlier homogeneous implementation mentioned above.

    The graph palette was made in the same way as the Simple Palette described above, except that the state information is not a background color, but rather an input string, chart type and a Peer Visual Server connection. Other than that, the two palette implementations are basically the same.

    The other advantage to the graph palette implementation is that the client may be a Cocoa, Java, Carbon or other type of implementation while the Peer Visual Server can maintain its own implementation criterion. You can find an example of this heterogeneous use at www.marketocracy.com where visual formats from the Peer Visual Server help members manage very successful mutual funds like the fund shown in Figure 4.


    Figure 4: Output Of Custom Peer Visual Server From www.marketocracy.com (Courtesy of Marketocracy(R), Inc).

    In this case, the Peer Visual Server outputs its results to a web browser, but because of the client server architecture that same Peer Visual Server can be used to make a desktop application without any alteration of the server code. The design is also used to off-load the data query, modeling computation and resulting visualization portion of the display to a separate computer so that it enables the Interface Builder palette to incorporate distributed computing. In addition, the graphical layout of the output is maintained in a separate coded state maintained by a widget builder called Vvidget Builder(TM) which is designed to handle data-related diagramming and graphs (the figures for this article were made with Vvidget Builder). In that way, the graph state and function is partitioned from the Interface Builder palette implementation so, for example, it does not suffer from the versioning problem described above.

    Conclusion

    For simple functionality, such as a dial or simple control with few attributes the normal Interface Builder plug-in model may be sufficient. But that model suffers from many ills found in homogeneous software architectures. Those ills were mentioned in previous sections and are fundamental to large-scale processing and software design and are not unique to Interface Builder. The client server architecture of the Peer Visual Server addressed those ills in a straight forward way and broadens the applicability of the implementation by permitting reuse of the system with the Interface Builder graph palette as well as different client environments such as Cocoa, Carbon and Java and different client interfaces from desktop applications to web browsers. In that sense, Interface Builder is not a tool to solve all problems, but rather a tool that permits easy access to heterogeneous systems from within a desktop application through palette extensions. So, it is the recognition of that applicability of the Interface Builder palette paradigm that is the main point of this article.

    References

    You can download the graph palette and supporting code, example project, documentation, graphing server, Vvidget Builder layout application and other resources at http://www.vvi.com/download/vvidgetuser. You can also get one million dollars, professional fund-managment tools with great looking reports and graphs and have the opportunity to become a very successful mutual fund manager at www.marketocracy.com. The dollars are virtual, but the underlying software and results are not.

    Legal

    VVI is a Registered Trademark of VVimaging, Inc. VVI, Vvidget, Vvidget Builder, Vvidget User, Peer Visual and VVimaging are trademarks of VVimaging, Inc. in the United States and world-wide. Marketocracy is a Registered Trademark of Marketocracy, Inc. References to Marketocracy are for informational purposes only.


    Ed VanVliet is Director Of Application Development at VVI where he helps design and construct business and engineering data systems. He designed the Peer Visual Server as well as interfaces to database systems, instrumentation and real-time data feeds and is currently working on a variety of systems and conversions between Windows and Mac OS X for business and engineering companies. You can contact him at ed@vvi.com.

 
AAPL
$567.34
Apple Inc.
+42.59
MSFT
$39.37
Microsoft Corpora
-0.32
GOOG
$527.22
Google Inc.
+0.28

MacTech Search:
Community Search:

Software Updates via MacUpdate

Cyberduck 4.4.4 - FTP and SFTP browser....
Cyberduck is a robust FTP/FTP-TLS/SFTP browser for the Mac whose lack of visual clutter and cleverly intuitive features make it easy to use. Support for external editors and system technologies such... Read more
TechTool Pro 7.0.3 - Hard drive and syst...
TechTool Pro is now 7, and this is the most advanced version of the acclaimed Macintosh troubleshooting utility created in its 20-year history. Micromat has redeveloped TechTool Pro 7 to be fully 64... Read more
MacFamilyTree 7.1.6 - Create and explore...
MacFamilyTree gives genealogy a facelift: it's modern, interactive, incredibly fast, and easy to use. We're convinced that generations of chroniclers would have loved to trade in their genealogy... Read more
EtreCheck 1.9.9 - For troubleshooting yo...
EtreCheck is a simple little app to display the important details of your system configuration and allow you to copy that information to the Clipboard. It is meant to be used with Apple Support... Read more
TeamViewer 9.0.28116 - Establish remote...
TeamViewer gives you remote control of any computer or Mac over the Internet within seconds, or can be used for online meetings. Find out why more than 200 million users trust TeamViewer! Free for... Read more
Viber 4.1.0 - Send messages and make cal...
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,... Read more
Apple iOS 7.1.1 - The latest version of...
The latest version of iOS can be downloaded through iTunes. Apple iOS 7 brings an all-new design and all-new features. Simplicity Simplicity is often equated with minimalism. Yet true simplicity is... Read more
1Password 4.3 - Powerful password manage...
1Password is a password manager that uniquely brings you both security and convenience. It is the only program that provides anti-phishing protection and goes beyond password management by adding Web... Read more
Lens Blur 1.3.0 - True out-of-focus boke...
Let Lens Blur transform your existing photo into true SLR-quality out-of-focus bokeh effect! Everyone needs a gorgeous personalized background for a social profile, blog, Web/UI design, presentation... Read more
VMware Fusion 6.0.3 - Run Windows apps a...
VMware Fusion allows you to create a Virtual Machine on your Mac and run Windows (including Windows 8.1) and Windows software on your Mac. Run your favorite Windows applications alongside Mac... Read more

Latest Forum Discussions

See All

Galaxy Conquerors Review
Galaxy Conquerors Review By Jennifer Allen on April 24th, 2014 Our Rating: :: RETRO SHOOTINGUniversal App - Designed for iPhone and iPad Old school shooting is fun but inaccurate in Galaxy Conquerors.   | Read more »
Yomi Review
Yomi Review By Rob Thomas on April 24th, 2014 Our Rating: :: C-C-C-COMBO BREAKERiPad Only App - Designed for the iPad Round One – Fight! No quarters required for this iOS adaptation of a tabletop adaptation of the arcade fighting... | Read more »
Injustice: Gods Among Us Updated with Ne...
Injustice: Gods Among Us Updated with New Characters, Leaderboards, Gear, and Online Multiplayer Posted by Rob Rich on April 24th, 2014 [ | Read more »
Spin It Review
Spin It Review By Jordan Minor on April 24th, 2014 Our Rating: :: SPIN ME RIGHT ROUNDUniversal App - Designed for iPhone and iPad Spin It has a fine puzzle game model, but its execution lacks energy.   | Read more »
Productivity App NoteSuite is Having its...
Productivity App NoteSuite is Having its Biggest Sale Ever, Just for One Week Posted by Rob Rich on April 24th, 2014 [ permalink ] | Read more »
Wayward Souls Review
Wayward Souls Review By Carter Dotson on April 24th, 2014 Our Rating: :: CARRY ON, WAYWARD SONUniversal App - Designed for iPhone and iPad Wayward Souls is a roguelike-inspired action-RPG that sets a high bar for other games to... | Read more »
The Sandbox Gets Update, Receives New Ca...
The Sandbox Gets Update, Receives New Campaign and New Elements Posted by Tre Lawrence on April 24th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Football Management Simulator One For El...
Football Management Simulator One For Eleven Released Worldwide Today for iOS Posted by Simon Reed on April 24th, 2014 [ permalink ] Free-To-Play football management title One For E | Read more »
Leo’s Fortune Review
Leo’s Fortune Review By Jordan Minor on April 24th, 2014 Our Rating: :: FORTUNATE SONUniversal App - Designed for iPhone and iPad Leo’s Fortune delivers a platforming experience as creative and refined as any console game.   | Read more »
Suited Up (Games)
Suited Up 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: Suited Up is a difficult, one-touch platformer that requires players to visualize each jump. The controls in Suited Up are simple,... | Read more »

Price Scanner via MacPrices.net

16GB 1st generation iPad mini available for $...
Radio Shack has a select number of refurbished 1st generation 16GB WiFi iPad minis available for $199.99 on their online store. Choose free shipping or free ship-to-store. We expect these to sell out... Read more
13-inch 2.5GHz MacBook Pro on sale for $100 o...
B&H Photo has the 13″ 2.5GHz MacBook Pro on sale for $1099 including free shipping plus NY sales tax only. Their price is $100 off MSRP. Read more
iPad Sales “Lull” A Reality Correction Of Unm...
I have lots of time for Jean-Louis Gassée, the former Apple Computer executive (1981 to 1990) who succeeded Steve Jobs as head of Macintosh development when the latter was dismissed in 1985. Mr.... Read more
Apple Makes OS X Betas Available To All – Wit...
Apple’s OS X Beta Seed Program, which lets you install the latest pre-release builds, try it out, and submit your feedback, is now open to anyone who wants to sign on rather than to developers and... Read more
Apple Releases iOS 7.1.1 Update
The latest iOS 7.1.1 update contains improvements, bug fixes and security updates, including: • Further improvements to Touch ID fingerprint recognition • Fixes a bug that could impact keyboard... Read more
Logitech Announces Thinner, Lighter, More Fle...
Logitech has announced an update to its Ultrathin for iPad Air, iPad mini and iPad mini with Retina display, improving the flexibility and design of its award-winning predecessor with an even thinner... Read more
Logitech Introduces Hinge, Big Bang and Turna...
Logitech has announced expansion of its tablet product line with three new cases – the Logitech Hinge, the Logitech Big Bang and the Logitech Turnaround – each for the iPad Air, iPad mini and iPad... Read more
WaterField’s Rough Rider Leather Messenger Ba...
WaterField Designs have announced the new 15-inch size of their popular Rough Rider leather messenger bag, a vintage-looking bag that combines Old West charm and ruggedness with distinctly modern... Read more
New Mac Pro on sale, save $100 on the 4-Core...
J&R has the new 4-Core Mac Pro in stock today and on sale for $2899 including free shipping plus NY sales tax only. Their price is $100 off MSRP, and it’s the lowest price available for this... Read more
Apple refurbished iMacs available for up to $...
The Apple Store has Apple Certified Refurbished 2013 iMacs available for up to $300 off the cost of new models. Apple’s one-year warranty is standard, and shipping is free. - 27″ 3.4GHz iMac – $1699... Read more

Jobs Board

*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
Position Opening at *Apple* - Apple (United...
…customers purchase our products, you're the one who helps them get more out of their new Apple technology. Your day in the Apple Store is filled with a range of Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
*Apple* Inc. Research Data Specialist - Appl...
…of Worldwide Market Research & Intelligence. The team is responsible for conducting Apple branded consumer market research. It is also responsible for analyzing data Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.