TweetFollow Us on Twitter

The Road to Code: Play it Again, Sam

Volume Number: 25 (2009)
Issue Number: 01
Column Tag: The Road to Code

The Road to Code: Play it Again, Sam

A review of the last year and a half

by Dave Dribin

In Review

Over the last year and a half, we've covered a lot of ground on The Road to Code. We've gone over the basics of programming in C to advanced Cocoa technology, such as Cocoa bindings and Core Data. This month, we're going to put all these concepts together in one article, for those who haven't read each and every article since the beginning of our journey.

Objective-C

There are three legs that support Mac OS X programming, the first being the language. Programs are written for Mac OS X using a language called Objective-C. Objective-C was not created by Apple or even NeXT, but NeXT adopted it in the mid-eighties. Since then, Objective-C has not been used by any other major vendor, thus it's mainly seen as Apple's language.

Objective-C is a strict superset of the cross-platform C language that adds object-oriented programming. C is a statically typed language, meaning every variable is declared as a specific type, like int or float. You still use these primitive types when coding in Objective-C. You also still use C for basic control structures, such as if/then statements, and for and while loops.

Objective-C adds object-oriented programming on top of C's procedural model. Listing 1 shows the interface of a simple Objective-C class to represent a geometric rectangle.

Listing 1: Rectangle class interface

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

The @interface keyword in the first line declares a new class named Rectangle whose superclass is NSObject. Objective-C classes can only have one superclass, meaning multiple inheritance is not supported. The NSObject class is the root of all class hierarchies.

Instance variables are declared between the curly braces. They are listed, one per line, with their type followed by their name, similar to structures in C. Instance variables are only available to the class implementation. They are generally not accessible by other classes.

Instance methods are how others interact with your class and are declared until the @end keyword. Instance methods have a bit of a strange syntax compared to C functions. The return value is in parenthesis and each method argument has a keyword before it. These keywords are actually part of the method name, so the full method name, called a selector, for the first method in the Rectangle class is:

    initWithLeftX:bottomY:rightX:topY:

The arguments are interleaved where the colons are. Calling methods use the square bracket syntax. For example, this is how you would call the area method:

    float area = [rectangle area];

For methods with arguments, the argument values are interleaved with the keyword part of the method. You can also chain multiple method calls together by nesting the square brackets. This is how you would call the constructor to initialize a new Rectangle:

    Rectangle * rectangle =
        [[Rectangle alloc] initWithLeftX:0
                                 bottomY:0
                                  rightX:5
                                    topY:10];

The use of interleaved keywords is unlike most languages, but I think it makes methods much easier to read.

The minus sign in front the method name means it is an instance method: you call this method on an instance of the class. You can use a plus sign to declare a class method:

+ (Rectangle *)zeroRect;

This means you call the method on the class itself:

Rectangle * rectangle = [Rectangle zeroRect];

To define the body of a method, you repeat the method signature and put the body of the method in curly braces:

- (float)area
{
    return _width * _height;
}

This is very much like standard C functions where you use the return keyword to stop executing the method and set the return value. As this example shows, you can directly access instance variables.

Properties

Objective-C 2.0, which was introduced in Mac OS X 10.5, but is also available for the iPhone SDK, has a new feature called properties. Properties simplify the declaring and defining of accessor methods that expose instance variables. Listing 2 is our rectangle interface declared using properties.

Listing 2: Rectangle interface with properties

#import <Foundation/Foundation.h>
@interface Rectangle : NSObject <NSCoding>
{
    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

The @property keyword is used to define a property. Not only does this automatically declare the getter and setter accessor methods, but it also means that they may be accessed using dot notation, instead of method call notation:

    float area = rectangle.area;

You still need to define the body of these implied getter and setter methods, but these may also be generated using the @synthesize keyword:

@synthesize leftX = _leftX;
@synthesize bottomY = _bottomY;
@synthesize width = _width;
@synthesize height = _height;

These lines generate proper accessor methods, tying the properties to a specific instance variable. The property syntax greatly reduces the amount code you have to write for accessors.

Memory Management

All Objective-C objects are allocated on the heap using dynamic memory. It is not possible to allocate an Objective-C object on the stack. Using dynamic memory in C requires using the malloc and free functions. malloc allocates memory from the system and free deallocates memory, returning it to the system.

There are primarily two kinds of memory management bugs you may encounter when dealing with dynamic memory: memory leaks and dangling pointers. Memory leaks occur when you fail to deallocate memory. Over time, your application will use more and more memory, which means less for other applications. Dangling pointers occur when you deallocate memory too soon and active pointers are still pointing to the deallocated memory. Dangling pointers often result in a crash of the application.

In order to avoid memory bugs in C, every malloc must be matched by a free at some point to ensure that all allocated memory is properly returned to the system. To help make this easier, C code usually adopts a system where each piece of dynamic memory has a single owner. The owner is responsible for freeing memory when it is done with it. In order to make this work in practice, you have to setup some conventions so you know who is the owner of a piece of memory.

Traditionally, memory management of objects in Objective-C is handled with a technique called manual reference counting. Reference counting allows multiple owners of an object, compared to the single ownership model of dynamic memory in C. This drastically simplifies the memory management overhead the programmer needs to think about.

To take ownership of an object, you use the retain method to increase the reference count. To relinquish ownership, you use the release method to decrease the reference count. When the reference count reaches zero, the object is deallocated and the memory is returned to the system.

While the ownership rules are simpler in Objective-C than dynamic memory in C, there are still some basic rules that need to be followed in order to ensure proper memory management and avoid memory bugs. Here are the memory management rules as laid out by the Memory Management Programming Guide for Cocoa:

You own any object you create.

If you own an object, you are responsible for relinquishing ownership when you have finished with it.

If you do not own an object, you must not release it.

I suggest reading that entire memory management guide, which you can find on Apple's developer website, as it contains everything you need to know for proper memory management in Objective-C. Some topics of interest are delayed release using autorelease pools, how to write proper accessor methods, and avoiding retain cycles. We also covered these topics in the February 2008 issue.

Garbage Collection

If you are writing applications for Mac OS X 10.4 and earlier or the iPhone, you must use manual reference counting with retain and release. However, if you are fortunate enough to write applications for Mac OS X 10.5 only, you may choose to use garbage collection for memory management.

With garbage collection, you no longer have to worry about using retain and release. The system automatically knows when an object has zero owners and is deallocated. As usual, there are some edge cases you should be aware of, but for all intents and purposes, garbage collection makes your life much easier. I highly recommend it, if you are able to target Mac OS X 10.5.

Libraries

The second leg supporting Mac OS X programming are the system libraries. The libraries define OS X programming as much as the language. Reusable libraries in Objective-C are called frameworks. There are two main system frameworks on Mac OS X: Foundation and AppKit.

Foundation contains much of the lower-level reusable components, such as strings, collections, and file management. These objects are generic and usable in most any application you may be writing, from command line to GUI to server daemons. For example, the root class, NSObject, is part of the Foundation framework. In fact, Foundation is also available when developing for the iPhone. The iPhone's version of Foundation is not quite as full-featured as its Mac OS X counterpart, but you'll find many of the same objects, such as NSString, NSArray, and NSDictionary available on both Mac OS X and iPhone OS.

The AppKit framework is the GUI framework for Mac OS X, providing the system's APIs for GUI components such as windows and buttons. The combination of Foundation and AppKit is known as Cocoa, and Cocoa is really the heart and soul of Mac OS X programming.

Developer Tools

The final leg of support are the developer tools. Apple provides the developer tools for Mac OS X for free. The developer tools include not only a compiler and linker but also a full blown IDE, Xcode, and GUI designer, Interface Builder. Xcode is a fairly advanced IDE. This is where you will spend your time writing code. It allows you to edit, compile, and debug your code all through a nice GUI. It also has features you would expect in a modern IDE, such as autocompletion and some basic refactoring tools.

Interface Builder is an important part of developing for Mac OS X and iPhone. Instead of having to create your user interface in code by instantiating windows and view, then hooking them all up manually, Interface Builder allows you to do this graphically. But it is not a code generating tool, like many GUI designers. Instead of creating code that you have to modify or customize, it creates nib files (which have the .nib or .xib file extension), which contains all the objects for your user interface, freeze dried into a single package. At runtime, your nib file gets loaded, thus creating all your objects and hooking them up appropriately.

Interface Builder not only allows you to layout your user interface, it also allows you to customize their behavior. For example, you can set options on views and controls. One important customization is the autosizing behavior using springs and struts. This defines how controls behave when the window containing the view is resized. It allows views to stretch or stay pinned to a side of the window. An example of the springs and struts settings is shown in the Autosizing section of Figure 1.


Figure 1: Springs and struts

Often you need to write code to customize how GUI components react to user interaction or customize their behavior. Because Interface Builder is not a code generating tool, it uses techniques called actions and outlets to hook up code to the objects defined in the nib file.

Actions are methods that are called in response to a user interacting with a control. For example, buttons call their action method when the button is clicked and menu items call their action method when the menu item is chosen. An action method is a method that has a special return type of IBAction and takes a single argument of type id. Here is an example action method for handling a button press:

- (IBAction)buttonPressed:(id)sender;

The sender argument is typically the control that sent the action, in this case it would be the NSButton that the user clicked. The IBAction return type is an alias for void, so you do not actually return anything. It is used purely as a marker to help Interface Builder identify action methods by scanning the header file.

Outlets allow you to hookup instance variables or properties to objects in the nib. For example, if you wanted to customize the behavior of an NSTableView, you would create an outlet and then use Interface Builder to hookup the outlet to the particular table view in your user interface. To declare an outlet for an instance variable, prefix its type with IBOutlet, as follows:

    IBOutlet NSTableView * _tableView;

To use an outlet object in your code, you must do so after all the outlets in the nib are connected. A special method named awakeFromNib gets called on all objects that were reconstituted from a nib after all objects have been created and all outlet and action connections have been made. It is in awakeFromNib where you would put your code to customize your table view.

MVC

Much of Foundation and AppKit was designed with the model-view-controller design pattern in mind. Design patterns are reusable ideas and architectures used across different programs. The model-view-controller pattern, or MVC pattern, is a common structure for designing GUI applications.

The MVC pattern is shown in Figure 2. Classes in your application should be categorized into three distinct roles: models, views, and controllers. The view classes represent the user interface, and are typically the windows, views, and controls in the AppKit framework. Example view classes include NSButton and NSWindow. The model classes represent the core of your application. For example, if you were writing an address book application, your Person and Address classes would be model classes. This is essentially your application without a user interface. The controller classes glue to together the model and the view by mediating between them.


Figure 2: MVC Architecture

The Rectangle class we've been using as an example is considered a model class. Model classes also know how to convert themselves to and from bytes so they can be stored in a file. The technique of converting an object into a stream of bytes is called archiving, and converting from a stream of bytes is called unarchiving. An object that knows how to archive and unarchive itself must implement the NSCoding protocol. The NSCoding protocol is shown in Listing 3.

Listing 3: NSCoding protocol

@protocol NSCoding
- (void)encodeWithCoder:(NSCoder *)coder;
- (id)initWithCoder:(NSCoder *)decoder;
@end

A protocol is just like a method interface, except it has no implementation. Classes that implement protocols must provide implementations for all methods declared in the protocol interface. To implement NSCoding in our Rectangle class, you could these methods as such:

#pragma mark -
#pragma mark NSCoding
- (void)encodeWithCoder:(NSCoder *)coder
{
    [coder encodeFloat:_leftX forKey:@"leftX"];
    [coder encodeFloat:_bottomY forKey:@"bottomY"];
    [coder encodeFloat:_width forKey:@"width"];
    [coder encodeFloat:_height forKey:@"height"];
}
- (id)initWithCoder:(NSCoder *)decoder
{ 
    self = [super init];
    if (self == nil)
        return nil;
    
    _leftX = [decoder decodeFloatForKey:@"leftX"];
    _bottomY = [decoder decodeFloatForKey:@"bottomY"];
    _width = [decoder decodeFloatForKey:@"width"];
    _height = [decoder decodeFloatForKey:@"height"];
    
    return self;
}

With the Rectangle object implementing we can now convert a rectangle to NSData, a class that represents a collection of bytes, using NSKeyedArchiver:

    Rectangle * rectangle = ...;
    NSData * data =
        [NSKeyedArchiver archivedDataWithRootObject: rectangle];

Conversely, you can convert a previously archived rectangle back into a Rectangle object use NSKeyedUnarchiver:

    NSData * data = ...;
    Rectangle * rectangle =
        [NSKeyedUnarchiver unarchiveObjectWithData: data];

We covered the MVC pattern in detail in the August 2008 issue.

Document-Based Applications

Another design pattern for GUI applications is called a document-based application. A document-based application is one that resolves around the user editing, saving, and opening documents. Because this is such a common kind of application, Cocoa provides classes to help make writing them easier called the document-based architecture. There are three classes that comprise the document-based architecture, but the main one is NSDocument.

When writing a document-based application, you typically subclass NSDocument and customize it for your application. Your subclass not only acts as a controller, mediating between your UI and the model, it also handles saving and opening document files.

Dirty Documents and Undo

Users of document-based applications expect dirty document and undo support. Dirty document support is when the application tracks changes to a document and asks the user to save their changes if the document is closed or the application is quit. This helps ensure that users do not inadvertently lose any changes they made.

Documents use a change count to keep track of dirty state of the document. The change count gets incremented every time the user edits the document. If the change count is zero, the document is clean and may be closed without losing data. If the change count is greater than zero, then the document is dirty. NSDocument does not update the change count for you. If you need to manually increment the change count, you use the updateChangeCount: method of NSDocument:

    [self updateChangeCount:NSChangeDone];

Undo and redo support dovetails with the document change count. Thus, when a user edits a document, the change count should increase and the changes should be undoable. When the user undoes a change, the change count must be decremented, as well. Thus, if the users undoes all the possible edits, the change count is back at zero.

Undo and redo support is handled by the NSUndoManager class. You typically register the previous value with the undo manager before setting the new value. For example, to have the Rectangle class support undo in its setWidth: method you would register the undo action as follows:

- (void)setWidth:(float)width;
{
    if (width == _width)
        return;
    
    NSUndoManager * undoManager = [self undoManager];
    [[undoManager prepareWithInvocationTarget:self] setWidth:_width];
    _width = width;
}

Typically, you do not put undo support into model objects, and you put them in the controller layer. The example included the November 2008 issue showed how to add undo support to our NSDocument subclass. We showed how to use key-value coding (KVC) and key-value observering (KVO) in the document to monitor changes to its rectangles.

Cocoa Bindings

Cocoa bindings is a technology to help reduce the burden of writing controller classes. Much of the controller code is very similar from application to application. It shuttles data from the model to the view and also ensures user interaction from the views is reflected on the model objects.

Because much of the controller code is tedious and repetitive, Apple tried to engineer a technique to make controller code more reusable. The result is Cocoa bindings. By taking advantage of KVC and KVO, Cocoa bindings provides reusable controller objects in the form of NSController subclasses such as NSObjectController and NSArrayController. User interface elements are bound to an NSController instance. These bindings are setup in Interface Builder and rely and key paths. The controllers then use KVC to get the value from model objects and KVO to watch for changes to model objects. Figure 3 is an example from our September 2008 issue that shows how to bind the width of the rectangle to a text field.

Core Data

While writing model objects is not necessarily difficult, there is again a lot of repetitive code. You have to implement NSCoding in the model and undo support in the controller. Again, Apple tries to engineer a technique to make model code more reusable. Apple took a lot of what it learned about object-relational persistence from its WebObjects framework, and re-designed it for use in single user applications. The result is Core Data.

Because of its object-relational mapping lineage, Core Data uses database terms, such as entity and attribute instead of object-oriented terminology like classes and instance variables.

In the December 2008 issue, we transformed our ordinary Rectangle model class to a Core Data entity. Core Data entities are designed using a visual designer and are implemented using NSManagedObject class. You define all the attributes and then Core Data takes care of the rest. Here is our Rectangle class, redesigned as a Core Data entity:


Figure 3: Width binding to a text field


Figure 4: Rectangle entity

We also showed how you subclass NSManagedObject to add in additional derived attributes, such as area and perimeter. Using Core Data to implement your model classes also means you get undo support for free. Any changes made to your model are automatically registered with the undo manager. By handling undo and object persistence support, Core Data saves you from writing a lot of code.

Conclusion

That wraps up a whirlwind summary of what we've learned about programming on Mac OS X. If you haven't already, give it all a try! And check back next month for more adventures on The Road to Code.


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/.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Apple Pro Video Formats 2.0.1 - Updates...
Apple Pro Video Formats brings updates to Apple's professional-level codes for Final Cut Pro X, Motion 5, and Compressor 4. Version 2.0.1: Support for the following professional video codecs Apple... Read more
Maya 2015 - Professional 3D modeling and...
Maya is an award-winning software and powerful, integrated 3D modeling, animation, visual effects, and rendering solution. Because Maya is based on an open architecture, all your work can be scripted... Read more
EtreCheck 2.2 - For troubleshooting your...
EtreCheck is a simple little app to display the important details of your system configuration and allow you to copy that information to the Clipboard. It is meant to be used with Apple Support... Read more
OmniOutliner Pro 4.2 - Pro version of th...
OmniOutliner Pro is a flexible program for creating, collecting, and organizing information. Give your creativity a kick start by using an application that's actually designed to help you think. It's... Read more
VLC Media Player 2.2.1 - 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
Nisus Writer Pro 2.1.1 - Multilingual wo...
Nisus Writer Pro is a powerful multilingual word processor, similar to its entry level products, but brings new features such as table of contents, indexing, bookmarks, widow and orphan control,... Read more
Tinderbox 6.2.0 - Store and organize you...
Tinderbox is a personal content management assistant. It stores your notes, ideas, and plans. It can help you organize and understand them. And Tinderbox helps you share ideas through Web journals... Read more
OmniOutliner 4.2 - Organize your ideas,...
OmniOutliner is a flexible program for creating, collecting, and organizing information. Give your creativity a kick start by using an application that's actually designed to help you think. It's... Read more
calibre 2.25.0 - Complete e-library mana...
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
Things 2.5.4 - Elegant personal task man...
Things is a task management solution that helps to organize your tasks in an elegant and intuitive way. Things combines powerful features with simplicity through the use of tags and its intelligent... Read more

Watch This Homerun is Batting for the Ap...
Eyes Wide Games' Watch This Homerun is purportedly the first sports game coming to the Apple Watch, where you'll be up to bat as the pitcher tries to out-manuever you with fastballs, curveballs, and changeups. Using one-touch controls you can try to... | Read more »
Field Trip Can Take You on a Guided Tour...
Field Trip, by Google’s Niantic Labs, is an exploration app that gives you details about the awesome places you can discover wherever you find yourself. The app can show you local history, delicious restraunts, the best places to shop, and places to... | Read more »
Watch Your Six - SPY_WATCH is Infiltrati...
SPY_WATCH, by Bossa Studios, is a new game designed for the Apple Watch. Runmor has it your spy agency has fallen out of favor. To save it, you'll need to train-up a spy and send them on missions to earn you a stunningly suspicious reputation and... | Read more »
Both Halo: Spartan Assault and Halo: Spa...
Halo: Spartan Assault and Halo: Spartan Strike, by Microsoft, have officially landed on the App Store. Spartan Assault pits you against the Covenant with missions geared to tell the story of the origin of Spartan Ops. In Spartan Strike you'll delve... | Read more »
The Apple Watch Could Revolutionize the...
It’s not here yet but there’s that developing sneaky feeling that the Apple Watch, despite its price tag and low battery life, might yet change quite a lot about how we conduct our lives. While I don’t think it’s going to be an overnight... | Read more »
Mad Skills Motocross 2 Version 2.0 is He...
Mad Skills Motocross 2 fans got some good news this week as Turborilla has given the game its biggest update yet. Now you'll have access to Versus mode where you can compete against your friends in timed challenges. Turborilla has implemented a... | Read more »
Kids Can Practice Healthy Living With Gr...
Bobaka is releasing a new interactive book called Green Riding Hood  in May. The app teaches kids about yoga and organic style of life through mini-games and a fun take on the classic Little Red Riding Hood fairy tale. | Read more »
Chainsaw Warrior: Lords of the Night has...
It's time to put the Darkness back in its place now that Chainsaw Warrior: Lords of the Night has officially made it to iOS. | Read more »
A World of Ice and Fire Lets You Stalk 2...
George R. R. Martin’s A World of Ice and Fire, by Random House, is a mobile guide to the epic series. The new update gives you the Journeys map feture that will let you track the movements of 25 different characters. But don't worry, you can protect... | Read more »
Gameloft Announces Battle Odyssey, a New...
Battle Odyssey, Gameloft's newest puzzle RPG, is coming to the App Store next week. Set in the world of Pondera, you will need to control the power of the elements to defend the world from evil. You'll be able to entlist over 500 allies to aid you... | Read more »

Price Scanner via MacPrices.net

Sale! 15-inch Retina MacBook Pros for up to $...
 MacMall has 15″ Retina MacBook Pros on sale for up to $255 off MSRP. Shipping is free: - 15″ 2.2GHz Retina MacBook Pro: $1794.99 save $205 - 15″ 2.5GHz Retina MacBook Pro: $2244.99 save $255 Adorama... Read more
New 2015 MacBook Airs on sale for up to $75 o...
Save up to $75 on the purchase of a new 2015 13″ or 11″ 1.6GHz MacBook Air at the following resellers. Shipping is free with each model: 11" 128GB MSRP $899 11" 256GB... Read more
Clearance 13-inch Retina MacBook Pros availab...
B&H Photo has leftover 2014 13″ Retina MacBook Pros on sale for up to $250 off original MSRP. Shipping is free, and B&H charges NY sales tax only: - 13″ 2.6GHz/128GB Retina MacBook Pro: $1129... Read more
Clearance 2014 MacBook Airs available startin...
B&H Photo has clearance 2014 MacBook Airs available for up to $200 off original MSRP. Shipping is free, and B&H charges NY sales tax only: - 11″ 128GB MacBook Air: $729 $170 off original MSRP... Read more
Taichi Temple First Tai Chi Motion Sensor App...
Zhen Wu LLC has announced the official launch of Taichi Temple 1.0, the first motion sensor app for Tai Chi, offering a revolutionary new way to de-compress, relax and exercise all at the same time.... Read more
CleanExit – Erase your Hard Drive Quickly, Se...
CleanExit works on both Macs and PCs, securely and permanently deleting all files from any type of hard drive, flash-based drive or camera media card making the files permanently unrecoverable.... Read more
250 iPhone 6 Tips eBook Released for $1.99
Bournemouth, UK based iOS Guides has released 250 iPhone 6 Tips, a new eBook available in the iBookstore that reveals a wealth of tips and tutorials for iPhone 6 and iPhone 6 Plus. Priced at $1.99,... Read more
TigerText Introduces First Secure Enterprise...
TigerText, a provider of secure, real-time messaging for the enterprise, has announced the launch of TigerText for the Apple Watch. TigerText for the Apple Watch enables users to securely send and... Read more
The Conservation Fund Partners with Apple To...
The Conservation Fund has announced that it will partner with Apple to help protect working forests in the United States. The Apple initiative will conserve more than 36,000 acres of working... Read more
Clearance 13-inch 2.6GHz Retina MacBook Pro a...
B&H Photo has clearance 2014 13″ 2.6GHz/128GB Retina MacBook Pros now available for $1099, or $200 off original MSRP. Shipping is free, and B&H charges NY sales tax only. Read more

Jobs Board

*Apple* Solutions Consultant - Retail Sales...
**Job Summary** As an Apple Solutions Consultant (ASC) you are the link between our customers and our products. Your role is to drive the Apple business in a retail Read more
*Apple* Solutions Consultant - Retail Sales...
**Job Summary** As an Apple Solutions Consultant (ASC) you are the link between our customers and our products. Your role is to drive the Apple business in a retail Read more
DevOps Software Engineer - *Apple* Pay, iOS...
**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
*Apple* Pay - Site Reliability Engineer - Ap...
**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
Sr. Technical Services Consultant, *Apple*...
**Job Summary** Apple Professional Services (APS) has an opening for a senior technical position that contributes to Apple 's efforts for strategic and transactional Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.