IT tutorials
 
Mobile
 

Introducing the iPhone SDK (part 5) - Programming Paradigms

10/4/2011 5:14:46 PM
- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
iPhone programming centers on two important paradigms: objected-oriented programming and the Model-View-Controller (MVC) design pattern. The iPhone SDK is designed around supporting these concepts in the programs you build. To do this, it has introduced delegation (controller) and data source methods (model) and customized view classes (view).

Object-Oriented Programming

Objective-C is heavily based on Smalltalk, one of the most historically important object-oriented languages. Object-oriented programming uses the concepts of encapsulation and inheritance to build reusable classes with published external interfaces and private internal implementation. You build your applications out of concrete classes that can be stacked together like LEGO toys, because it’s always made clear which pieces fit together through class declarations.

Pseudo-multiple inheritance (via invocation forwarding and protocols) provides an important feature of Objective-C’s approach to object-oriented programming. iPhone classes can inherit behaviors and data types from more than one parent. Take the class UITextView, for example. It’s both text and a view. Like other view classes, it can appear onscreen. It has set boundaries and a given opacity. At the same time, it inherits text-specific behavior. You can easily change its display font, color, or text size. Objective-C and Cocoa Touch combine these behaviors into a single easy-to-use class.

Model-View-Controller

MVC separates the way an onscreen object looks from the way it behaves. An onscreen button (the view) has no intrinsic meaning. It’s just a button that users can push. That view’s controller acts as an intermediary. It connects user interactions such as button taps to targeted methods in your application, which is the model. The application supplies and stores meaningful data and responds to interactions such as these button taps by producing some sort of useful result. MVC is best described in the seminal 1988 paper by Glenn Krasner and Stephen Pope, which is readily available online.

Each MVC element works separately. You might swap out a pushbutton with, for example, a toggle switch without changing your model or controller. The program continues to work as before, but the GUI now has a different look. Alternatively, you might leave the interface as is and change your application where a button triggers a different kind of response in your model. Separating these elements enables you to build maintainable program components that can be updated independently.

The MVC paradigm on the iPhone breaks down into the following categories:

  • Model— Model methods supply data through protocols such as data sourcing and meaning by implementing callback methods triggered by the controller.

  • View— View components are provided by children of the UIView class and assisted by its associated (and somewhat misnamed) UIViewController class.

  • Controller— The controller behavior is implemented through three key technologies: delegation, target action, and notification.

Together, these three elements form the backbone of the MVC programming paradigm. Let’s look at each of these elements of the iPhone MVC design pattern in a bit more detail. The following sections introduce each element and its supporting classes.

View Classes

The iPhone builds its views based on two important classes: UIView and UIViewController. These two classes and their descendants are responsible for defining and placing all onscreen elements.

As views draw things on your screen, UIView represents the most abstract view class. Nearly all user interface classes descend from UIView and its parent UIResponder. Views provide all the visual application elements that make up your application. Important UIView classes include UITextView, UIImageViews, UIAlertView, and so forth. The UIWindow class, a kind of UIView, provides a viewport into your application and provides the root for your display.

Because of their onscreen nature, all views establish a frame of some sort. This frame is an onscreen rectangle that defines the space each view occupies. The rectangle is established by the view’s origin and extent.

Views are arranged hierarchically and are built with trees of subviews. You can display a view by adding it to your main window or to another view by using the addSubview method to assign a child to a parent. You can think about views as attaching bits of transparent film to a screen, each piece of which has some kind of drawing on it. Views added last are the ones you see right away. Views added earlier may be obscured by other views sitting on top of them.

Despite the name, the UIViewController class does not act as controllers in the MVC sense. They more often act as view handlers and models than as controllers. Although some will disagree, Apple terminology does not always match the MVC paradigm taught in computer science classes.

View controllers are there to make your life easier. They take responsibility for rotating the display when a user reorients his or her iPhone. They resize views to fit within the boundaries when using a navigation bar or a toolbar. They handle all the interface’s fussy bits and hide the complexity involved in directly managing interaction elements. You can design and build iPhone applications without ever using a UIViewController or one of its subclasses, but why bother? The class offers so much convenience it’s hardly worth writing an application without them.

In addition to the base controller’s orientation and view resizing support, two special controllers, the UINavigationController and UITabBarController, magically handle view shifting for you. The navigation version enables you to drill down between views, smoothly sliding your display between one view and the next. Navigation controllers remember which views came first and provide a full breadcrumb trail of “back” buttons to return to previous views without any additional programming.

The tabbed view controller lets you easily switch between view controller instances using a tabbed display. So if your application has a top ten list, a game play window, and a help sheet, you can add a three-buttoned tab bar that instantly switches between these views without any additional programming to speak of.

Every UIViewController subclass implements a method to load a view, whether through implementing a procedural loadView method or by pulling in an already-built interface from a .xib file and calling viewDidLoad. This is the method that lays out the controller’s main view. It may also set up triggers, callbacks, and delegates if these have not already been set up in Interface Builder.

So in that sense alone, the UIViewController does act as a controller by providing these links between the way things look and how interactions are interpreted. And, because you almost always send the callbacks to the UIViewController itself, it often acts as your model in addition to its primary role as a controller for whatever views you create and want to display. It’s not especially MVC, but it is convenient and easy to program.

Controller

When Apple designs interactive elements such as sliders and tables, they have no idea how you’ll use them. The classes are deliberately general. With MVC, there’s no programmatic meaning associated with row selection or button presses. It’s up to you as a developer to provide the model that adds meaning. The iPhone provides several ways in which prebuilt Cocoa Touch classes can talk to your custom ones. Here are the three most important: delegation, target-action, and notifications.

Delegation

Many UIKit classes use delegation to hand off responsibility for responding to user interactions. When you set an object’s delegate, you tell it to pass along any interaction messages and let that delegate take responsibility for them.

A UITableView is a good example of this. When a user taps on a table row, the UITableView has no built-in way of responding to that tap. The class is general purpose and it has no semantics associated with a tap. Instead, it consults its delegate—usually a view controller class or your main application delegate—and passes along the selection change through a delegate method. This enables you to add meaning to the tap at a point of time completely separate from when the table class was first implemented. Delegation lets classes be created without that meaning while ensuring that application-specific handlers can be added at a later time.

The UITableView delegate method tableView: didSelectRowAtIndexPath: is a typical example. Your model takes control of this method and implements how it should react to the row change. You might display a menu or navigate to a subview or place a check mark next to the current selection. The response depends entirely on how you implement the delegated selection change method.

To set an object’s delegate, assign its delegate property (this is preferred) or use some variation on the setDelegate: method. This instructs your application to redirect interaction callbacks to the delegate. You let Xcode know that your object implements delegate calls by adding a mention of the delegate protocol it implements in the class declaration. This appears in angle brackets, to the right of the class inheritance. Listing 1-1 shows a kind of UIViewController that implements delegate methods for UITableView views. The MergedTableController class is, therefore, responsible for implementing all required table delegate methods.

Xcode’s documentation exhaustively lists all standard delegate methods, both required and optional. Open Help > Documentation (Command-Option-Shift-?) and search for the delegate name, such as UITableViewControllerDelegate. The documentation provides a list of instance methods that your delegate method can or must implement.

Delegation isn’t limited to Apple’s classes. It’s simple to add your own protocol declarations to your classes and use them to define callback vocabularies. Listing 1 creates the FTPHostDelegate protocol, which declares the ftpHost instance variable. When used, that object must implement all three (required) methods declared in the protocol. Protocols are an exciting and powerful part of Objective-C programming, letting you create client classes that are guaranteed to support all the functionality required by the primary class.

Note

If your application is built around a central table view, use UITableViewController instances to simplify table creation and use.


Listing 1. Defining and Adding Delegate Protocol Declarations to a Class Definition
@protocol FTPHostDelegate <NSObject>
- (void) percentDone: (NSString *) percent;
- (void) downloadDone: (id) sender;
- (void) uploadDone: (id) sender;
@end

@interface MergedTableController : UIViewController
<UITableViewDelegate,UITableViewDataSource>
{
UIView *contentView;
UITableView *subView;
UIButton *button;
id <FTPHostDelegate> *ftpHost;
SEL finishedAction;
}
@end

Target-Action

Target-actions are a lower-level way of redirecting user interactions. You encounter these almost exclusively for children of the UIControl class. With target-action, you tell the control to contact a given object when a specific user event takes place. For example, you’d specify which object to contact when users press a button.

Here is a typical example. This snippet defines a UIBarButtonItem instance, a typical buttonlike control used in iPhone toolbars. It sets the item’s target to self and the action to @selector(trackNotifications:). When tapped, it triggers a call to the defining object sending the setHelvetica: message:

UIBarButtonItem *helvItem = [[[UIBarButtonItem alloc]
initWithTitle:@"Helvetica" style:UIBarButtonItemStyleBordered
target:self action:@selector(setHelvetica:)] autorelease];

As you can see, the name of the method (setHelvetica:) is completely arbitrary. Target-actions do not rely on an established method vocabulary the way delegates do. In use, however, they work exactly the same way. The user does something, in this case presses a button, and the target implements the selector to provide a meaningful response.

Whichever object defines this UIBarButtonItem instance must implement a setHelvetica: method. If it does not, the program crashes at runtime with an undefined method call error. Unlike delegates and their required protocols, there’s no guarantee that setHelvetica: has been implemented at compile time. It’s up to the programmer to make sure that the callback refers to an existing method.

Standard target-action pairs always pass either zero, one, or two arguments. These arguments are the interaction object and a UIEvent object that represents the user’s input. Your selector can choose to pass any or all of these. In this case, the selector uses one argument, the UIBarButtonItem instance that was pressed. This self-reference, where the triggered object is included with the call, enables you to build more general action code. Instead of building separate methods for setHelvetica:, setGeneva:, and setCourier:, you could create a single setFontFace: method to update a font based on which button the user pressed.

Note

To build target-action into your own UIControl-style classes, add a target variable of type id (any object class) and an action variable of type SEL (method selector). At runtime, use performSelector: withObject: to send the method selector to the object. To use selectors without parameters, for example, @selector(action), pass nil as the object.


Notifications

In addition to delegates and target-actions, the iPhone uses yet another way to communicate about user interactions between your model and your view—and about other events, for that matter. Notifications enable objects in your application to talk among themselves, as well as to talk to other applications on your system. By broadcasting information, notifications enable objects to send state messages: “I’ve changed,” “I’ve started doing something,” or “I’ve finished.”

Other objects might be listening to these broadcasts, or they might not. For your objects to “hear” a notification, they must register with a notification center and start listening for messages. The iPhone implements many kinds of notification centers. For App Store development, only NSNotificationCenter is of general use.

The NSNotificationCenter class is the gold standard for in-application notification. You can subscribe to any or all notifications with this kind of notification center and listen as your objects talk to each other. The notifications are fully implemented and can carry data as well as the notification name. This name + data implementation offers great flexibility, and you can use this center to perform complex messaging.

It’s easy to subscribe to a notification center. Register your application delegate or, more typically, your UIViewController as an observer. You supply an arbitrary selector to be called when a notification arrives, in this case trackNotifications:. The method takes one argument, an NSNotification. Ensure that your callback method hears all application notifications by setting the name and object arguments to nil.

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(trackNotifications:) name:nil object:nil];

All notifications contain three data elements: the notification name, an associated object, and a user information dictionary. If you’re unsure what notifications UIKitNSLog(@"% @", [notification name]). objects in your application produce, have your callback print out the name from all the notifications it receives—for example,

The kinds of notification vary by the task you are performing. For example, notifications when rotating an application include UIApplicationWillChangeStatusBarOrientation Notification and UIDeviceOrientationDidChangeNotification.

Make sure you implement the trackNotifications: method (or another callback method whose selector you supplied), which gets called in this case for all program notifications, regardless of name or object. Setting these to nil when listening acts as a wild card.

 (void) trackNotifications: (NSNotification *) theNotification
{
CFShow([theNotification name]);
CFShow([theNotification object]);
CFShow([[theNotification userInfo] description]);
}

Note

Each debug feedback method has its advantages and disadvantages. The former have the advantage of not printing out the date and time, which results in cleaner output. How you choose to log information is strictly a matter of taste. There are no wrong or right ways to put print statements into your program.


Model

You’re responsible for building all application semantics—the model portion of any MVC app. You create the callback methods triggered by your application’s controller and provide the required implementation of any delegate protocol. For relatively simple programs, model details often are added to a UIViewController subclass. With more complex code, avoid shoehorning that implementation into a UIViewController. Custom-built classes can better help implement semantic details needed to support an application’s model.

There’s one place that the iPhone SDK gives you a hand with meaning, and that’s with data sources. Data sources enable you to fill UIKit objects with custom content.

Data Sources

A data source refers to any object that supplies another object with on-demand data. Some UI objects are containers without any native content. When you set another object as its data source, by assigning its dataSource property (preferred) or via a call like [uiobject setDataSource:applicationobject], you enable the UI object (the view) to query the data source (the model) for data such as table cells for a given UITableView. Usually the data source pulls its data in from a file such as a local database, from a Web service such as an XML feed, or from other scanned sources. UITableView and UIPickerView are two of the few Cocoa Touch classes that support or require data sources.

Data sources are like delegates in that you must implement their methods in another object, typically the UITableViewController that owns the table. They differ in that they create/supply objects rather than react to user interactions.

Listing 2 shows a typical data source method that returns a table cell for a given row. Like other data source methods, it enables you to separate implementation semantics that fill a given view from the Apple-supplied functionality that builds the view container.

Objects that implement data source protocols must declare themselves just as they would with delegate protocols. Listing 1 showed a class declaration that supports both delegate and data source protocols for UITableViews. Apple thoroughly documents data source protocols. You find this documentation in Xcode’s Documentation window (Help > Documentation).

Listing 2. Data Source Methods Fill Views with Meaningful Content
// Return a cell for the ith row, labeled with its number
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:@"any-cell"];
if (!cell) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero
reuseIdentifier:@"any-cell"] autorelease];
}
// Set up the cell
cell.text = [tableTitles objectAtIndex:[indexPath row]];
return cell;
}

The UIApplication Object

In theory, you’d imagine that the iPhone “model” component would center on the UIApplication class. In practice, it does not, at least not in any MVC sense of the word model. In the world of the Apple SDK, each program contains precisely one UIApplication instance, which you can refer to via [UIApplication sharedInstance].

For the most part, unless you need to open a URL in Safari, recover the key window, or adjust the look of the status bar, you can completely ignore UIApplication. Build your program around a custom application delegate class that is responsible for setting things up when the application launches and closing things down when the application terminates. Otherwise, hand off the remaining model duties to methods in your custom UIViewController classes or to custom model classes.

Note

Use [[UIApplication sharedInstance] keyWindow] to locate your application’s main window object.


Uncovering Data Source and Delegate Methods

In addition to monitoring notifications, message tracking can prove to be an invaluable tool. Add the following snippet to your class definitions to track all the optional methods that your class can respond to:

-(BOOL) respondsToSelector:(SEL)aSelector {
printf("SELECTOR: %s\n", [NSStringFromSelector(aSelector)
UTF8String]);
return [super respondsToSelector:aSelector];
}
 
Others
 
- Introducing the iPhone SDK (part 4) - iPhone Application Components
- Introducing the iPhone SDK (part 3) - Assembling iPhone Projects
- Introducing the iPhone SDK (part 2) - SDK Limitations & Using the Developer Portal
- Introducing the iPhone SDK (part 1) - Understanding Model Differences & Platform Limitations
- iTunes and Your iPad (part 2) - Register Your iPad Without an Apple ID in iTunes & Set Up Your iPad
- iTunes and Your iPad (part 1) - Registering or Activating your iPad the First Time
- Java ME on Symbian OS : MIDP Graphical User Interfaces API (part 3) - Game API
- Java ME on Symbian OS : MIDP Graphical User Interfaces API (part 2) - UIExampleMIDlet
- Java ME on Symbian OS : MIDP Graphical User Interfaces API (part 1)
- Java ME on Symbian OS : Introduction to MIDP & Using MIDlets
 
 
Top 10
 
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
Technology FAQ
- Is possible to just to use a wireless router to extend wireless access to wireless access points?
- Ruby - Insert Struct to MySql
- how to find my Symantec pcAnywhere serial number
- About direct X / Open GL issue
- How to determine eclipse version?
- What SAN cert Exchange 2010 for UM, OA?
- How do I populate a SQL Express table from Excel file?
- code for express check out with Paypal.
- Problem with Templated User Control
- ShellExecute SW_HIDE
programming4us programming4us