TweetFollow Us on Twitter

The Road to Code: More Cocoa Bits

Volume Number: 24 (2008)
Issue Number: 06
Column Tag: The Road to Code

The Road to Code: More Cocoa Bits

Interface Builder UI tweaking and introduction to table view

by Dave Dribin

Customizing the User Interface

Last month in The Road to Code we went over how to customize application behavior using notifications and delegates. This month we're going start off talking about how you can customize the user interface in Interface Builder. There's a lot you can tweak without writing a line of code.

Window Resizing

One important aspect of user interface design is how the window and its views and controls react to resizing. Improper resizing may confuse the user and lead to a bad user experience. You control how resizing affects each and every view and control within Interface Builder. Unfortunately, the defaults are rarely useful. For example, if we resize our Hello World window with the default settings, it will look similar to Figure 1.

Figure 1: Improper window resizing

As you resize, all the controls will be bunched up in the upper-left portion of the window. This isn't really a good use of the extra space. The text fields on the right should expand to the full width of the window, and the Calculate button should also stick to the right side of the window. Thus we want the window to look similar to Figure 2 when resized.

Figure 2: Proper window resizing

I've also kept the Calculate button on the bottom of the window. You could also keep it pinned towards the top, but for demonstration purposes, I'm going to keep it on the bottom. In order to make our window properly resize like this, we need to open Interface Builder.

Select the text field next to the Rectangle Width label. Next, open up the Inspector panel and select the Size tab; it's third from the left with the ruler icon. It should look similar to Figure 3.

Figure 3: Size panel of the Inspector

This panel contains information about the size of the selected view. The Autosizing section is the part that dictates how the control behaves when the window is resized. The left portion of the autosizing section is called the springs and struts. There are six lines you can click on and activate, two on the inside and four on the outside. The two on the inside are called springs and the four on the outside are called struts as noted in Figure 4.

Figure 4: Autosizing springs and struts

When a specific string or strut is activated, it is colored red and has a solid line. When not activated, it is colored light red with a dotted line. An activated spring indicates that the width or height of the view expands and contracts in proportion to its superview. An activated strut indicates that the view maintains a fixed distance between its edge and the same edge of its superview. The right portion of autosizing section is an animated preview showing you how the settings will affect the view. You should see the animation change as you activate and deactivate springs and struts.

The animated preview is handy, but sometimes you need to actually run the application and try resizing the window to verify your settings. While you can go back to Xcode and run the application, Interface Builder allows you to simulate the interface without switching to Xcode. Choose the File > Simulate Interface menu or Command-R to do this. While simulating the interface, you may resize the window and watch how the views react. When you are done, you need to quit the Cocoa Simulator using the menu or Command-Q. Between the animation preview and the simulator, you should be able to find the correct springs and struts settings for your application without ever switching to Xcode.

The default setting, as shown in Figure 4 above, is to have the top and left struts activated and no springs activated. This explains why all of our controls are bunched up in the upper left portion of the window. For our text fields, we want to activate the horizontal spring and the left, right, and top struts. This will cause them to resize horizontally while staying pinned on the left, right, and top. The final settings should look like Figure 5.

Figure 5: Autosizing for text fields

For the Calculate button, we don't want any springs activated. The default settings have only the top and left struts activated, so we need to change this again. We want only the right and bottom struts activated. This will keep the button pinned to the lower right portion of the window. The final settings should look like Figure 6.

Figure 6: Autosizing for button

Try simulating the user interface, and see if it behaves correctly. It should now work as shown in Figure 2. Once it works, save the nib file, switch back to Xcode, and run the application. Again, the controls should resize appropriately.

There's one final aspect of our resizing that's not quite right. While making the window bigger works fine, it is possible to resize the window so small such that not all of our controls will fit in the window. To prevent this, we can specify a minimum size for our window. The window's sizes can be viewed and set in the Size pane of the Inspector window, as well. If you select the window by clicking on its title bar the Size pane should look similar to Figure 7.

Figure 7: Window size

You can see that our window has neither a minimum nor maximum size. Click on the Has Minimum Size checkbox to enable a minimum size. I think the window as currently laid out makes a nice minimum size, so click the Use Current button to set the minimum size to the window's current size. If you now simulate the user interface, you should be able to resize the window larger and smaller, as before, but you should not be allowed to resize it any smaller than the defined size. This is perfect, so save the nib file. If you want, you may provide a maximum size, too. I'm going to keep the maximum size disabled so the user can make the window as large as they want.

Resizing the window in Interface Builder

You can now properly resize the window in a running application, but what about resizing the window in Interface Builder? You can resize the window by dragging the resize corner, just as in a running application. However, the controls inside the window do not resize according to their autosizing settings. This may be fine if you are resizing the window to make room for more views. However, if you just want to make the window larger or smaller, it can be a chore to go through and manually resize each view and control after resizing the window. Fortunately there is a trick. If you hold down the Command key while resizing the window in Interface Builder, the controls will also resize according to their autosizing settings. If, for some reason, you forget to hold down Command while resizing the window, Interface Builder allows you to undo the resize. Then you can redo it while holding down the Command key.

Formatters

By default, text fields can display and accept any text. Sometimes, however, the text fields need stricter formatting. Our rectangle program is a perfect example. The rectangle values are all floating point numbers. Maybe we would like to control how many decimal points are displayed. Also, our user interface doesn't stop the user from entering letters into the width and height fields. Other applications may like to format numbers in text fields as currency or percentages.

Luckily Cocoa has just the solution for us, called formatters. Formatters can be added to any text field to customize how objects are presented to the user. Interface Builder comes with two built-in types of formatters that you will use frequently: number formatters and date formatters. Number formatters take a number, usually a floating point number, and format it better. They are quite flexible and can be used to customize how decimal points are used, as well as allowing you to add comma separators for numbers over a thousand and format numbers as currency and percentages. To apply a formatter to a text field, drag it from the Library panel on top of a text field, as in Figure 8. Date formatters are used to customize the presentation of NSDate objects.

Figure 8: Adding a number formatter

The formatter is now attached to the text field. Interface Builder shows this by adding an icon of the formatter just below the text field as shown in Figure 9.

Figure 9: Text field with an attached formatter

By clicking on the formatter icon, you can change its attributes. Click on the formatter now, and the Attributes pane of the Inspector panel should update as in Figure 10. The Style pull-down menu offers various pre-configured formats. Set the Style to be Decimal.

Figure 10: Number formatter attributes

Now add a formatter with the Decimal style to the other numeric text fields, as well. If you would like, you can customize the decimal field to show one digit after the decimal point by setting the Minimum Fraction Digits to 1. When you run the application with formatters in place, numbers over 1,000 should be formatted appropriately as shown in Figure 11.

Figure 11: An application with formatters

Formatters not only convert from an object to text, but they also convert text back into an object. For number formatters, they are converted to NSNumber objects. The most important benefit we get out of using number formatters for input is that it restricts the user input to numbers only. If the user enters letters, the formatter will remove them from the text field.

With the autosizing properly set up, the minimum window size in place, and formatters on the text fields, our user interface is now nicely polished. And we didn't have to write a single line of code. All the tweaking was done using Interface Builder. The final code for this project may be found on the MacTech website.

Table Views

I'd like to shift gears a bit and get back to code and talk about a popular control called a table view. A table view is a control, like buttons and text fields, and is implemented by the NSTableView class. It displays rows and columns of information, similar to a spreadsheet application. It is a powerful control that is used in many applications.

Because a table view may display large amounts of information, the view class itself does not hold all the data. Instead, the table view requires a separate class that provides the data called a data source. Whenever the table view needs to display data for a specific row and column, it asks the data source for this information.

In last month's article, we talked about notifications and delegates as a way to customize user interface behavior in code, and data sources are very similar to delegates. A data source class must also implement specific methods. A table view may have both a delegate and a data source. The table view's delegate is only used for customizing the behavior of the view itself, just like the window and application delegates from last month. The same class may even implement the table view data source and delegate methods.

Let's go over a simple example of a table view and its data source. We're going to ignore the table view delegate and use the default behavior. Create a new Cocoa Application project in Xcode and open up its MainMenu.nib file in Interface Builder. You should have a blank window. Now, find the table view in the Library panel and drag it to the window. Resize the table view so that there is a small border around all sides. Finally, active all the springs and struts for the table view. This should allow the table view to expand vertically and horizontally as the window is resized.

Next, let's look at the attributes for a table view that are available in Interface Builder. Because a table view is enclosed in a scroll view, it can sometimes be a bit tricky to choose the table view. With the Attributes pane of the Inspector panel selected, click on the table view. Most likely, this will select the outer scroll view, which will have attributes that look like Figure 12. You may customize how the scroll bars, or scrollers, are displayed from this panel. The default is fine for us.

Clicking on the table view again should select the table view itself, and the Attributes pane should look similar to Figure 13. Now you can customize attributes of the table view itself, such as how many columns it has and various selection possibilities. Again, we're going to leave the default settings, but we will be coming back to this shortly.

Figure 12: Scroll view attributes

Oh, and because selecting the scroll view and table view can be a bit tricky, I'm going to let you in on a little secret that may help out. You can customize how Interface Builder shows the components in the nib. If you select list mode from the toolbar, you will be presented with a hierarchical list of components, instead of just icons. From this view, you may open up the disclosure triangles to select the scroll view or table view directly, as in Figure 14. Using list mode is often very helpful in selecting nested views, such as table views, tab views, and split views.

With the table view selected, you can now select individual table columns and change their attributes. After selecting the first table column, set its title and identifier to Column 1 and One, respectively, as shown in Figure 15. Now change the second column to have its title and identifier to be Column 2 and Two, respectively.

Figure 13: Table view attributes

Figure 14: List mode of Interface Builder

Figure 15: Table column attributes

If you save the nib and run the application from Xcode, you should get a window and table view, but the table view should be empty. In order to get data into the table view, we need to implement a data source in code. Create a new Objective-C class and name it MyController. In order for this class to be a table view data source, it must implement at least two methods. Here's the first one:

- (NSInteger) numberOfRowsInTableView: (NSTableView *) tableView;
{
    return 3;
}

The purpose of this method is self-explanatory: it sets the number of rows for a given table view. While the number of columns is set in Interface Builder, the number of rows is set in your code. For demonstration purposes we are returning a constant value of 3, which means three rows will be displayed.

Every row and column refers to a particular value in the table called a table cell. The second method that you must implement provides the actual data for each cell:

- (id) tableView: (NSTableView *) tableView
objectValueForTableColumn: (NSTableColumn *) tableColumn
            row: (NSInteger) rowIndex
{
    NSString * identifier = [tableColumn identifier];
    return [NSString stringWithFormat:
            @"%@ %d", identifier, rowIndex];
}

This method gets called for each and every cell in the table. You'll notice that it passes a table column object, NSTableColumn, and a row index. You may be surprised that it does not pass a column index, too. The problem is that the user is free to re-order columns, and this would make the column index pretty useless. From column object, we can get the identifier we setup in Interface Builder. The identifier is a much more reliable value than the column index, thus you can see why using a unique and meaningful identifier is very useful. For testing purposes, we are returning a string using the table column identifier and the row index.

We're almost ready to run our application, but first we need to tell the table view that MyController is its data source. Be sure to save all your files in Xcode and switch to Interface Builder. Find NSObject in the Library panel and drag it to you MainMenu.nib window. Set the class of this new object to be MyController in the Inspector panel. This creates an instance of the MyController class inside the nib.

Hooking this object up to the table view is similar connecting a delegate. You need to control-drag from the table view to the controller object. Be sure you are dragging from the table view and not the scroll view or the table column. Use list mode, if you have trouble selecting the table view. Once you control-drag from the table view to the controller object, Interface Builder should popup a menu allowing you to choose the outlet for connection. Two choices exists for table views: dataSource and delegate. Choose dataSource from the menu, as shown in Figure 16.

Figure 16: Connecting a data source

Now, save the nib, switch back to Xcode, and run the application. If all goes well, you should see a window similar to Figure 17. There should be three rows in the table and the contents of each table cell should be a mix of the table column identifier and the row index. You can even re-order the table columns if you want, and the table cell values should remain the same.

Figure 17: Simple table application

A Useful Table Example

Admittedly, that example is not very useful, so let's spice it up. Let's bring back our trusty Rectangle class and create an application to show a list of rectangles along with their area and perimeters. Add the Rectangle.h and Rectangle.m files to your Xcode project. For reference, the header file is shown in Listing 1.

Listing 1: Rectangle.h header file

#import <Foundation/Foundation.h>
@interface Rectangle : NSObject
{
    float _leftX;
    float _bottomY;
    float _width;
    float _height;
}
@property float leftX;
@property float bottomY;
@property float width;
@property float height;
@property (readonly) float area;
@property (readonly) float perimeter;
- (id) initWithLeftX : (float) leftX
             bottomY: (float) bottomY
              rightX: (float) rightX
                topY: (float) topY;
@end

Go to Interface Builder and select the table view. We need to setup our table with four columns, each with the following header titles: Width, Height, Area, and Perimeter. In the table view's attributes, set the number of columns to 4. Resize the window so that all four columns are available. Then, select each column and change the title and identifiers appropriately. In order to keep things simple, let's keep the identifiers the same as the titles. Finally, make sure each column is not editable. The attributes for the width column are shown in Figure 18. Make sure the other three columns are setup in a similar fashion.

Figure 18: Width column attributes

Just as we can add formatters to text fields, you can also add them to table columns. Add number formatters to each of the table columns by dragging from the Library to the text cells of each table column. Set their style to be Decimal, as we did earlier.

We are finished with the user interface, so save the nib and switch to Xcode. Our controller class will keep an array of rectangles and display them in the table. Let's start out by populating the array in our constructor with a few rectangles:

- (id) init
{
    self = [super init];
    if (self == nil)
        return nil;
    
    _rectangles = [[NSMutableArray alloc] init];
    
    Rectangle * rectangle;
    rectangle = [[Rectangle alloc] initWithLeftX   : 0
                                         bottomY: 0
                                          rightX: 10
                                            topY: 20];
    [_rectangles addObject: rectangle];
    // Without garbage collection you need:
    // [rectangle release];
    
    rectangle = [[Rectangle alloc] initWithLeftX   : 0
                                         bottomY: 0
                                          rightX: 500
                                            topY: 100];
    [_rectangles addObject: rectangle];
    // Without garbage collection you need:
    // [rectangle release];
    
    return self;
}

Be sure to add the _rectangles instance variable to the header file. Now, we're going to enable garbage collection for our project, too. This allows use to avoid releasing the rectangle instances and avoid implementing a destructor. Click on the project name in the Groups & Files list on the left. Then choose the File > Get Info menu to open up the Inspector panel. Select the Build tab, find the Objective-C Garbage Collection build setting and set it to Supported.

If you do not want to enable garbage collection, uncomment the release calls to rectangle and implement the dealloc method to release the _rectangles array. You also need to release the rectangle instances after adding them to the _rectangles array, as described in the comments. Remember the array retains objects, so you need to release them if you no longer need them.

Now we need to modify our data source methods to use the array of rectangles, instead of hard coded values. The numberOfRowsInTableView method is easy. It returns the number of elements in the _rectangles array:

- (NSInteger) numberOfRowsInTableView: (NSTableView *) tableView
{
    return [_rectangles count];
}

The tableView:objectValueForTableColumn:row: method is a bit more complex. It needs to return the proper rectangle property based on the identifier. The other tricky part is that the method returns an id type. This means we need to wrap our float values inside an NSNumber instance, as well:

- (id) tableView: (NSTableView *) tableView
objectValueForTableColumn: (NSTableColumn *) tableColumn
            row: (NSInteger) rowIndex
{
    NSString * identifier = [tableColumn identifier];
    Rectangle * rectangle = [_rectangles objectAtIndex: rowIndex];
    float value;
    if ([identifier isEqualToString: @"Width"])
        value = rectangle.width;
    else if ([identifier isEqualToString: @"Height"])
        value = rectangle.height;
    else if ([identifier isEqualToString: @"Area"])
        value = rectangle.area;
    else if ([identifier isEqualToString: @"Perimeter"])
        value = rectangle.perimeter;
    
    return [NSNumber numberWithFloat: value];
}

Running our application now should result in a window similar to Figure 19. It should show our two rectangles, along with their corresponding area and perimeter.

Figure 19: Initial rectangle table

Try resizing the window and see if it works correctly. Also try editing the individual table cells. Because we setup our table columns to be uneditable, it should not be allowed. The full listings for MyController are shown in Listing 2 and Listing 3.

Listing 2: MyController.h header file

#import <Cocoa/Cocoa.h>
@interface MyController : NSObject
{
    NSMutableArray * _rectangles;
}
@end
#import "MyController.h"
#import "Rectangle.h"
@implementation MyController
Listing 3: MyController.m source file
- (id) init
{
    self = [super init];
    if (self == nil)
        return nil;
    
    _rectangles = [[NSMutableArray alloc] init];
    
    Rectangle * rectangle;
    rectangle = [[Rectangle alloc] initWithLeftX   : 0
                                         bottomY: 0
                                          rightX: 10
                                            topY: 20];
    [_rectangles addObject: rectangle];
    // Without garbage collection you need:
    // [rectangle release];
    
    rectangle = [[Rectangle alloc] initWithLeftX   : 0
                                         bottomY: 0
                                          rightX: 500
                                            topY: 100];
    [_rectangles addObject: rectangle];
    // Without garbage collection you need:
    // [rectangle release];
    
    return self;
}
- (NSInteger) numberOfRowsInTableView: (NSTableView *) tableView
{
    return [_rectangles count];
}
- (id) tableView: (NSTableView *) tableView
objectValueForTableColumn: (NSTableColumn *) tableColumn
            row: (NSInteger) rowIndex
{
    NSString * identifier = [tableColumn identifier];
    Rectangle * rectangle = [_rectangles objectAtIndex: rowIndex];
    float value;
    if ([identifier isEqualToString: @"Width"])
        value = rectangle.width;
    else if ([identifier isEqualToString: @"Height"])
        value = rectangle.height;
    else if ([identifier isEqualToString: @"Area"])
        value = rectangle.area;
    else if ([identifier isEqualToString: @"Perimeter"])
        value = rectangle.perimeter;
    
    return [NSNumber numberWithFloat: value];
}
@end

Conclusion

Once again, we've covered a lot of ground in just one article. There's a lot more we can do with a table view, too much to cover in a single article. Next month, we'll explore how to add and remove rectangles from the table. That is, if you haven't gone ahead and figured it out on your own.


Dave Dribin has been writing professional software for over eleven years. After five years programming embedded C in the telecom industry and a brief stint riding the Internet bubble, he decided to venture out on his own. Since 2001, he has been providing independent consulting services, and in 2006, he founded Bit Maki, Inc. Find out more at http://www.bitmaki.com/ and http://www.dribin.org/dave/.

 
AAPL
$97.67
Apple Inc.
+0.64
MSFT
$44.50
Microsoft Corpora
+0.10
GOOG
$589.02
Google Inc.
-4.33

MacTech Search:
Community Search:

Software Updates via MacUpdate

Vienna 3.0.0 RC 2 :be5265e: - RSS and At...
Vienna is a freeware and Open-Source RSS/Atom newsreader with article storage and management via a SQLite database, written in Objective-C and Cocoa, for the OS X operating system. It provides... Read more
VLC Media Player 2.1.5 - Popular multime...
VLC Media Player is a highly portable multimedia player for various audio and video formats (MPEG-1, MPEG-2, MPEG-4, DivX, MP3, OGG, ...) as well as DVDs, VCDs, and various streaming protocols. It... Read more
Default Folder X 4.6.7 - Enhances Open a...
Default Folder X attaches a toolbar to the right side of the Open and Save dialogs in any OS X-native application. The toolbar gives you fast access to various folders and commands. You just click... Read more
TinkerTool 5.3 - Expanded preference set...
TinkerTool is an application that gives you access to additional preference settings Apple has built into Mac OS X. This allows to activate hidden features in the operating system and in some of the... Read more
Audio Hijack Pro 2.11.0 - Record and enh...
Audio Hijack Pro drastically changes the way you use audio on your computer, giving you the freedom to listen to audio when you want and how you want. Record and enhance any audio with Audio Hijack... Read more
Intermission 1.1.1 - Pause and rewind li...
Intermission allows you to pause and rewind live audio from any application on your Mac. Intermission will buffer up to 3 hours of audio, allowing users to skip through any assortment of audio... Read more
Autopano Giga 3.6 - Stitch multiple imag...
Autopano Giga allows you to stitch 2, 20, or 2,000 images. Version 3.0 integrates impressive new features that will definitely make you adopt Autopano Pro or Autopano Giga: Choose between 9... Read more
Airfoil 4.8.7 - Send audio from any app...
Airfoil allows you to send any audio to AirPort Express units, Apple TVs, and even other Macs and PCs, all in sync! It's your audio - everywhere. With Airfoil you can take audio from any... Read more
Microsoft Remote Desktop 8.0.8 - Connect...
With Microsoft Remote Desktop, you can connect to a remote PC and your work resources from almost anywhere. Experience the power of Windows with RemoteFX in a Remote Desktop client designed to help... Read more
xACT 2.30 - Audio compression toolkit. (...
xACT stands for X Aaudio Compression Toolkit, an application that encodes and decodes FLAC, SHN, Monkey’s Audio, TTA, Wavpack, and Apple Lossless files. It also can encode these formats to MP3, AAC... Read more

Latest Forum Discussions

See All

This Week at 148Apps: July 21-25, 2014
Another Week of Expert App Reviews   At 148Apps, we help you sort through the great ocean of apps to find the ones we think you’ll like and the ones you’ll need. Our top picks become Editor’s Choice, our stamp of approval for apps with that little... | Read more »
Reddme for iPhone - The Reddit Client (...
Reddme for iPhone - The Reddit Client 1.0 Device: iOS iPhone Category: News Price: $.99, Version: 1.0 (iTunes) Description: Reddme for iPhone is an iOS 7-optimized Reddit client that offers a refreshing new way to experience Reddit... | Read more »
Jacob Jones and the Bigfoot Mystery : Ep...
Jacob Jones and the Bigfoot Mystery : Episode 2 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: Jacob Jones is back in Episode 2 of one of Apples 'Best of 2013' games and an App Store... | Read more »
New Trailer For Outcast Odyssey, A New K...
New Trailer For Outcast Odyssey, A New Kind of Card Battler Posted by Jennifer Allen on July 25th, 2014 [ permalink ] Out this Fall is a new kind of card battle game: Outcast Odyssey. | Read more »
Hay Day – Tip, Tricks, Strategies, and C...
Recently got into Supercell’s other huge hit, Hay Day and could do with some advice on what to do? We’ve got you covered with some helpful trips and tricks to bear in mind! Ticking Along One of the key things to keep in mind while building up that... | Read more »
Monster Head Review
Monster Head Review By Nadia Oxford on July 25th, 2014 Our Rating: :: FEEDING TIMEUniversal App - Designed for iPhone and iPad Racking up a high score with Monster Head is trickier than it first appears. The appeal wears out fairly... | Read more »
Garfield: Survival of the Fattest Coming...
Garfield: Survival of the Fattest Coming to iOS this Fall Posted by Jennifer Allen on July 25th, 2014 [ permalink ] Who loves lasagna? Me. Also everyone’s favorite grumpy fat cat, Garfield. | Read more »
Happy Flock Review
Happy Flock Review By Andrew Fisher on July 25th, 2014 Our Rating: :: HERD IT ALL BEFOREUniversal App - Designed for iPhone and iPad Underneath the gloss of Happy Flock’s visuals is a game of very little substance. It’s cute, but... | Read more »
Square Register Updates Adds Offline Pay...
Square Register Updates Adds Offline Payments Posted by Ellis Spice on July 25th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Looking For Group – Hearthstone’s Curse...
For the first time since its release (which has thankfully been a much shorter window for iPad players than their PC counterparts), Blizzard’s wildly successful Hearthstone: Heroes of Warcraft CCG is sporting some brand new content: the single... | Read more »

Price Scanner via MacPrices.net

Record Mac Shipments In Q2/14 Confound Analys...
A Seeking Alpha Trefis commentary notes that Apple’s fiscal Q3 2014 results released July 22, beat market predictions on earnings, although revenues were slightly lower than anticipated. Apple’s Mac’... Read more
Intel To Launch Core M Silicon For Use In Not...
Digitimes’ Monica Chen and Joseph Tsai, report that Intel will launch 14nm-based Core M series processors specifically for use in fanless notebook/tablet 2-in-1 models in Q4 2014, with many models to... Read more
Apple’s 2014 Back to School promotion: $100 g...
 Apple’s 2014 Back to School promotion includes a free $100 App Store Gift Card with the purchase of any new Mac (Mac mini excluded), or a $50 Gift Card with the purchase of an iPad or iPhone,... Read more
iMacs on sale for $150 off MSRP, $250 off for...
Best Buy has iMacs on sale for up to $160 off MSRP for a limited time. Choose free home shipping or free instant local store pickup (if available). Prices are valid for online orders only, in-store... Read more
Mac minis on sale for $100 off MSRP, starting...
Best Buy has Mac minis on sale for $100 off MSRP. Choose free shipping or free instant local store pickup. Prices are for online orders only, in-store prices may vary: 2.5GHz Mac mini: $499.99 2.3GHz... Read more
Global Tablet Market Grows 11% in Q2/14 Notwi...
Worldwide tablet sales grew 11.0 percent year over year in the second quarter of 2014, with shipments reaching 49.3 million units according to preliminary data from the International Data Corporation... Read more
New iPhone 6 Models to Have Staggered Release...
Digitimes’ Cage Chao and Steve Shen report that according to unnamed sources in Apple’s upstream iPhone supply chain, the new 5.5-inch iPhone will be released several months later than the new 4.7-... Read more
New iOS App Helps People Feel Good About thei...
Mobile shoppers looking for big savings at their favorite stores can turn to the Goodshop app, a new iOS app with the latest coupons and deals at more than 5,000 online stores. In addition to being a... Read more
Save on 5th generation refurbished iPod touch...
The Apple Store has Apple Certified Refurbished 5th generation iPod touches available starting at $149. Apple’s one-year warranty is included with each model, and shipping is free. Many, but not all... Read more
What Should Apple’s Next MacBook Priority Be;...
Stabley Times’ Phil Moore says that after expanding its iMac lineup with a new low end model, Apple’s next Mac hardware decision will be how it wants to approach expanding its MacBook lineup as well... 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
WW Sales Program Manager, *Apple* Online St...
**Job Summary** Imagine what you could do here. At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring Read more
Lead Software Engineer, *Apple* Online Stor...
**Job Summary** Imagine what you could do here. At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring Read more
Manager, *Apple* Fullfillment Operation (AF...
…cross-functional teams to drive the highest level of program management quality for Apple . You will help plan launch strategy and demand generation programs with Read more
Project Manager / Business Analyst, WW *Appl...
…a senior project manager / business analyst to work within our Worldwide Apple Fulfillment Operations and the Business Process Re-engineering team. This role will work Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.