TweetFollow Us on Twitter

iPhone Productivity Applications, Part I

Volume Number: 25 (2009)
Issue Number: 03
Column Tag: iPhone

iPhone Productivity Applications, Part I

Developing applications that manage complex data

by Rich Warren

(Ed note: Parts I and II were actually printed out of order. Click here for Part II.)

Productivity Applications

My Last article, "Built for iPhone 2.0" described the three general categories of iPhone applications. Utilities provide a single view of the data with little or no interaction. Productivity applications manage and organize complex data. While immersive applications use the entire screen to provide a rich, interactive view. We then looked at the major tools used to build an iPhone application, and stepped through the development of a simple utility app.

This time, we will turn our attention to productivity. Productivity applications focus on managing and organizing complex data. Developers typically refrain from customizing the interface. Instead, they focus on creating a clean, streamlined solution that allows the user to move through the data in an unobtrusive and intuitive manner.

Note: productivity applications are not necessarily limited to traditional productivity-oriented tasks, like ToDo lists and calendars. Any application that focuses on data and organization may benefit from the productivity style. Mail is a perfect example of a productivity application. It allows you to manage a number of incoming and outgoing messages from a variety of different email accounts. Many third-party social networking applications also fall into this category. Even the iPod application is largely a data-driven, productivity app.

Productivity applications use three main tools to organize and interact with your data: UITabBarControllers, UINavigationControllers and UITableViews.

UITabBarControllers let the user easily switch between different tasks or different groups of data. For example, the clock application lets the user choose between the different time-related tasks: World Clock, Alarm, Stopwatch and Timer. The iPod app, on the other hand, lets the user select between different views of the data: Album, Artist, Genre, Song, Playlists, Videos, etc. Some applications even mix tasks and data groups. The App Store displays three data groups: features, categories and top 25, while letting the user access the search and updates tasks.

The tab bar can support any number of tab items. However, it will only show five tabs at a time. UITabBarController automatically manages any extra tab items by providing a more... button, and letting the user customize the items that appear on the tab bar.

Next, UINavigationController lets users move from general to more specific views. This controller maintains a stack of views. When a new view is added to the top of the stack, that view slides in from the right, while the old view slides off the left. When the top view is popped from the top of the stack, it slides back off the right, and the previous view returns from the left. This provides a very intuitive interface for moving through hierarchical data.

While both UITabBarController and UINavigationController manage navigation between views, UITableView handles the actual display of data. Tables are often used to present lists, for example, the list of email accounts, the list of mailboxes within a single account, or even the list of messages within a single mailbox. UITableView displays a single column of cells. Each cell within the table can be quite complex, combining images, icons and formatted text. But, in general, the pattern holds. Each entry represents a single selection from a list of similar items.

A productivity application typically combines some or all of these tools into a user interface that naturally matches the application's data. In general, UITabBarController provides the coarsest level of organization, defining our broadest groups. Within each group, UINavigationControllers allows the user to move from the most general to the most specific information, while UITableViews display the information available at each level of detail.

Note: Applications may have multiple UINavigationControllers or UITableViews; however, they should only have a single UITabBarController. Additionally, if you use a tab bar, then UITabBarController should always be the root controller for your application. You can add UINavigationControllers to a UITabBarController, but you should never add a UITabBarController to a UINavigationController.

Gas Tracker

For the rest of this article, we will build a simple productivity application. Given the state of our economy and the recent spike in gas prices, I wanted a tool that would help me track the amount of money I'm wasting on my car.

In many ways, this is an ideal iPhone application. A desktop version just wouldn't work. I'm nowhere near my computer when I fill up my tank. Sure, I've tried carrying a notepad in my car to do these calculations manually, but I always lose the pen under the seat. However, if I'm wearing pants, I have phone with me.

Additionally, the tasks are appropriate for a mobile application. Each interaction is short and simple - perfect for managing data on the go.

Creating the Project

OK, let's get started. Open Xcode. Select File ... New Project.... This brings up the New Project window. Project templates are grouped into categories shown in the leftmost column. Select the iPhone OS Application group.

Apple provides a number of project templates, each pre-loaded with the initial framework for a particular style of application. Since we will use a tab bar to manage the lowest levels of our view hierarchy, we should select Tab Bar Application and press the Choose button. In the next panel, name the application GasTracker, select a path and press Save.


Select the Tab Bar Application Template

Like all Xcode templates, the Tab Bar Application provides a great deal of functionality before we even touch the code. Go ahead and build and run the application. As you see, it creates a tab view that allows us to toggle between two different views.


The code itself starts with the GasTrackerAppDelegate. As with most Cocoa applications, the app delegate manages many of the high-level details. Currently, it simply creates the tab bar controller when the application launches, then releases the controller and window when the application closes.

The delegate also acts as a UITabBarControllerDelegate. There are two commented-out methods for modifying the tab bar's behavior. tabBarController:didSelectViewController: is called whenever the user presses a button on the tab bar. The application also calls tabBarController:didEnd-CustomizingViewControllers: whenever the user edits the buttons on the toolbar. We won't use either of these methods in this application, but they may be useful in your own projects.

The only other class is FirstViewController. Like the app delegate, the initial implementation does not do much, but it has a number of method stubs we could use to customize our view's behavior. We will examine these in more detail later.

There are also two nib files. MainWindow.xib defines the application's Window and Tab Bar Controller. The tab bar's views can either be defined within the Tab Bar Controller, or placed in separate nib files. In this template, the first view is defined within the controller. Open the MainWindow.xib , and then open the Tab Bar Controller. Click on the First button. You will see the layout directly.

The second view is defined in its own nib, named (not surprisingly) SecondView.xib. Click on the tab bar's Second button, and you will see a grayed-out box in the center of the view, with a link to SecondView.xib. Double click the link, and the second view's nib will open automatically.

While the generated code demonstrates a few useful techniques, the initial files are not very useful. I think it's better to just start from a clean slate. First, let's handle the simple part. In Xcode, delete FirstViewController.h, FirstViewController.m, and SecondView.xib. Go ahead and move them to the trash when prompted.

Now for the trickier part. In Interface Builder, open MainWindow.xib, and click on the Tab Bar Controller from the Interface Builder Documents.


Interface Builder Documents

Make sure the Attributes Inspector is open (either through the Tools menu, or by clicking on the Inspector's Attributes tab). You should see a list of view controllers that have been added to the tab bar. Select First, and then click the minus button. It should be deleted from the list. Do the same for Second.


Now let's add our views to the tab bar. We can set both the name and the class (or at least the super class) in this table. Press the plus button. Name this view History, and set the class to Navigation Controller. Now add five more views. Name these MPG, Gas Price, Cost/Mile, Cost/Month and Cost/Day. Leave the classes set to View Controller.

Note: You should be a little careful with the button titles. If they are too long, the labels may appear cramped or even overlap. Also, the size shown in Interface Builder is different from the size in the actual app. Build and run the application to test the label's true size. According to my tests, Cost/Month is OK, but Cost Per Month was too long.


Now look at the Tab Bar Controller window again. Notice, if you click the button once, the window will display the view associated with that button. All the views are currently grayed out. Additionally, the Inspector will show the view controller settings for that view. Double click the button, and the inspector shows the settings for the tab bar item itself.

Building Controllers and Nibs

Before we can do any more work in Interface Builder, we need to create our nibs and controller classes. Let's start by adding the controllers. Back in Xcode, right click on the Classes folder in the Groups & Files view. Select Add ... New File.... In the New File window, make sure Cocoa Touch Classes is selected, and then double click on NSObject subclass. In the next screen, name it HistoryNavigationController.m and click Finish. Do the same for StatsViewController.m, but this time, select the UIViewController subclass.


Adding a UIViewController Subclass

NSObject may seem like a strange choice for our HistoryNavigationController, but we don't need the method stubs provided by the UIViewController template, and we're going to change the super class anyway. So, open HistoryViewController.h and make the changes shown below:

HistoryNavigationController.h

Initial interface for the HistoryNavigationController class.
#import <UIKit/UIKit.h>
@class Model;
@interface HistoryNavigationController : UINavigationController {
   IBOutlet Model *model;
}
@property (nonatomic, retain) Model *model;
@end

We've made two small changes. As we already indicated, we've changed the super class to UINavigationController. Second, we've added a Model property, including a forward declaration of the Model class, and a model instance variable. The model is also declared as an IBOutlet, which allows us to connect it to the controller using Interface Builder. What's Model? Hold that question; we'll get to that in a bit.

While we're here, take a closer look at the property definition. We are using both the nonatomic and the retain keywords. The first keyword is an easy choice. Most iPhone properties should be declared nonatomic. They typically do not need to be thread safe, and using nonatomic accessors improves performance.

The second keyword is more of a design choice. By default, properties are set to simply assign incoming values to the instance variable. That may be appropriate if you can guarantee that the object in question will be retained somewhere else in your application. In our case, the model object will be instantiated by our nib file.

In iPhone OS, the nib file autoreleases all objects it creates. However, if you connect an object to an IBOutlet, it will call setValue:forKey: which will use the appropriate setter method. For our model, it will use the setter defined by the property, so it will be retained. Additionally, if you don't provide an explicit setter, the object would be retained automatically.

Note: The rules defining how nibs retain objects differ from Mac OS X to iPhone OS. In both cases, Apple recommends that you manage these objects through an IBOutlet, and create an appropriate setter that explicitly retains the object. For more information, see the Resource Programming Guide, which can be found either in Xcode's help documentation or online at http://developer.apple.com.

Ok, let's look at the implementation. Open HistoryNavigationController.m. We need to make three small changes here. Import Model.h, synthesize the model property, and release the model as shown below.

HistoryNavigationController.m

Initial implementation for the HistoryNavigationController class.

#import "HistoryNavigationController.h"
#import "Model.h"
@implementation HistoryNavigationController
@synthesize model;
- (void)dealloc {
    [model release];
    [super dealloc];
}
@end

Now add the model property to the StatsViewController. It follows the same pattern: forward declaration, instance variable and property declaration in StatsViewController.h; import, synthesize and release in StatsViewController.m. I will leave the actual typing up to you.

While you're there, you'll probably notice that StatsViewController.m contains a number of method stubs. These handle a range of different events: custom initialization, rotation, and low memory warnings. We'll look at these settings in more detail in part two.

For now, let's build our nib. At this point, we'll just create a single nib for our stats view controller. Right click on the Resources folder and select Add ... New File.... Make sure User Interfaces is selected, and double-click View XIB. Name it StatsView.xib.

Open StatsView.xib. In the Document Window, select File's Owner. Open the Identity Inspector, and change the class to StatsViewController. Next, connect the File's Owner's view outlet to the View object in the Document Window. You can do this by right clicking on the File's Owner icon. A black and gray table will appear. Click in the circle at the end of the view row, then drag to the View icon. You can now save and close the nib file. We will edit the layouts later.


Connecting the File's Owner's view Outlet

Note: Nibs are traditionally placed in the Resources group; however, you do not have to place them there. The groups are only used within Xcode to organize and manage the source files. They have no relationship to the actual layout of the project's files on disk. In fact, you can create your own groups to further improve the project's organization. If you download the source code for this project from ftp.mactech.com, you will see that I've created a number of additional subgroups within the Classes group.

Ok, now let's link our tabs to these nib files. Make sure MainWindow.xib is open. Select the Tab Bar Controller icon in the Document Window. This will open the Tab Bar Controller view, if it isn't open already. The tab bar displays the six views that we just added. Single click on the History tab. The Attributes Inspector should be labeled as Navigation Controller Attributes. If not, try clicking on another tab, then single clicking on the History tab again.


The Nib Name attribute here would be for the Navigation Controller itself. We won't use a nib for this controller, so just leave this entry blank. We will eventually modify the navigation controller's layout directly in the Tab Bar Controller view. Switch to the Identity Inspector (either through the Tools menu, or by clicking on the Inspector's Identity tab), and change the class to HistoryNavigationController.



Now, single click on the MPG tab. This time, we should set the nib name to StatsView and set the class to StatsViewController. Repeat this for all the remaining tabs.



Now let's set the icons for each tab. History is the easiest. Make sure the Attribute Inspector is open. Double click on the history tab to bring up the Tab Bar Item Attributes. Change Identifier to History. This will set both the tab title and the icon to the built-in History tab item.


Note: Each of the built-in icons is automatically linked with a title. You cannot use the icon without using the corresponding title. If you want a custom title, you must use a custom icon.

For the other tabs, we will customize the icons and titles. Tab bar icons are simply 30-pixel by 30-pixel PNG image. Notice, however, that the image color does not matter. The tab bar uses the alpha value of each pixel to create a monochrome icon. It displays the alpha channel as blue in the tab bar, and as black in the More... list.

To create these icons, I find it easiest to use a paint program that supports transparencies. Draw the icon in black against a transparent background. You can even set the transparency of the ink to draw in grayscale. Then save the image as a PNG.

30 x 30 Icon Art, Black with a Semi-Transparent Gray Background


Once you have an icon, add it to your project. In Xcode, select Project ... Add to Project.... Navigate to the PNG file and click Add. In the next window, be sure to check Copy items into destination group's folder (if needed).

Now, back in Interface Builder. Double click on the tab in question. Identifier should say Custom. Select your icon's name from the Image combo box. Repeat for each tab.


OK, I know...I know...I've gone through a lot of Interface Builder commands rather quickly. Hopefully, I've given you enough pointers to get by, but a complete tutorial on Interface Builder is really beyond the scope of this article. If you have any questions or difficulties, check out Apple's Interface Builder User Guide. That can be found either in Xcode's developer documentation, or online at http://developer.apple.com.

M is for Model

Apple really pushes the Model View Control pattern (MVC to the cool kids). I won't go into a full description of MVC here. If you're not familiar with the concept, there are plenty of great explanations on the web. I'll just say that I agree with Apple. MVC is a good idea. [Ed. Note: For a review of MVC, see Dave Dribin's "Road to Code" in the August, 2008 issue]

We've already seen two of the three main players. We've just built a number of views and controllers. We've linked them together. All that with only a few lines of code.

But now things get a little weird. While Cocoa provides clear support for the controllers and views, models aren't so obvious, at least not on the iPhone. Here's the problem. Most of our controllers will need a connection to our model. Some of these controllers may be instantiated pragmatically, letting us pass the model to them directly, but many are automatically created through the nib files.

There are a number of ways to work around this problem. Many people simply instantiate their model object in the app delegate, and then add a property to the delegate. They can then access the property anywhere in their project, using the application singleton.

Using the UIApplication Singleton

Add your model to the application delegate as a property. You can access the application Singleton anywhere in your project. From the application, you can access the delegate, and from the delegate you reach your model.

UIApplication *app = [UIApplication sharedApplication];
id delegate = app.delegate;
id modelObject = [delegate model];

This works, and it is reasonably simple. However, there are a number of reasons I don't like it. First, singleton classes have many of the same problems as global variables. Second, we're programming against a particular application delegate's implementation, not the UIApplicationDelegate protocol. Third, from a pure Object Oriented standpoint, managing the model seems outside the application delegate's role. Finally (and most importantly), it just feels kludgy.

Alternatively, we could create a singleton object to explicitly manage our model. While this feels better in many ways, I still prefer to avoid Singletons where possible. Besides, it may be a bit heavy handed for this application. Though, I will admit, it may be the cleanest solution for some of the more-complicated projects.

If possible I'd like to connect the model the same way we connected the views and controllers, using Interface Builder. Fortunately, in this application we can create a single Model object in our MainWindow.xib, and connect it to all the relevant controllers. This may not always be possible. In more complex projects, you may need to pass an external object into a nib as a proxy object. These objects are then set when you load the nib file using NSBundle's loadNibNamed:owner:options: method. For more information, check out the NSBundle UIKit Additions, Resource Programming Guide and Interface Builder User Guide.

The first step is to build our model. Unfortunately, that is outside the scope of this article. Instead, you can simply grab the necessary code from ftp.mactech.com. You will need both the Model and the Entry classes. Add these to your project.

Note: For this project, our model knows how to automatically load any saved data when it is instantiated. It will also save itself whenever the user makes any changes. This greatly simplifies our controller and delegate code. Check out Model.m for more details.

Now let's add the object to our nib. Open MainWindow.xib. Drag an Object controller from the Library to the Document Window. In the Identity Inspector, set the Object's class to Model. Now we have to make our connections. Single click on each tab to select the tab's controller, then right click on the tab. Connect the tab's model outlet with the model object. That's it. We've linked our model, views and controllers.

Configuring Tab Customizability

As I said earlier, the tab control can only display up to five icons at a time. If you have more than five view controllers, the tab controller only displays four of them and a More... button. Clicking on the More... button brings up a table with all the additional controllers. The user can then select a controller from the table, or they can click on the edit button and customize the contents of the tab bar.

However, not all tab items are customizable. For example, the user cannot replace the More... button. In fact, UITabBarController maintains an array of customizable controls. If a controller is in that array, then it can be moved or removed from the tab bar. By default, all the tab bar's view controllers are automatically placed in the customizeableViewController array.

In our program the History view will act as the main interface for managing our data. It should always be available, therefore we must remove it from the customizeableViewController array. We could subclass UITabBarController, but that's probably overkill for this application. Instead, we can access the tab bar controller from within our application delegate.

Open GasTrackerAppDelegate.m, and modify the applicationDidFinishLaunching: method, as shown below:

applicationDidFinishLaunching:

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    
    // Add the tab bar controller's current view 
    // as a subview of the window
    [window addSubview:tabBarController.view];
   
      
    // Only the StatsViewControllers are customizeable
    NSMutableArray *customizeable = [[NSMutableArray alloc] init];
    for (id controller in tabBarController.customizableViewControllers) {
      
        if ([controller isKindOfClass: [StatsViewController class]]) {
            [customizeable addObject:controller];
        }
    }
   
    tabBarController.customizableViewControllers = customizeable;
    [customizeable release];
}

Basically, this method creates a new array that only contains subclasses of StatsViewController, then it assigns that array to the UITabBarController's customizeableViewControllers property.

OK, a little bit of housecleaning left. Be sure to import StatsViewController.h at the top of GasTrackerAppDelegate.m.

#import "GasTrackerAppDelegate.h"
#import "StatsViewController.h"

Looking Forward:

So far, we've built the application's skeleton and set up the tab view and the model. The application compiles without any warnings. When you run the app, you can switch from tab to tab or customize the tab bar. Of course, the various views don't do much yet.

This project will continue in Part 2. In particular, we will focus on setting up the navigation controller and our table views. We will also add a view for entering data, and create custom classes for each of the stats views. Once that's done, we'll have a fully functional productivity application.


Rich Warren lives in Honolulu, Hawaii with his wife, Mika, daughter, Haruko, and his son, Kai. He is a software engineer, freelance writer and part time graduate student. When not playing on the beach, he is probably writing, coding or doing research on his MacBook Pro. You can reach Rich at rikiwarren@mac.com, check out his blog at http://freelancemadscience.blogspot.com/ or follow him at http://twitter.com/rikiwarren.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Suitcase Fusion 7 18.2.4 - Font manageme...
Suitcase Fusion 7 is the creative professional's font manager. Every professional font manager should deliver the basics: spectacular previews, powerful search tools, and efficient font organization... Read more
SoftRAID 5.6.1 - High-quality RAID manag...
SoftRAID allows you to create and manage disk arrays to increase performance and reliability. SoftRAID allows the user to create and manage RAID 4 and 5 volumes, RAID 1+0, and RAID 1 (Mirror) and... Read more
BetterTouchTool 2.25 - Customize Multi-T...
BetterTouchTool adds many new, fully customizable gestures to the Magic Mouse, Multi-Touch MacBook trackpad, and Magic Trackpad. These gestures are customizable: Magic Mouse: Pinch in / out (zoom... Read more
Google Chrome 59.0.3071.115 - Modern and...
Google Chrome is a Web browser by Google, created to be a modern platform for Web pages and applications. It utilizes very fast loading of Web pages and has a V8 engine, which is a custom built... Read more
Google Chrome 59.0.3071.115 - Modern and...
Google Chrome is a Web browser by Google, created to be a modern platform for Web pages and applications. It utilizes very fast loading of Web pages and has a V8 engine, which is a custom built... Read more
SoftRAID 5.6.1 - High-quality RAID manag...
SoftRAID allows you to create and manage disk arrays to increase performance and reliability. SoftRAID allows the user to create and manage RAID 4 and 5 volumes, RAID 1+0, and RAID 1 (Mirror) and... Read more
Suitcase Fusion 7 18.2.4 - Font manageme...
Suitcase Fusion 7 is the creative professional's font manager. Every professional font manager should deliver the basics: spectacular previews, powerful search tools, and efficient font organization... Read more
BetterTouchTool 2.25 - Customize Multi-T...
BetterTouchTool adds many new, fully customizable gestures to the Magic Mouse, Multi-Touch MacBook trackpad, and Magic Trackpad. These gestures are customizable: Magic Mouse: Pinch in / out (zoom... Read more
WhiteCap 6.7.1 - Visual plug-in for iTun...
WhiteCap is a sleek and sophisticated music visualizer and screensaver that features futuristic, wireframe mesh visuals with dynamic backgrounds and colors. WhiteCap contains thousands of visual... Read more
DiskMaker X 6.0 rc5 - Make a bootable OS...
DiskMaker X (was Lion DiskMaker) helps you to build a bootable drive from the official OS X installer app (the one you download from the Mac App Store). It detects the OS X Install program with... Read more

Latest Forum Discussions

See All

This War of Mine gets a new ending and m...
This War of Mine just got a big new update, featuring free DLC that adds a new ending to the game, among other exciting changes. The update is celebrating the game's two-year release anniversary. Apart from the new ending, which will be quite... | Read more »
Summon eight new heroes in Fire Emblem H...
Nintendo keeps coming at us with Fire Emblem Heroes updates, and it doesn't look like that trend is stopping anytime soon. The folks behind the game have just announced the new War of the Clerics Voting Gauntlet, expected to start next Tuesday. [... | Read more »
The best deals on the App Store this wee...
iOS publishers are pulling out all the stops this week -- there's a huge number of seriously great games at discounted prices this week. Let's not waste any time and get right down to business. [Read more] | Read more »
The House of da Vinci (Games)
The House of da Vinci 1.0.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0.0 (iTunes) Description: Enter The House of Da Vinci, a new must-try 3D puzzle adventure game. Solve mechanical puzzles, discover hidden... | Read more »
Solve the disappearance of history’s gre...
Blue Brain Games invites you to indulge in an immersive hands-on 3D puzzle adventure in similar vein to The Room series, with its debut release The House of Da Vinci. Set during the historic period of the Italian Renaissance (when Leonardo himself... | Read more »
Age of Rivals (Games)
Age of Rivals 3.3 Device: iOS Universal Category: Games Price: $.99, Version: 3.3 (iTunes) Description: Deep civilization-building strategy in a fast-paced card game! | Read more »
Panthera Frontier (Games)
Panthera Frontier 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: | Read more »
Angry Birds Evolution beginner's gu...
Angry Birds changes things up a fair bit in its latest iteration, Angry Birds Evolution. The familiar sling-shot physics mechanics are still there, but the game now features team-based gameplay, RPG elements, and a new top-down view. With all of... | Read more »
Sega Forever is for the retro game fans
Sega is launching a new retro games service titled Sega Forever, in a move that's sure to delight games enthusiasts with a bit of nostalgia. Sega's releasing five classic games for free. The titles include Sonic the Hedgehog, Phantasy Star II,... | Read more »
The Little Acre (Games)
The Little Acre 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: | Read more »

Price Scanner via MacPrices.net

13-inch 1.8GHz/256GB MacBook Air on sale for...
B&H Photo has the updated 2017 13″ 1.8GHz/256GB MacBook Air (MQD42LL/A) in stock and on sale for $1129 including free shipping plus NY & NJ tax only. Their price is $70 off MSRP. Read more
27-inch 3.4GHz iMac on sale for $1699, save $...
B&H Photo has the new 2017 27″ 3.4GHz iMac (MNE92LL/A) in stock and on sale for $1699 including free shipping plus NY & NJ sales tax only. Their price is $100 off MSRP. Read more
21-inch 2.3GHz iMac on sale for $1049, save $...
B&H Photo has the new 2017 21″ 2.3GHz iMac (MMQA2LL/A) in stock and on sale for $1049 including free shipping plus NY & NJ tax only. Their price is $50 off MSRP. Read more
ABBYY TextGrabber 6 for iOS Implements Instan...
ABBYY has announced the release of TextGrabber 6.0.0, an important feature update to the company’s productivity app developed for iOS and Android devices. TextGrabber 6.0 now offers Real-Time... Read more
vPhone, First Smartphone That Can’t Be Lost,...
Austin, Texas based Hypori has introduced the vPhone, a virtual smartphone that affords every business user the benefits of separate work and personal phones, conveniently delivered on a single... Read more
Save this weekend with 2016 refurbished MacBo...
Apple has dropped prices on Certified Refurbished 2016 15″ and 13″ MacBook Pros by as much as $590 off original MSRP. An Apple one-year warranty is included with each model, and shipping is free: -... Read more
New 27-inch 3.4GHz iMac on sale for $1699, sa...
MacMall has the new 2017 27″ 3.4GHz iMac (MNE92LL/A) in stock and on sale for $1699 including free shipping. Their price is $100 off MSRP. Read more
Clearance 2016 MacBook Pros available for up...
B&H Photo has clearance 2016 13″ and 15″ MacBook Pros in stock today and on sale for up to $400 off original MSRP. Shipping is free, and B&H charges NY & NJ sales tax only: - 15″ 2.7GHz... Read more
Apple Ranks 9th In comScore Top 50 U.S. Digit...
comScore, Inc. has released its monthly ranking of U.S. online activity at the top digital media properties for May 2017 based on data from comScore Media Metrix Multi-Platform. * Entity has... Read more
10.5-inch iPad Pros available for up to $20 o...
B&H Photo has the new 2017 10.5″ iPad Pros available for up to $20 off MSRP including free shipping plus NY & NJ sales tax only: - 64GB iPad Pro WiFi: $649 - 256GB iPad Pro WiFi: $749 - 512GB... Read more

Jobs Board

*Apple* News Product Marketing Mgr., Publish...
…organizational consensus on strategy and vision for publisher tools, authoring, and Apple News Format.Carries this strategy and vision across the organization to Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
Security Data Analyst - *Apple* Information...
…data sources need to be collected to allow Information Security to better protect Apple employees and customers from a wide range of threats.Act as the subject matter Read more
Lead *Apple* Solutions Consultant - Apple I...
…integrity, and trust.Success Metrics/Key Performance Indicators:Quantitative* Year over Year growth in Apple Product and Beyond the Box sales in the assigned Point of Read more
*Apple* Solutions Consultant till v%u00E5r...
…ethics, integrity, and trust.Success Metrics/Key Performance Indicators:QuantitativeYear over Year growth in Apple Product and Beyond the Box sales in the assigned Point Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.