Search Posts in my Blog

Monday 25 June 2012

A Color Chooser for the iPhone



In this blog we’ll show an interesting way to set the background color of a view. We’ll also be looking at different ways to represent the same data, and converting from one representation to another. So, let’s get started!
Start up Xcode, choose Create a new Xcode project, choose the Single View Application template, name the project ColorChooser, and select the options shown here:
Click Next, choose a location to save the project, and then click Create.
Open the MainStoryboard.storyboard file, and drag controls (6 UILabels, 3 UISliders, and 3 UITextFields) to the view. Arrange them thus:
Change the text in the label controls to match the image above. For the sliders, change these values in the Attributes inspector:
Also change the Keyboard value for the three text fields to “Numbers and Punctuation” and the Return Key value to “Done” as shown:
Open the ViewController.h file, and make the changes shown:
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (nonatomic, strong) IBOutlet UISlider *redSlider;
@property (nonatomic, strong) IBOutlet UISlider *greenSlider;
@property (nonatomic, strong) IBOutlet UISlider *blueSlider;
@property (nonatomic, strong) IBOutlet UITextField *redText;
@property (nonatomic, strong) IBOutlet UITextField *greenText;
@property (nonatomic, strong) IBOutlet UITextField *blueText;
@property (nonatomic, strong) IBOutlet UILabel *hexLabel;
- (IBAction)sliderChanged:(UISlider *)sender;
- (IBAction)textFieldChanged:(UITextField *)sender;
@end
We’ve added properties (as outlets) for the sliders, the text fields, and one of the labels, and also action method headers for the sliders and text fields. Return to the MainStoryboard.storyboard file. Right – click on the View Controller object, and drag from the outlets to their corresponding controls. The redSlider is in the top position, the greenSlider is in the middle, and the blueSlider is at the bottom. Likewise, the redText is at left, the greenText is in the middle, and the blueText is at the right. The hexLabel is the label into which we placed the text #000000 initially.
Finally, change the background color of the main view to black. Don’t worry that this makes the labels’ text invisible, we’ll take care of that in code.
Drag from the sliderChanged action (still in the View Controller’s popup menu) to all three slider controls. In the popup for each, select the Value Changed event. Also drag from the textFieldChanged action to all three text field controls; in their popups, select the Did End On Exit event. When you are finished, the View Controller’s connections should look like this:
Make sure you’ve made all these connections correctly, then open the ViewController.m file. Make the following changes:
#import "ViewController.h"
@interface ViewController ()
- (void) setLabelColorsToContrastWithBackground;
@end
@implementation ViewController
@synthesize redText, redSlider;
@synthesize greenText, greenSlider;
@synthesize blueText, blueSlider;
@synthesize hexLabel;
#pragma mark – private method
- (void) setLabelColorsToContrastWithBackground
{
    CGFloat redValue, greenValue, blueValue, alphaValue;
   
    //set each label’s color to contrast with the background:
    [self.view.backgroundColor getRed:&redValue
                                green:&greenValue
                                 blue:&blueValue
                                alpha:&alphaValue];
   
    for (id subview in self.view.subviews) {
        if ([subview isMemberOfClass:[UILabel class]]) {
            [subview setColor:
             [UIColor colorWithRed:- redValue
                             green:- greenValue
                              blue:- blueValue
                             alpha:1]];
        }
    }
}
#pragma mark – action methods
- (IBAction)sliderChanged:(UISlider *)sender
{
    //set the background color from the sliders:
    self.view.backgroundColor =
        [UIColor colorWithRed:(self.redSlider.value / 255)
                        green:(self.greenSlider.value / 255)
                         blue:(self.blueSlider.value / 255)
                        alpha:1];
    //set the text fields:
    self.redText.text =
        [NSString stringWithFormat:@"%d"(int)self.redSlider.value];
    self.greenText.text =
        [NSString stringWithFormat:@"%d"(int)self.greenSlider.value];
    self.blueText.text =
        [NSString stringWithFormat:@"%d"(int)self.blueSlider.value];
    //set the hexadecimal value in the label using format specifiers:
    self.hexLabel.text =
        [NSString stringWithFormat:@"#%02X%02X%02X",
            (int)self.redSlider.value,
            (int)self.greenSlider.value,
            (int)self.blueSlider.value];
   
    [self setLabelColorsToContrastWithBackground];
}
- (IBAction)textFieldChanged:(UITextField *)sender
{
    //set the sliders from the integer values of the texts:
    self.redSlider.value = [self.redText.text intValue];
    self.greenSlider.value = [self.greenText.text intValue];
    self.blueSlider.value = [self.blueText.text intValue];
   
    //set the background color from the sliders:
    self.view.backgroundColor =
    [UIColor colorWithRed:(self.redSlider.value / 255)
                    green:(self.greenSlider.value / 255)
                     blue:(self.blueSlider.value / 255)
                    alpha:1];
   
    //set the hex value in the label using format specifiers:
    self.hexLabel.text =
        [NSString stringWithFormat:@"#%02X%02X%02X",
            (int)self.redSlider.value,
            (int)self.greenSlider.value,
            (int)self.blueSlider.value];
   
    [self setLabelColorsToContrastWithBackground];
}
#pragma mark – View Controller delegate methods:
- (void)viewDidLoad
{
    [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
    [self setLabelColorsToContrastWithBackground];
}
- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
   
    //we can do this type of chained C assignment as long as
  //the types are the same:
    self.redText = self.blueText = self.greenText = nil;
  self.redSlider = self.blueSlider = self.greenSlider = nil;
  self.hexLabel = nil;
}
In a .m file, the @interface / @end section encloses what is known as a class extension in Objective – C. In a class extension, we can place any properties or methods that we don’t want to be public members of the class. (All properties and methods in the .h file are public, meaning that they are visible to any classes that instantiate the class.) Here, we declare a private method called setLabelColorsToContrastWithBackground.
Next, we @synthesize all of the properties we declared in the .h file. Note that we can synthesize more than one property on a line. Often it makes sense to group these logically, as we’ve done here.
After synthesizing the properties, we implement the private method we just declared. This method sets the labels’ colors to contrast with the color of the view’s background. It does this by obtaining the red, green, and blue values of the current background color, then setting each label’s color to these values subtracted from 1. Note the use of fast enumeration (the for in loop) to get all the subviews of the main view. We determine if the subview is a label before attempting to set it’s color, for two reasons: first, not all controls may have a setColor method, and second, we really don’t want to set the color of anything but a label. This way of doing things avoids setting the color of six labels individually.
Next we define the sliderChanged: method. First we set the background color according to the values of the sliders. But we have to convert between the 0..255 range of the slider to the 0..1 range expected by the RGBA components of the UIColor structure. This is done by dividing each slider’s value by 255 before passing it to the colorWithRed: Green: Blue: Alpha: method.
We then set the text fields to an integer representation of each slider’s value. Slider controls actually post their values as floats, not integers; this necessitates that we cast each value to an int before sending it to the format specifier %d.
Finally, we build the hexadecimal string for display in the hexLabel by using the format string
@”#%02X%02X%02X” with each slider’s int value. This will print a #, followed by a hexadecimal representation of the int value passed in. The 0 indicates that the digit will be left padded by zero’s within it’s field width, and the 2 indicates the field width. As the last step, we call the setLabelColorsToContrastWithBackground method.
The textFieldChanged: method works in a very similar way to the sliderChanged: method, we’ll leave it up to you to analyze it.
In viewDidLoad, we simply make sure that the labels contrast with the black background we initially set on the view. In viewDidUnload, we set all the subviews of the main view to nil to ensure that the reference counter releases these objects.
Run the ColorChooser, and have fun experimenting with the interface!

Using NSTimer in iPhone



In this blog, we’ll be looking at the NSTimer class. We’ll learn how to schedule a repeating timer which fires once per second, and controls the display of two labels on a view. Let’s see how it works!
To begin, start Xcode and select “Create a new Xcode project” from the Welcome window. Choose the Single View Application template, and click Next. Name the project “TimerDemo” and set the options as shown:
Click Next, choose a location to save the project, and then click Create.
Select the MainStoryboard.storyboard file in the Project Navigator. Drag two UILabels from the library to the view, resize them, center the text in both labels, and change the text as shown:
Select the ViewController.h file, and make the changes shown in bold:
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (nonatomic, strong) IBOutlet UILabel *secondsDisplay;
@property (nonatomic, strong) IBOutlet UILabel *minutesDisplay;
@property (nonatomic, strong) NSTimer *secondsTimer;
@end
As you can see, we are adding two IBOutlets for the two labels we created on the storyboard view, and a third property, which is the timer object. This timer will fire once per second.
Open the ViewController.m file, and make the bolded changes:
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, assign) int seconds;
@property (nonatomic, assign) int minutes;
@end
@implementation ViewController
@synthesize secondsDisplay;
@synthesize minutesDisplay;
@synthesize secondsTimer;
@synthesize seconds;
@synthesize minutes;
- (void) timerFireMethod:(NSTimer *) theTimer
{
    self.seconds++;
    if (self.seconds == 60) {
        self.minutes++;
        self.seconds = 0;
    }
 
    self.secondsDisplay.text = [NSString
                                           stringWithFormat:@"Seconds: %d", self.seconds];
    self.minutesDisplay.text = [NSString
                                           stringWithFormat:@"Minutes: %d", self.minutes];
}
// (listing continues)
- (void)viewDidLoad
{
    [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
 
    self.secondsTimer = [NSTimer
                             scheduledTimerWithTimeInterval:1.0
                                              target:self
                                            selector:@selector(timerFireMethod:)
                                            userInfo:nil
                                             repeats:YES];
  self.seconds = 0;
  self.minutes = 0;
}
In the class extension (between @interface and @end in the ViewController.m file, we declare two additional properties: seconds and minutes. When we declare properties here, we are making them private to the class.
Next, we synthesize all five properties. Then we define timerFireMethod, which will be called every time the timer fires. This method must have the signature shown, ie:
- (void) methodName:(NSTimer *) timerName
In this method, first we increment the seconds, then check to see if seconds is equal to 60. If it is, we set seconds to zero and increment minutes. We then update both labels using the stringWithFormat class method of NSString.
In viewDidLoad, we initialize the timer using the scheduledTimerWithTimeInterval class method of NSTimer. Because this is a class method, it will give us an autoreleased object. Note that the selector parameter is the timerFireMethod defined earlier. We set both seconds and minutes to zero.
As the final step, we need to wire up the two label properties to their corresponding label objects in the view. Return to theMainStoryboard.storyboard file, right click the File’s Owner object, and wire up the two controls as shown:









Run the application, and you will see the seconds display start counting up each time the timer fires. After a minute has passed, you will see the seconds display revert to 0 and the minutes display change to one: