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
$111.78
Apple Inc.
-0.87
MSFT
$47.66
Microsoft Corpora
+0.14
GOOG
$516.35
Google Inc.
+5.25

MacTech Search:
Community Search:

Software Updates via MacUpdate

NeoOffice 2014.6 - Mac-tailored, OpenOff...
NeoOffice is a complete office suite for OS X. With NeoOffice, users can view, edit, and save OpenOffice documents, PDF files, and most Microsoft Word, Excel, and PowerPoint documents. NeoOffice 3.x... Read more
LibreOffice 4.3.5.2 - Free Open Source o...
LibreOffice is an office suite (word processor, spreadsheet, presentations, drawing tool) compatible with other major office suites. The Document Foundation is coordinating development and... Read more
CleanApp 5.0.0 Beta 5 - Application dein...
CleanApp is an application deinstaller and archiver.... Your hard drive gets fuller day by day, but do you know why? CleanApp 5 provides you with insights how to reclaim disk space. There are... Read more
Monolingual 1.6.2 - Remove unwanted OS X...
Monolingual is a program for removing unnecesary language resources from OS X, in order to reclaim several hundred megabytes of disk space. It requires a 64-bit capable Intel-based Mac and at least... Read more
NetShade 6.1 - Browse privately using an...
NetShade is an Internet security tool that conceals your IP address on the web. NetShade routes your Web connection through either a public anonymous proxy server, or one of NetShade's own dedicated... Read more
calibre 2.13 - Complete e-library manage...
Calibre is a complete e-book library manager. Organize your collection, convert your books to multiple formats, and sync with all of your devices. Let Calibre be your multi-tasking digital librarian... Read more
Mellel 3.3.7 - Powerful word processor w...
Mellel is the leading word processor for OS X and has been widely considered the industry standard since its inception. Mellel focuses on writers and scholars for technical writing and multilingual... Read more
ScreenFlow 5.0.1 - Create screen recordi...
Save 10% with the exclusive MacUpdate coupon code: AFMacUpdate10 Buy now! ScreenFlow is powerful, easy-to-use screencasting software for the Mac. With ScreenFlow you can record the contents of your... Read more
Simon 4.0 - Monitor changes and crashes...
Simon monitors websites and alerts you of crashes and changes. Select pages to monitor, choose your alert options, and customize your settings. Simon does the rest. Keep a watchful eye on your... Read more
BBEdit 11.0.2 - Powerful text and HTML e...
BBEdit is the leading professional HTML and text editor for the Mac. Specifically crafted in response to the needs of Web authors and software developers, this award-winning product provides a... Read more

Latest Forum Discussions

See All

Make your own Tribez Figures (and More)...
Make your own Tribez Figures (and More) with Toyze Posted by Jessica Fisher on December 19th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
So Many Holiday iOS Sales Oh My Goodness...
The holiday season is in full-swing, which means a whole lot of iOS apps and games are going on sale. A bunch already have, in fact. Naturally this means we’re putting together a hand-picked list of the best discounts and sales we can find in order... | Read more »
It’s Bird vs. Bird in the New PvP Mode f...
It’s Bird vs. Bird in the New PvP Mode for Angry Birds Epic Posted by Jessica Fisher on December 19th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Telltale Games and Mojang Announce Minec...
Telltale Games and Mojang Announce Minecraft: Story Mode – A Telltale Games Series Posted by Jessica Fisher on December 19th, 2014 [ permalink ] | Read more »
WarChest and Splash Damage Annouce Their...
WarChest and Splash Damage Annouce Their New Game: Tempo Posted by Jessica Fisher on December 19th, 2014 [ permalink ] WarChest Ltd and Splash Damage Ltd are teaming up again to work | Read more »
BulkyPix Celebrates its 6th Anniversary...
BulkyPix Celebrates its 6th Anniversary with a Bunch of Free Games Posted by Jessica Fisher on December 19th, 2014 [ permalink ] BulkyPix has | Read more »
Indulge in Japanese cuisine in Cooking F...
Indulge in Japanese cuisine in Cooking Fever’s new sushi-themed update Posted by Simon Reed on December 19th, 2014 [ permalink ] Lithuanian developer Nordcurrent has yet again updated its restaurant simulat | Read more »
Badland Daydream Level Pack Arrives to C...
Badland Daydream Level Pack Arrives to Celebrate 20 Million Downloads Posted by Ellis Spice on December 19th, 2014 [ permalink ] | Read more »
Far Cry 4, Assassin’s Creed Unity, Desti...
Far Cry 4, Assassin’s Creed Unity, Destiny, and Beyond – AppSpy Takes a Look at AAA Companion Apps Posted by Rob Rich on December 19th, 2014 [ permalink ] These day | Read more »
A Bunch of Halfbrick Games Are Going Fre...
A Bunch of Halfbrick Games Are Going Free for the Holidays Posted by Ellis Spice on December 19th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »

Price Scanner via MacPrices.net

Holiday sale: 13-inch 128GB MacBook Air for $...
 Best Buy has the 2014 13-inch 1.4GHz 128GB MacBook Air on sale for $849.99, or $150 off MSRP, on their online store. Choose free home shipping or free local store pickup (if available). Price valid... Read more
13-inch 2.6GHz Retina MacBook Pro on sale for...
Best Buy has lowered their price on the 2014 13″ 2.6GHz/128GB Retina MacBook Pro to $1149.99 on their online store for a limited time. That’s $150 off MSRP and the lowest price available for this... Read more
Kodak Returns to CES With New Consumer Produ...
Former photography colossus Kodak is returning to CES for the first time in three years where the Kodak booth (#21818 South Hall 1) will showcase a wide range of innovative, imaging-related products... Read more
Invaluable Launches New Eponymously -Named A...
Invaluable, the world’s largest online live auction marketplace, hhas announced the official launch of the Invaluable app for iPad, now available for download in the iTunes App Store. Invaluable... Read more
IDC Reveals Worldwide Mobile Enterprise Appli...
International Data Corporation (IDC) last week hosted the IDC FutureScape: Worldwide Mobile Enterprise Applications and Solutions 2015 Predictions Web conference. The session provided organizations... Read more
Hello Vino Wine App Launches “Safe Ride Home”...
Hello Vino has announced addition of a new “Get a Safe Ride Home” feature in its Food & Drink app with a direct connection to Uber, the technology platform that connects users with rides. The... Read more
DEVON-technologies Releases DEVONthink To Go...
Coeur d’Alene, Idaho based DEVON-technologies, LLC has updated DEVONthink To Go, its mobile companion to DEVONthink, to version 1.5. The update includes an iOS 8 extension, compatibility with the... Read more
The Apple Store offering free next-day shippi...
The Apple Store is now offering free next-day shipping on all in stock items if ordered before 12/23/14 at 10:00am PT. Local store pickup is also available within an hour of ordering for any in stock... Read more
It’s 1992 Again At Sony Pictures, Except For...
Techcrunch’s John Biggs interviewed a Sony Pictures Entertainment (SPE) employee, who quite understandably wished to remain anonymous, regarding post-hack conditions in SPE’s L.A office, explaining “... Read more
OtterBox Defender Series Case For iPad mini 3...
With their innovative Touch ID technology and ultrathin profile, the latest tranche of Apple iPads are more desirable than ever, and OtterBox has just announced the Defender Series custom-engineered... Read more

Jobs Board

*Apple* Store Leader Program (US) - Apple, I...
…Summary Learn and grow as you explore the art of leadership at the Apple Store. You'll master our retail business inside and out through training, hands-on experience, Read more
Project Manager, *Apple* Financial Services...
**Job Summary** Apple Financial Services (AFS) offers consumers, businesses and educational institutions ways to finance Apple purchases. We work with national and Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
*Apple* Retail - Multiple Positions (US) - A...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.