Home > 2010 Winter DPS913 > Introduction to Cocoa for Seneca SCS students

Introduction to Cocoa for Seneca SCS students

January 13, 2010 Leave a comment Go to comments

This post introduces School of Computer Studies students to Cocoa.

At the beginning of the Objective-C introduction, you learned that Cocoa provides the programmer with a rich library of Objective-C classes, as well as an execution environment (aka “runtime”). We’ll learn more about Cocoa now.

Many of the Mac’s apps are Cocoa apps:

  • Finder (in 10.6+)
  • Safari
  • Mail
  • Xcode
  • iPhoto
  • iWork (Pages, Numbers, Keynote)

The preferred programming language of Cocoa is Objective-C. Keep this in mind as you consider that the Java platform typically uses Java, and the .NET Framework platform uses C#.

Cocoa frameworks introduction

A Cocoa framework is a library of classes and functionality. There are classes for just about any need and function. There are two important frameworks that new iPhone OS programmers will encounter, Foundation, and UIKit. There are many others however, and you will encounter some of them later in the course.

The Foundation framework includes the core classes in Objective-C. Here are a few highlights.

NSObject is the root class for most Objective-C classes. The new classes that you write will inherit directly from NSObject, or from subclass of NSObject. It includes common state information (e.g. class type/kind, text description, etc.) and common methods (e.g. initialization, introspection, etc.).

Strings are available in NSString and NSMutableString. As the name suggests, an NSString instance cannot be changed after creation.

Cocoa has collection classes. There are immutable and mutable versions of array (NSArray), dictionary (NSDictionary), and set (NSSet). The members of the collection classes can be objects of any type. The members do not have to be all the same type. However, the members must be objects. Therefore, if you want to include a C scalar type as a member, it must be in an object wrapper (like NSNumber for an int, float, or double).

There are Foundation classes that abstract operating system facilities. For example, there is an NSFileManager, which (as its name suggest) enables you to work with the file system. Many others are available.

It is possible to write an app that uses only Foundation classes. We will do this periodically, by creating (as we did in our very first app today) a Mac OS X Console Application. This tactic, often used during testing and prototyping, enables us to focus on the task we want to test, without carrying along all the UI baggage.

The UIKit includes classes that are needed and useful in iPhone OS apps. (The AppKit framework includes classes for Mac OS apps.) Here are a few highlights.

UIApplication provides a single and centralized point of control and coordination for an iPhone OS app. A single UIApplication object gets created when your iPhone OS app launches. It handles user events, and dispatches messages forwarded to it by control objects (e.g. a user interface “button”) to the configured target object.

The user interface is a UIView object. An iPhone OS app has a single window, on which views (rectangular areas) are drawn and layered. Some of these subviews are “controls” – subclasses of UIView that handle events. Examples include a UIButton and UITextField.

iPhone OS apps also make extensive use of controller classes. UIViewController provides view management for a screen full of user interface content. UIViewController is also part of the event handling hierarchy (aka the responder chain). We work with view controllers right away in this course, and with other controllers in the coming weeks.

Where do I get good documentation?

This is always one of the most difficult questions to answer. Why? As individuals, we each have our own view of what “good documentation” is. I will suggest the path through the material, as listed on the “DPS913 Virtual Textbook” page of my web site. Although I won’t be able to answer the question directly, here is my experience, which is typical of others.

Most of the documentation is provided by Apple. It is good documentation, but you won’t realize it immediately. Initially, it may even frustrate you. One of your first complaints will be the lack of code samples. Well, I will teach you how to use the Apple docs, and reveal their utility and value to you. Additionally, if you learn the foundational concepts and skills – starting now, today – you’ll realize that Objective-C is largely self-documenting, so the need for code samples is reduced. (Hopefully, in the future, the Apple docs will include more code samples for newbies, because it really would be useful.)

There are some good books available that help the beginner learn iPhone OS and Mac OS programming. Many are available on the Seneca library’s online books service. Here are a few that I have relied on in the past year or so:

  • Beginning iPhone 3 Development – Mark, and LaMarche
  • More iPhone 3 Development – Mark, and LaMarche
  • iPhone SDK Development – Dudney, and Adamson
  • Cocoa Programming for Mac OS X – Hillegass
  • Learn Objective-C on the Mac – Dalrymple, and Knaster

One caution I have is the use of a search engine to locate “how to” information and code samples. Much of the content “out there” is unsuitable for your use. Sorry, that’s just the way it is. Reliable information seems to be consistently available on Stack Overflow, and typically on the blog and service sites that the above textbook authors are affiliated with. Sporadically elsewhere, you’ll find good content, but if you learn the foundational concepts and skills, you’ll end up appreciating the Apple documentation.

How does an app start up, run, and terminate?

As noted earlier, Cocoa provides a runtime execution environment. When you launch your program, your “main” function (entry point) causes the Cocoa runtime to begin. Then, the runtime takes over. Cocoa starts your app, and then calls your code. Cocoa determines, based on your code, when the user interface needs to draw, and it tells your app when an event happens, like a touch or mouse/keyboard action.

Event handling in Cocoa

You learned earlier (in the section titled “So, where does my code go? What code do I write?”) that you write your code in existing or new classes. Essentially, you are writing event handler methods. When your app launches and runs, the Cocoa runtime is in control. The runtime calls your methods at the right time, as the user interacts with the app.

Existing classes that are provided by an Xcode project template often have empty, default, or commented-out methods that you can override and/or implement with your own custom code (and, of course, you can add your own methods). If you have examined the <appname>ViewController that the Xcode iPhone OS View-based Application template provides, you will have noticed the methods, and probably wondered where they came from. Let’s explain:

  • viewDidLoad – inherited from UIViewController – commented out – called (by the Cocoa runtime) after the (user interface) view has loaded
  • shouldAutorotateToInterfaceOrientation: – inherited from UIViewController – commented out – called (by the Cocoa runtime) after it detects a portrait/landscape device orientation change
  • dealloc – inherited from NSObject – default implementation – called (by the Cocoa runtime) after the object is sent the “release” message (method); indicates that the caller/user is finished using the object, and its memory can be deallocated

User interface elements, like buttons and text fields, also generate events. These events cause the appropriate action, depending upon the situation. Events are handled by code that implements a design and coding pattern described next. The code can be superclass methods that you override, or your own methods.

As an example, assume that you wish to add a button to the user interface. That’s easy to do here, in a way that’s similar to other platforms. Now what? In other platforms, you may subclass the button, and override the mouse-click method. Do we do this in Cocoa? No. Subclassing is NOT necessary for most classes. It is discouraged. Cocoa prefers other patterns, including delegation, or target/action, or notification.

Introducing the key design and coding patterns in Cocoa apps

Another key foundational concept for new iPhone OS and Mac OS programmers is the design and coding patterns that we use.

  • The model-view-controller design pattern is fundamental to all the apps that you write
  • Delegation is a pattern that you will use in every app
  • Target/action is a pattern that implements typical user interface actions in code
  • Notification is a pattern that is also often used in apps

Let’s introduce each one next.

The model-view-controller (MVC) design pattern

The Cocoa frameworks, perhaps more than any other platform that you’ve worked on, enforce the model-view-controller (MVC) design pattern. The pattern enables you to write an app in a modular and maintainable way. It promotes the separation of concerns:

  • The model code defines state and behaviour for your app’s data
  • The view code is concerned only with the presentation of the data and app state to the user; it doesn’t include any app logic
  • The controller code includes the app’s logic, and it mediates between the model and the view

We have actually seen (already!), in the earlier code samples, MVC in action:

  • The Student class modelled a real-life student
  • Although we didn’t see it, a view class (an iPhone screen full of content) would display a Student object’s data
  • The view controller class took care of instantiating a Student object, and setting its state and behaviour

In general, in a typical iPhone OS app (which has a user interface), you will be coding and using the view, and the controller. If the app works with data, you will be coding and using the model too. (Typically, instances of your model object will be created somewhere in your app, often in a controller.)

Delegation pattern

An object (i.e. an instance of a class) can assign responsibilities to a helper object, which is called a “delegate”. The delegate responds (handles) messages to influence or affect the object.

Delegation helps you design and implement your app correctly. It can help you separate, for example, user interface operations/logic, from application logic. Specifically, if a view object event happens (i.e. something happens in the user interface), the event handler code is NOT written in the view object. Instead, the view object assigns the event-handling responsibility to its delegate (perhaps a controller object). The result is that application logic lives where it belongs.

Objects that you already have can make great delegates. There’s no need to define and code a separate object. It’s easy to create a delegate relationship, in code, or by using Interface Builder.

A delegate can service more than one object.

If a delegate method isn’t implemented, no problem. The object dynamically determines whether its delegate implements a method, but if it doesn’t, then no error is generated (by default).

What kind of things can a delegate do? Generally, a delegate can have up to three kinds of methods:

  • Methods that influence or affect the object (e.g. appear, disappear, size/move, terminate, etc.)
  • Methods that are simply informative (i.e. they report that something happened)
  • Methods that are required to configure or operate the object (e.g. provide data for a list or table)

Have we seen a delegate yet? Yes. In our sample iPhone OS app, the <appname>AppDelegate class is a delegate.

What object is it the delegate for? The application object (the instance of UIApplication) that gets instantiated when your app launches.

How do we know this? In the .h interface for <appname>AppDelegate, we see the following syntax:

@interface FirstiPhoneAppAppDelegate : NSObject &lt;UIApplicationDelegate&gt; {

The <UIApplicationDelegate> syntax that follows the name of the superclass is a declaration that this <appname>AppDelegate class, which inherits from NSObject, conforms to the formal protocol called UIApplicationDelegate. This means that our class promises to implement methods (required and any desired optionals) that are defined in the UIApplicationDelegate protocol. So conceptually, FirstiPhoneAppAppDelegate is a helper object, that has been assigned responsibilities by the application object.

(We will cover “protocols” later, in more depth. For now, this explanation should suffice. If you’re familiar with a C# “interface”, the concept is similar to a protocol.)

What delegate methods does <appname>AppDelegate implement? It implements the applicationDidFinishLaunching: optional method.

What’s the benefit of delegation here? Well, we don’t need access to the UIApplication class code. We also don’t have to subclass it and override the applicationDidFinishLaunching: method. All we have to do is decide that <appname>AppDelegate will be the delegate to the application object, and implement the methods that are suitable and appropriate.

Target/action pattern

We just discussed a user interface button in an iPhone OS app. Many of the visible “controls” (which are views with event generators) in the iPhone OS user interface use the target/action pattern:

Target – the object that will receive the message

Action – the name of the method that will be called

While you define your methods in your classes (often a controller), you use Interface Builder to connect event generators to these methods. From the perspective of your view in Interface Builder, you are specifying the target – your controller – and the action – the method that will be called.

Notification pattern

The third style for event handling is to use notifications. In general, objects can “broadcast” interesting events. For example, “I am going to close/terminate”. If another object is interested in this event, it can register for this notification. This pattern is beneficial, because it loosens the coupling between objects.

Multiple objects can listen for the same event. Therefore, like broadcasting, there can be one sender, but multiple listeners. (In contrast, delegation allows multiple senders, but only one listener.)

Notifications are just that – simply informative. Notifications cannot influence/affect the object, or configure/operate the object.

Cocoa memory management introduction

In this section, we will present a brief introduction to memory management for Cocoa applications. Automatic memory management, with garbage collection, is a recent addition to Cocoa (in 2008). Mac OS X apps can optionally use automatic memory management, but iPhone OS apps cannot, so we’ll ignore automatic memory management in this course.

Therefore, you must learn about memory management techniques, and use them in your apps. The techniques are really quite simple and clear:

Objects that YOU create, often with alloc init, must be memory managed by YOU. This means that you must “release” the object when you’re done using it. Otherwise, it will cause a memory leak, which is bad.

However, objects that are given to you, often by class convenience methods, require little or no memory management by you.

To explain, here’s some background information: Cocoa uses a reference counting scheme for memory management. When an object is created, its “retain count” is set to 1. When it is given to another object, or sent the “retain” message, the retain count increments by 1. You send the object the “release” message to indicate that you’re done using it. When the retain count falls to zero, the object’s memory is deallocated by the Cocoa runtime.

The following is a concise memory management rule summary:

If you create an object with any of the following methods, you must release it when you are done using it:

+ alloc

+ new

– copy

– retain

If you are given an object (e.g. from a class convenience method), and you want it retained after the current scope ends:

Send the object the retain message

Later, when you’re done using it, send the object the release message

Now that you know something about memory management techniques, you need to add the following as the third step to the process of declaring and initializing an instance variable: In the .m implementation’s dealloc method, you must send the release message to each instance variable. Use this statement format:

[ instanceVariable release ];




Advertisements
Categories: 2010 Winter DPS913
  1. No comments yet.
  1. January 13, 2010 at 8:11 am

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: