Extension: Rotation


In this post we’ll talk about how to handle rotating a UI. We’ll start by using existing constructs to allow our views to support rotation, and then discuss complications and their solutions. Start with a new Single View Application and call it AutoRotate. As usual, I’ll be using ARC. Open the main view controller’s implementation.

Enabling Rotation in Code

First, we have to tell the system that the view controller supports rotation and that it should rotate to a specific orientation. We do this by implementing an existing method on UIViewController:

#pragma mark - Rotation
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
	return (toInterfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

The method might already exist in the file, provided by the template. In that case, simply change the method contents.

In this method, we’re returning a boolean value that tells the system whether to rotate to a specific orientation. We return YES for all supported orientations. Note though that we are not supporting UIInterfaceOrientationPortraitUpsideDown. Apple’s guidelines state that the upside-down orientation should not be supported unless necessary, because might end up being confused about which way is up, an important feature of phones. Of course, this distinction isn’t made on the iPad, and Apple strongly recommends to support all four orientations on iPad. But for now, we’ll support all except upside-down.

Now we’ll build the interface and implement the actual rotation logic—open the XIB. Design an interface like this one. It doesn’t matter exactly what you use, but keep it simple with some of the basic UI elements. The bar at the bottom is a UIToolbar. I put three UIBarButtonItems on it and two Flexible Spacers in between.

Initial View

Initial View

We don’t need to hook up any of the elements, because we’re just concerned with rotating the view. Build and run the app.

Initial View in Simulator

Initial View in Simulator

You can rotate the iPhone Simulator by 90 degrees at a time. Go to the Hardware menu, and then select Rotate Left or Rotate Right. You can also use Command-LeftArrow or Command-RightArrow. The rotation will be accompanied by a corresponding animation, and you’re left with a view that look like this:

Mangled Rotation

Mangled Rotation

While the background rotated (along with the bottom toolbar, which is handled by the system, the rest of the view didn’t change. We can fix that with a few different ways.

Struts and Springs

Struts and springs are a simple IB construct that gives you a few options to stretch and position views. Select the “1” button and go to the Size Inspector (the one with the Ruler icon). You’ll see a section called Autosizing. If you mouse over the Example area to the right, it’ll animate to show you the changes.

Autosizing UI

Autosizing UI

The autosizing area is where you make the changes. You’ll see a square with I-beams (struts) on the outside and double arrows (springs) on the inside. The I-beams on the outside acts as “anchors” to the sides of the containing view. The arrows on the inside tell the subview to expand with the containing view. Behavioral conditions:

  • If all the I-beams are enabled, the subview will stay the same size and anchored near (0,0) in the containing view. On the iPhone, that would be the top-left corner.
  • If no I-beams or double arrows are enabled, the subview will stay in the same size in the center of the containing view.
  • If all the double arrows are enabled but no I-beams, the subview will expand proportionally to the containing view.
  • If all the double arrows and I-beams are enabled, the view will expand with the subview, keeping the same distance around all the edges.

You can see all of this happening in the Example.

We can use these struts and springs to position some of the UI. All the buttons and the label should have both springs enabled. The progress view and slider should have the horizontal spring enabled. Button 1 should have the top and left struts enabled; button 2 should have top and right. Button 3 should have just left; button 4 should have just right. The label should have no struts enabled.

The progress view should have just the left strut; the slider just the right strut. The textview at the bottom should have both springs, the bottom, and left and right struts enabled.

Build and run again, and we see something like this:

Struts & Springs UI

Struts & Springs UI

It’s almost perfect. Springs and struts give you some basic flexibility—it moved our buttons and label nicely—but for more complex situations, like the lower part of our view, we need something more robust.

Swapping Views

Swapping views as necessary gives you the flexibility to structure your views any way you want using the convenience of Interface Builder. Begin by adding two outlets to the view controller’s header:

@property (strong, nonatomic) IBOutlet UIView *portraitView;
@property (strong, nonatomic) IBOutlet UIView *landscapeView;

Synthesize the properties and go over to the XIB. Drag out a new view and go to the Attributes Inspector. Under Orientation in Simulated Metrics, select “Landscape”. Build a view similar to this:

Manual Landscape View

Manual Landscape View

Connect the new view as landscapeView, and the old view as portraitView. Go to the implementation file, where we will handle the swap. Add the following code to the bottom of the file, before the @end:

#define degreesToRadians(x) (M_PI * (x) / 180.0)
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
	if (toInterfaceOrientation == UIDeviceOrientationPortrait) {
		self.view = self.portraitView;
		self.view.transform = CGAffineTransformIdentity;
		self.view.transform = CGAffineTransformMakeRotation(degreesToRadians(0)); 
		self.view.bounds = CGRectMake(0.0, 0.0, 320.0, 460.0);
	}
	else if (toInterfaceOrientation == UIDeviceOrientationLandscapeRight) {
		self.view = self.landscapeView;
		self.view.transform = CGAffineTransformIdentity; 
		self.view.transform = CGAffineTransformMakeRotation(degreesToRadians(-90)); 
		self.view.bounds = CGRectMake(0.0, 0.0, 480.0, 300.0);
	}
	else if (toInterfaceOrientation == UIDeviceOrientationLandscapeLeft) {
		self.view = self.landscapeView;
		self.view.transform = CGAffineTransformIdentity; 
		self.view.transform = CGAffineTransformMakeRotation(degreesToRadians(90)); 
		self.view.bounds = CGRectMake(0.0, 0.0, 480.0, 300.0);
	}
	else
		return;
}

We start with a pre-processor macro that converts degrees to radians. iOS uses radians in its graphics work, but it’s easier for us people to think in degrees. Note that in this case, we will have to do some custom graphics work, because we will have to transform the view to match the rotation.

Inside the delegate method, we check for the corresponding orientation and swap the view in the first line of each condition. Then we reset the view’s transformation. We’ll cover transformations in a future post. We use a provided function to make a rotation transformation and apply it to the view. We also change the size of the view to fit the screen. All of these changes happen in the will method, so they are complete before the actual rotation happen, and the correct view will be displayed in time. Note that animating all aspects of the transition would require additional code, which is beyond the scope of this post.

Rotating Tips

On the iPhone, not all apps support all orientations, or even rotation at all. On iPad, apps should support as many orientations as possible—at least both variants one orientation; preferably all four orientations.

Note that landscape and portrait views don’t necessarily have to present the same information, or even the same appearance. The Music app on the iPhone displays a UIKit-based tab bar and table interface in portrait view, but a custom coverflow interface in landscape.

If you’re doing some custom views/drawing, make sure the view animates when you rotate, especially if you’re displaying content such a grid of icons or text. Otherwise, it is a very disorientating experience for the user and might discourage use of your app.

Finally, make sure there is some meaningful change when the user rotates. If you’re just stretching the UI, consider whether it makes sense to rotate, or if rotation is worth the effort. If you have text input, the larger keyboard might be worth it—but you also loose a large portion of the rest of the content. Otherwise, rotating might not be necessary.

Download AutoRotate here.

Design Patterns: Model-View-Controller


As programs get larger, there is a greater need for a paradigm to keep everything in order. At the simplest level, any program is a means to store data and present it in a meaningful way. With only a few views and a good data store, this might be rather easy in a simple app for iPhone. But with Pages-caliber apps, especially on the iPad, a formal solution is needed. Cocoa adopts the Model-View-Controller paradigm (MVC) to better organize projects.

What is MVC?

MVC Overview

MVC Overview

Under the MVC system, your classes are one of three types—a model, a view, or a controller. Models store data in an organized form. For a simple app, the model could just be the actual data store, either in-memory (maybe as an NSArray or NSDictionary), or to-and-from disk. In a more complex app, you may choose to use a SQLite database or Core Data, and your model would be a simple instance or one piece of data. More importantly to MVC though, your model must not describe how to store the data—it must not contain any information about padding in the UI, for example, or the position (frame) of any item. Models are usually specific to your application, so they usually are not reusable, unless you have a “template” method to store data.

Views are what you actually see on-screen. They have functions to draw to screen or to other contexts. The view should not store the data it is displaying though—a label should not keep its text around; a table view should not store a copy of its data. Instead, along with MVC there are the patterns of delegation and the language features of KVC and KVO. Many of the classes from UIKit, including UILabel, UITableView, UITextView, and indeed UIView are views. Obviously, views, because they just display (any) data, can be very easily reused. Conversely, views of should not be bound to specific data. Some views may be suited to certain types of data—table views are more suited to text; the iPhone’s home screen is more suited for icons and short text—but you should not impose other restrictions, such as a maximum text length or that the text should only be of one case (that’s so 1980s…).

The view and the model should never interact. This preserves reusability. If UITableView had an outlet to your MainDataModel, it could it only be used with MainDataModel. If you had a model class called Person, it wouldn’t work with UITableView (and the Address Book app would never exist). The controller serves as a median. As shown in the image above, the controller controls interaction. If the model changes, the controller is notified and the view is changed accordingly (for example, you could call [tableView reloadData]). If user interaction changes the model (for example, deleting a row from a table view), the controller is also notified, and from there the change gets propagated to the data store. Therefore, the view can just tell the controller that some data at this location got deleted; the view does not have to worry about what to do or how to handle the deletion so it actually gets deleted. This goes back to the concept of abstraction, one of the fundamentals of object-oriented programming. Similarly, the model does not have to be concerned with exactly how the data got deleted, and just delete the data. In this way, the classes are kept clean and perform one function—the point of a class in the first place. Because the controller is the median and has to deal with specific views and data models, it is typically the least reusable. UIViewController implements so little functionality (from a functionality perspective—it actually does a lot behind the scenes) because controllers are very specific to each application. Most of your app logic goes into the controller.

Another compelling reason to use a controller is to make decisions. Obvious, but there are situations where changes to the model or view should not or need not propagate to the other. Without a controller, a change in the data at row 586 would affect the view even if the view was only showing rows 5–10, an unnecessary operation (which may even cause the UI to slow down for a moment). Other times, data should not be deleted, or deleted at a later time—if a file is being written to from another thread, a delete command from the UI should not be executed immediately. The write should be stopped or allowed to finish before the delete occurs.

Mediation

Hand-in-hand with MVC comes the concept of delegation (and data sources). Data sources are obvious—protocols such as UITableViewDataSource make it so a table view can get data from an id type, making the table view very reusable. The controller implements the delegate, and asks its data model for data as necessary (or as the data source methods are called). More interestingly though, the controller can return data that does not correspond to the data model; in fact, the controller could calculate values and not have a data model at all. The table view does not have to know about this though, and does not need to do any extra handling in these cases.

The data source protocol “pushes” data to the view; the delegate goes in the other direction and informs the controller of changes to the view. There is a naming convention involved, which will be the topic of a future post. Again, the controller can notify the model, or not, depending on the situation.

KVC and KVO are not really used in simple applications. However, with multiple controllers that need to interact with each other, KVC and KVO can be used to great benefit. KVO, which stands for Key-Value Observing, registers a class for notifications when a key-value is changed in any other class. This is a more advanced topic, and will form the basis of another post. It is an effective way to allow multiple controllers to communicate without resorting to a tangle of protocols.

Resources

WWDC 2010 had a great lecture on MVC and the “10 Best MVC Tips Ever.” It is highly recommended. Note that you will need to be a registered developer, including free developers.
Video Link | iTunes Link | Slides (9.7MB)

WWDC 2011—Initial Impressions


Today Apple began the annual WWDC week with a keynote that introduced OS X Lion, iOS 5, and iCloud. If you haven’t done so yet, check out the keynote stream. Rather than just re-iterate the new features, I’d like to share some of my thoughts.

Lion

At first, I have to say that as far as features go, it was a bit underwhelming. I do have to say , I’ve been using pre-release seeds of Lion. Because of the NDA, I can’t talk too much more about the exact features…

Having seen and used these features, I realized that from a new user’s perspective the features are actually really compelling. Why did I find them underwhelming? It’s because the features have integrated themselves so smoothly and seamlessly into my daily experience that they’re really not obtrusive. Some commentary:

  • Gestures: I love them. Takes a bit of getting used to at first, but really integrate into my user experience. I love being able to touch everything and directly interact with it. My only complaint is that there is (at the moment, at least) no built-in ability to define custom gestures.
  • Full Screen: Very useful on laptops, not so much on desktops. Could be useful in some cases, but I’m not sure I like it at all. Its usefulness is doubtful, in my opinion.
  • LaunchPad & MAS: The App Store is actually really nice. Convenient, easy, accessible—everything is as advertised. As far as LaunchPad goes, I find it easy enough to use, and with the gesture to invoke from my Magic Trackpad, it joins my repertoire of app launching, along with the Applications stack, Spotlight, and LaunchBar. Not always as smooth as advertised though.
  • AutoSave, Versions, etc.: Very helpful. ‘Nuff Said.
  • Resume: Usually very useful, for when I have a bunch of documents open in Preview, but can be annoying at times. Sometimes the point of quitting an app is to clear out all the windows. It’s a bit more annoying when the files take a while to load, as they might when launching QuickTime. But very useful after a reboot.
  • Mail: Great new interface, no loss of functionality—great recipe.
What happens is that OS X is less of a new OS, and more of a new paradigm. With the further integration of iCloud, it definitely fits this role. That’s also part of the reason why it’s $29.99—a great price for a preview of the future of computing. And yes, I honestly believe that.

iOS 5

  • Notifications: This one was a long time coming. Predicted by rumors for months, this is probably the best way to do notifications in a mobile platform. Very well done.
  • Twitter: I don’t use Twitter. I don’t get Twitter. …
Logo of WebKit framework

WebKit

  • Safari: The tabs are frankly a bit ugly, but the rest of the stuff is awesome. I’ve been a proponent of WebKit since the original iPhone. I love Safari Reader on the desktop, and I’m glad they brought it to iOS.
  • Reminders: Everyone needs this. The problem with To-Do lists though is forgetting to actually use them. Not sure what Reminders is going to do for that.
  • Camera: How do I up the volume in camera mode…? Actually, the features are really nice. If the iPhone 5 bumps the camera specs a bit, it could become a serious competitor to higher-end point-and-shoots, or maybe even some dSLRs…?
  • The New Keyboard: The keyboard on the original iPad always seemed just a little bit too small. I like being able to split the keyboard, but can’t help thinking that simply typing with my thumbs might not be the most efficient. Of course, this isn’t an issue that can be fixed overnight. Why couldn’t the screen have been just a tiny bit bigger…?

iCloud

Actually not sure what to think about this yet. The features look compelling enough, but without having half a dozen Apple devices not sure how well this’ll work. And plus, some companies, schools, etc. might block anything besides in-house cloud services, so its practicality might be limited. We’ll see.

First Impressions

So, that’s some initial commentary. I kept them to short blurbs for a reason—they’re first impressions. Incidentally, for developers, first impressions are absolutely vital. So, what are your thoughts? Post them in the comments below.

What’s in it for us?

Well, all the new APIs must mean something. What happens, though, is that Lion is literally bringing the iOS design paradigms to the desktop. Which means that user interfaces can be re-thought. Instead of simply relying on individual mouse clicks, gestures are now a now interface interaction method. This allows for much more fluid interfaces. What happens is that the design of user interfaces now takes prominence. Always emphasized with iOS, this design-based nature will trickle down to OS X. These interactions are visible in the new Mail, Safari, and iCal (^^). Sometime there will no longer be a single pair of coordinates for a mouse pointer—there will only be multi-touch and gestures. That is the future. And that is what developers must work for.

Objects (Part 2): Properties


Every object is made up of instance variables (iVars) and methods. Our Fraction class, which we really began to build in the last post, contains two iVars, both NSIntegers, called numerator and denominator. Fraction also has two methods, setNumerator: and setDenominator:. These methods will set a value to the corresponding instance variable. In most cases, you would also have a method, with the same name as the instance variable (yes, this is permitted, and in this case, encouraged), which would return the value of the instance variable. These setter and getter methods are referred to as mutator and accessor methods, respectively. These methods are a major concept of object-oriented programming—data encapsulation, the notion that objects hide their instance variables.

At this moment, our Fraction class defines and implements the setter methods (note that we simply have not needed the getter methods so far). However, this would be difficult to do when we start working with large classes, which have many instance variables. This is also not very scalable; the same code to retrieve values for a small block of data stored on an iPhone should probably not be the same code used to retrieve a long string of data from a powerful desktop Mac or even from the internet. Fortunately, there is a very convenient concept that Objective-C provides, and this construct should be used wherever possible.

Properties

Properties replace the accessor methods for an object. Quite simply, our Fraction class’s interface now looks like this:

#import 
@interface Fraction : NSObject { 
	NSInteger numerator; 
	NSInteger denominator; 
}
@property NSInteger numerator; 
@property NSInteger denominator;
- (void)setNumerator:(NSInteger)value; 
- (void)setDenominator:(NSInteger)value;
- (void)display; 
@end

The general form of the property statement is

@property type name

Note that the setter (and if we had them, the getter) methods are no longer needed. We will have the compiler synthesize these methods for us, but placing this line in our implementation, right after the @implementation line:

#import "Fraction.h" @implementation Fraction
@synthesize numerator, denominator 
- (void)setNumerator:(NSInteger)value { 
    numerator = value; 
} 
- (void)setDenominator:(NSInteger)value {
    denominator = value; 
} 
- (void)display { 
    NSString *numeratorString = [[NSString alloc] initWithFormat:@"%d", self.numerator]; 
    NSString *denominatorString = [[NSString alloc] initWithFormat:@"%d", self.denominator]; 
    NSLog(@"%@/%@", numeratorString, denominatorString); 
    [denominatorString release]; 
    [numeratorString release]; 
}
@end 

Of course, the identifiers after the @synthesize have to match the names you declared as properties in the interface. However, the identifiers that you declared after @property do not have the match the instance variables; instance variables will be created at compile time if this happens.

You do not have to change your method calls in your main() routine; the methods still exist. However, there is an easier (and sometimes controversial) way to access these synthesized properties.

The Dot Operator

As previously mentioned, a getter method returns the value of an iVar; a setter sets a value to the iVar.

[myFraction setNumerator: 2] // Set numerator to 2 NSInteger 
numeratorValue = [myFraction numerator]; // returns the value of the numerator, and set to the new variable called numeratorValue

The dot operator, introduced in Objective-C 2.0 (yes, there was a 1.0, but that was a long time ago), allows you to invoke the getter method by writing

iVar.property

and the setter by

iVar.property = value

Therefore, the above example can be re-written as

myFraction.numerator = 2; // Set numerator to 2 
NSInteger numeratorValue = myFraction.numerator; // set value of numerator to numeratorValue 

C programmers might recognize this syntax as being used to access members of a struct—because that is exactly what you are doing. Behind the scenes, an object’s instance variables are stored as a struct. And if you have no idea what this line means, don’t worry—structs are a basic C data type that we may cover in a later lesson.

Property Attributes

In a property declaration, you can specify any number of (non-contradictory) attributes:

@property (attribute1, attribute2, etc.) type name;

A list of possible attributes follows (adapted from Apple’s developer documentation, The Objective-C Programming Language: Declared Properties)

Accessor Method Names

The default names for the getter and setter methods associated with a property are propertyName and setPropertyName: respectively—for example, given a property “foo”, the accessors would be foo and setFoo:. The following attributes allow you to specify custom names instead. They are both optional and may appear with any other attribute (except for readonly in the case of setter=).

  • getter=getterName: Specifies the name of a different (custom) getter method for the property. The method must return a value matching the iVar’s type, and it takes no arguments.
  • setter=setterName: Specifies the name of a different (custom) setter method for the property. The method must return void, and it takes one argument of the same type as the iVar.If you specify that a property is readonly then also specify a setter with setter=, you will get a compiler warning.

Writability

These attributes specify whether or not a property has an associated set accessor. They are mutually exclusive.

  • readwrite: This is the default; this indicates that the property will have read and write capabilities. When synthesized, both the getter and setter will be generated.
  • readonly This indicates that the property can only be read; no data can be assigned to it (through the property). When synthesized, only a getter will be generated; when you try to assign the property a value using dot syntax, a compiler error will be generated.

Setter Semantics

These attributes specify the semantics of the setter. They are mutually exclusive.

  • assign: This is the default; it tells the setter to directly assign the value. This is typically delineated with primitive data types (ints, floats, etc.)
  • retain: Specifies that a retain should be called on the object upon assignment; the previous value is released. This is only valid for objects. This has to do with memory management, a topic that will be fully explored in a later lesson.
  • copy: Specifies that the argument passed in should be copied, and the copy will be assigned. The previous value is released. This is only valid for objects. It is used in the case where the original property (perhaps stored on a shared server across the network) should not be modified by any other code, but when other code requests the value, for potential modification.

Atomicity

Atomicity means that the value is written to a temporary location in memory first, and then written to the intended location. This ensures that there is always a valid copy of the data somewhere. If an assignment was not atomic, and something happened during the writing period, the data could become fatally corrupt—the user would lose data. By writing data atomically, the data will either be the original, or the new value—never in a partially written state.

  • nonatomic: Specifies that the object should not be assigned atomically. By default, accessors are atomic (this is more beneficial in a multi-threaded environment, where multiple threads may be reading/writing value to a piece of memory.

CS193P Material

Properties are a very powerful notion, and used throughout the language. If this explanation was not clear enough, please see Lecture 3 of CS193P. The relevant content begins around the 16 minute mark, and ends with a demo around the 45 minute mark. Of course, feel free to view the whole lecture.

The slides for the lecture are available on the CS193P website; for a direct link, click here.

The code for the Fraction class at this moment can be downloaded by clicking here.

Supplement: CS193P


Stanford University has offered the CS193P class for a few quarters now. It has become the ubiquitous source of beginning iPhone programming material for many people. The lectures are filmed and uploaded to iTunes U, and they are now available in 720p HD video. However, the lectures, which are the only option for non-enrolled students, are rather impersonal, and sometimes move too quickly (in my opinion). I have learned a lot from them, but I don’t think they’re the only source. In fact, I find that they are more helpful once I got the basics down. Nevertheless, there are real gems, and so I will be occasionally referring links as supplementary material.

To access the lectures:

  1. Launch iTunes and head into the iTunes Store (don’t worry, all the lectures are free).
  2. Click on iTunes U on the black bar near the top of the storefront.
  3. At the time of this writing, the lectures were under Staff Favorites. Click on the link, and you’ll be led to the main listing.

    CS193P Fall 2010 Lectures Listing

    iTunes Listing

Direct link (will open iTunes, if it is not already running):
http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=395605774

The lectures are available for streaming; alternatively, you can download them just like regular songs from iTunes. Note that file sizes are around 500MBs for the SD version and around 700MBs for the (linked) HD version.

The slides can be downloaded from the main website, listed above, as well as the sample code.

Objective-C Lesson 5: Loops


A computer is really good at executing the same thing over and over again. A lot of programming involves doing the same thing over and over again (and no, that’s not meant to be a programming joke, although it could certainly be taken as one). Objective-C allows for two main ways of looping. We’ll start with a rather general problem.

The for() Loop

The Problem

Create a program that displays the sum of all the numbers from 1 to a user-specified value. Note that to get a user-specified value, we are going to be using a function call to scanf(), which is similar to NSLog, except that it reads input, rather than exporting it. A brief explanation will follow, but scanf() is not a function that you will regularly use on the iPhone. It is just a “place-holder” way to get input until we can use better options.

As for the problem itself, we are adding all the numbers between 1 and the input. So if the input was 5, we would output the sum as 1 + 2 + 3 + 4 + 5, or 15.

The (Inefficient) Solution

We could just take all the values and simply add them up:

int sum = 1 + 2 + 3 + 4 + 5;

sum would equal 15, just as expected. But although this method is rather simple and the most logical at this point, it is not very efficient, or scalable. If the user had entered a large value, such as 1000, writing the code for that would be torturous. But there will be a user who will enter 1000. You will almost never be able to anticipate every single type of input your user might give or do to your program, and you should probably have a solution to handle every case. So how are we going to handle the case of the user inputting 1000—or indeed, any value other than 5 (in this case)?

The Best Solution

We would use a loop. Here is the code to accomplish the problem above, using a for() loop:

#import <Foundation/Foundation.h>int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

	int sum = 0;	// Make sure we start at zero, to avoid issues later

	// Allow user input
	NSLog(@"Please enter a value.");
	int times;
	scanf("%d", &times);

	// for() loop construct:
	for(int n = 1; n <= times; n = n + 1)
		sum = sum + n;

	NSLog(@"Sum of all values from 1 to %d is %d", times, sum);

    [pool drain];
    return 0;
}

The output shows that for an initial value of 1000, the sum is 500500.

Code Demystified

The for() loop is basically three statements in one line. Within the parentheses following the “for”, you have the initial expression, condition, and the loop expression. These are separated by semicolons.

Initial Expression

This statement is usually used to initialize variables used in the loop and assign them values. Usually this will be a counter of some sort which will not be used elsewhere in the program. In this case, I like to declare the variable and assign it a value at the same time, as I did above, rather than having int n; and then n = 1; in the loop. It just makes the code more concise.

You can initialize and declare more than one variable at a time: int a = 0, b = 3, c = 5;. For the most part though, you will only need some form of a (integer) counter variable, and you won’t need multiple variables. You could still use that to your advantage, though.

It is important to note that any variables you initialize here (initialize means that you have not made any mention of this variable before, and you are creating a new variable here) are only valid within the loop—as soon as you exit the loop (described below) the variable is no longer accessible.

Condition

This is a boolean condition that determines if the loop is still valid. If this expression becomes untrue (usually due to the loop expression), then the program exits out of the loop without running through the loop again. The program then moves on to the next line after the loop.

Remember that when comparing integers, as you usually will when using a loop, the following two expressions are equivalent: n <= 1000; and n < 1001;. But in this case, because you are only checking up to 1000 (and because the user entered 1000, and you should avoid modifying the input if possible; in addition, having to add one to the input just to use a less-than construct is not a good choice), the first expression makes more logical sense.

Loop Expression

This is an expression that is executed after the main body of the loop; it is usually a way to increment the initialized variable(s). In this case, the counter variable n is incremented by 1, so that eventually the loop condition will become false.

General Operational Procedure

Excerpted from Stephen Kochan’s Programming in Objective-C 2.0, 2nd Edition published by Addison-Wesley, &copy2009:

  1. The initial expression is evaluated first. This expression usually sets a variable that is used inside the loop, generally referred to as an index or counter variable, to some initial value (often 0 or 1).
  2. The looping condition is evaluated. If the condition is not satisfied (the expression is FALSE or NO), the loop immediately terminates. Execution continues with the program statement that immediately follows the loop.
  3. The program statement(s) that constitutes the body of the loop is executed.
  4. The looping expression is evaluated. This expression is generally used to change the value of the index variable, frequently by adding or subtracting 1.
  5. Return to step 2.

The while() Loop

This is another type of loop that Objective-C supports. Although most tutorials and textbooks would consider them (roughly) equivalent, I use for() loops whenever I know how many times I want to go through, whether it is by a hard-coded value or by a the value in a variable. The while() loop is better suited for cases where the program does not know how many times it is to be run, and instead checks for a different condition. This can be better illustrated with an example.

The Problem (Revised)

Calculate the sum of all the integers that the user enters; the user input is terminated by any negative value.

The Solution

This would be very difficult to do with a for() loop, as you do not know how many times to execute. You would have to do an ugly check in the loop condition. A while() loop makes this more elegant.

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

	NSLog(@"Input a list of integers. Hit Return after each one. End the list with a negative value.");
	int sum = 0;
	int input = 0;
	scanf("%d", &input);

	while (input >= 0) {	// "Greater-than or equal to zero" is the same as "not negative"
		sum = sum + input;
		scanf("%d", &input);
	}

	NSLog(@"The sum of all those values is %d", sum);    [pool drain];
    return 0;
}

Here is a sample run:

Input a list of integers. Hit Return after each one. End the list with a negative value.
5
2
18
30
37
69
-29
The sum of all those values is 161

Code Demystified

The expression for the while() loop is a simple boolean condition (the middle part of the for() loop). This gets evaluated, and if it is true, the body is executed. If not, the program moves on. This means that in the loop, you have to make the value untrue somehow; otherwise you will get an infinite loop.

The do-while Loop

In a regular for() or while() loop, the condition is checked first, then the loop is executed. This means that if the initial condition was false to begin with, the body of the loop would never ever get executed; the code would skip directly over the loop. The do-while loop is guaranteed to perform one iteration of the loop first, before checking the condition. From that point on, as long as the condition remains true, the loop will continue to execute. The syntax is as follows:

int n = 1;
do {
	sum = sum + n;
	n = n + 1;
} while (n <= 5);

The above example is a re-writing of the previous loop examples, using the do-while construct. A more compelling example might look like this:

int sum = 0;
int input = 0;
do {
	sum = sum + input;
	NSLog(@"Sum is %d", sum);
	scanf("%d", &input);
} while (input != -1);

In the above example, the program will continue to display the sum of all the values the user enters until negative 1 is entered. The loop in this case ensures that the NSLog is printed at least once, and the user input is gathered; in this case, the input is placed in the loop, rather than having to have an additional scanf() outside of the loop. This makes the code a little easier to read and understand.

Pitfalls

A few things that people get tripped up on:

  • Forgetting braces: If you have more than one statement that you want to execute given a certain condition, you must enclose them within curly braces. Otherwise, they can stand alone as one line, without braces.
  • The Infinite Loop: The loop condition must be made false, somehow. (It’s also a really good idea to actually have a loop condition). Otherwise, your loop will never end, and it keep running until your computer crashes, or until the power goes out.

Conclusion

Loops are relatively easy to implement, yet they can save you a lot of coding. For a big loop, like in the first example, you truly begin to leverage your computer’s processing power, and save yourself a lot of work. When combined with if() statements, they can become quite powerful.

iOS 4.2 Beta 3 Now Available!


It’s been a month or so since beta 2…but beta 3 came out (yesterday). I love new software; I usually don’t consider myself a beta tester, but in this case I can make an exception.

A few novel features include new wallpaper and new SMS ringtones.

However, it appears that the native YouTube app has lost AirPlay capability. Apparently AirPlay is not native to movie files, but can be enabled or disable by the developer. We’ll see what this means.

The download awaits.

Shameless Self-Promotion


To get the word out, I’d generally rely on search engines. And I can’t afford to pay Google to get listed (and most of those ads aren’t exactly reputable anyway). So, here’s some shameless self promotion. I promise I won’t really do this much more. Feel free to not read this. You may want to entertain yourself elsewhere (I’d recommend Uncyclopedia).


Cups of Cocoa Cups of Cocoa Cups of Cocoa Cups of Cocoa Cups of Cocoa Cups of Cocoa Cups of Cocoa Cups of Cocoa

iPhone App Development iPhone App Development iPhone App Development iPhone App Development

iPhone Application Development iPhone Application Development iPhone Application Development

Programming for iOS Programming for iOS Programming for iOS Programming for iOS Programming for iOS

iPhone App iPhone App iPhone App iPhone App iPhone App iPhone App iPhone App iPhone App iPhone App

iPhone Apps iPhone Apps iPhone Apps iPhone Apps iPhone Apps iPhone Apps iPhone Apps iPhone Apps

Creating iPhone Apps Creating iPhone Apps Creating iPhone Apps Creating iPhone Apps Creating iPhone Apps

iPhone Programming iPhone Programming iPhone Programming iPhone Programming iPhone Programming iPhone Programming

Developer Developer Developer Developer Developer Developer Developer Developer Developer Developer Developer

iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS

App Store App Store App Store App Store App Store App Store App Store App Store App Store App Store App Store

Programming Programming Programming Programming Programming Programming Programming

iPhone iPhone iPhone iPhone iPhone iPhone iPhone iPhone iPhone iPhone iPhone iPhone iPhone

iPod Touch iPod Touch iPod Touch iPod Touch iPod Touch iPod Touch iPod Touch iPod Touch

iPad iPad iPad iPad iPad iPad iPad iPad iPad iPad iPad iPad iPad iPad iPad iPad iPad iPad iPad iPad

Xcode Xcode Xcode Xcode Xcode Xcode Xcode Xcode Xcode Xcode Xcode Xcode Xcode Xcode Xcode

Objective-C Objective-C Objective-C Objective-C Objective-C Objective-C Objective-C Objective-C

Apple Apple Apple Apple Apple Apple Apple Apple Apple Apple Apple Apple Apple Apple Apple Apple

Cocoa Cocoa Cocoa Cocoa Cocoa Cocoa Cocoa Cocoa Cocoa Cocoa Cocoa Cocoa Cocoa Cocoa Cocoa

iPhone SDK iPhone SDK iPhone SDK iPhone SDK iPhone SDK iPhone SDK iPhone SDK iPhone SDK

Software Software Software Software Software Software Software Software Software Software Software

Object-Oriented Programming Object-Oriented Programming Object-Oriented Programming Object-Oriented Programming


😀

  • Welcome

    My goal is to make CupsOfCocoa into a beautiful source for beginners to the iPhone platform to get started. Subscribe below for more, and stay tuned!

  • Contact Me

    If you need to contact me for any reason, feel free to send me an email.
  • The Giving Spirit

    If you've found this site helpful, would you consider donating a little sum? Any amount is appreciated...Thanks so much!

  • Roadmap

  • Enter your email address to follow this blog and receive notifications of new posts by email.

    Join 220 other followers

  • Back to the Past

    May 2020
    S M T W T F S
     12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31  
  • Time Machine

  • You count!

    • 622,650 views
  • Worldwide Stats

    free counters
%d bloggers like this: