Jun 09

Sorry, this entry is only available in Español.

VN:F [1.9.8_1114]
Rating: 5.0/5 (1 vote cast)
VN:F [1.9.8_1114]
Rating: 0 (from 0 votes)
Tagged with:
Jun 09

VN:F [1.9.8_1114]
Rating: 0.0/5 (0 votes cast)
VN:F [1.9.8_1114]
Rating: +1 (from 1 vote)
Tagged with:
Jun 09

Sorry, this entry is only available in Español.

VN:F [1.9.8_1114]
Rating: 5.0/5 (2 votes cast)
VN:F [1.9.8_1114]
Rating: +1 (from 3 votes)
Tagged with:
Jun 07

Sorry, this entry is only available in Español.

VN:F [1.9.8_1114]
Rating: 0.0/5 (0 votes cast)
VN:F [1.9.8_1114]
Rating: 0 (from 0 votes)
Tagged with:
Jun 05

VN:F [1.9.8_1114]
Rating: 0.0/5 (0 votes cast)
VN:F [1.9.8_1114]
Rating: 0 (from 0 votes)
Tagged with:
Jun 05

When we want to create an application that contains different functionality related with the use of the application, but independent between them, like showing data in different ways or different tasks, we will want to use a Tab Bar in our application.

The Tab Bar will gave us acces to this different views, like independent modules, more over, it helps the user to place himself inside the application, telling him what he is seeing.

Today we will give basic indication to create and set up a Tab Bar in our application. In Xcode we have a template which will create an application with a Tab Bar and two different views, although it is a good start point, when we take a look to the code we can see much of what it’s going on, that because they use Interface Builder to do almost all the setting up. We will show a bit more of code.

Structure

We have an application, inside there is our Tab Bar, we need to tell the Tab Bar which views (UIViewController) it has to show, each view will take care of itself, but we need to setup the property tabBarItem (UITabBarItem) for each view so the Tab Bar can show us the icon and title of it.

Data

The only thing we need is an icon for each view and a title. We can use both at the same time or only one of them, of course, a Tab Bar only with a title doesn’t look right so I will recommend at least to use an icon to represent what is done in that tab. The title is always welcome when the icon is not clear what represents.

The title isn’t more than a normal string that we will give in the code, but the icon is a bit more tricky and although Apple give as some system icons to use, take a look at UITabBarSystemItem, they also tell us how we have to create our own icon.

▪ Use PNG format.
▪ Use only pure white with proper transparency.
▪ Don’t add shadows.
▪ Use anti-aliasing.
▪ Size of 30 x 30 pixels.

Code

To create the Tab Bar and add it to the application use this

- (void)applicationDidFinishLaunching:(UIApplication *)application {
 
tabBarController = [[UITabBarController alloc] init];
 
MyViewController* vc1 = [[MyViewController alloc] init];
 
MyOtherViewController* vc2 = [[MyOtherViewController alloc] init];
 
NSArray* controllers = [NSArray arrayWithObjects:vc1, vc2, nil];
 
tabBarController.viewControllers = controllers;
 
[window addSubview:tabBarController.view];
 
}

We create the Tab Bar, the view controllers we need and put those in an array to tell the Tab Bar those are the one it has to show. We add the Tab Bar view to the window and we are finished.

To set up each of the UITabBarItem of each view we can use the following lines

UIImage* anImage = [UIImage imageNamed:@"MyTabBarIcon.png"];
 
UITabBarItem* theItem = [[UITabBarItem alloc] initWithTitle:@"TabBarItemTitle" 
                                                     image:anImage tag:0];
 
[myViewController setTabBarItem:theItem];

Usually we will put these lines in the view controller itself, on the init method, but might be necesarly to do it in some other place when we are not using our own classes, for example when one of the tabs uses a Navigation Bar, in that case we can put these lines just after creating the Navigation Bar.

VN:F [1.9.8_1114]
Rating: 5.0/5 (1 vote cast)
VN:F [1.9.8_1114]
Rating: -1 (from 1 vote)
Tagged with:
May 29

This week, in an earlier post, we were showing how to use the common flip animation to show a view with the credits of the application. Today we are going to do the same but using the modal views that are implemented in the class UIViewController.

What we did show is usefull when we want to fully control the animation, but this other way will save us a lot of code and if we don’t want to do anything special during the animation will be enought.

We start the same way, with a table view inside a navigation bar, we add the information button to our controller.

- (void)viewDidLoad {
    [super viewDidLoad];
 
    self.title = @"Main menu";
 
    UIButton* infoButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
    [infoButton addTarget:self action:@selector(showAbout:) forControlEvents:UIControlEventTouchUpInside];
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:infoButton];
}

but in this case, our showAbout will be more simple

-(void)showAbout:(id)sender{
	AboutController *a = [[AboutController alloc] init];
	UINavigationController *n = [[UINavigationController alloc] initWithRootViewController:a] ;
	[a release];
 
	[a setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
	[self presentModalViewController:n animated:YES];
}

We are still creating a navigation bar and our credits view, but this time we indicate to our about view how we want the modal animation to be with the sentence [a setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal]; and finally we tell the controller of the actual view to present the new navigation bar.

Here there is a point that can be a little confussing, we are telling one controller how should be the animation, but we present another controller, in fact, if instead of [a setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal]; we use [n setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal]; with the navigation bar controller n, we get the same result, this is becouse the about view is the root view for the navigation bar. But, we can’t do the same in the last sentence or we won’t see the navigation bar that allows us to go back.

Now in the .m of the About controller we leave the viewDidLoad untouched, adding the “Ok” button that once pressed will take us back to our main controller.

- (void)viewDidLoad {
    [super viewDidLoad];
    UIBarButtonItem *btn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemDone target:self action:@selector(close:)];
    self.navigationItem.rightBarButtonItem = btn;
    [btn release];
}
 
but our close will be only one line of code, the one that makes the modal view to go away.
 
-(void)close:(id)sender{
       [self dismissModalViewControllerAnimated:YES];
}

Realice that this way we don’t need anymore to keep truck of the main controller to be able to go back to it, this is becouse using modal views we still have it in the view hierarchy.

VN:F [1.9.8_1114]
Rating: 5.0/5 (1 vote cast)
VN:F [1.9.8_1114]
Rating: +1 (from 1 vote)
Tagged with:
May 23

VN:F [1.9.8_1114]
Rating: 5.0/5 (1 vote cast)
VN:F [1.9.8_1114]
Rating: +1 (from 1 vote)
Tagged with:
May 23

Today we will see a very simple example of how to use and for what it’s use the NSKeyValueOnserving protocol (KVO), as in other posts, what is explained here can be used in many other cases.

This protocol allows us to detect changes in property values of objects and works as follows:

  • We have an object X of which we want to know when an attribute is modified
  • We have and object Y which will perform an action when X changes its attribute
  • The previous protocol allows the object Y to be notified of changes, for the attribute we specify, of the object X.

To achieve this we only need to tell X that Y wants to be notified of such changes using the method addObserver:forKeyPath:options:context: defined in the protocol and perform the appropriate actions using the method observeValueForKeyPath:ofObject:change:context: on the object Y, since this is the message that is sent when the attribute changes its value.

How example we use this method to detect when a user selects or deselects an annotation (MKAnnotation) on a map (MKMapView). First I will show how to set up the project as a tutorial and below how to used exactly the KVO, if you already have your project, go directly to the second section.

Preparation

First create a new project using the Xcode template based on a view. We add to the project the MapKit Framework to use the map and annotations.
Then modify the view controller to add an IBOutlet as reference the map that will be added later. We will have to import the Framework.

#import <UIKit/UIKit.h>;
#import <MapKit/MapKit.h>;
 
@interface MapKVOViewController : UIViewController  {
 
	IBOutlet MKMapView *theMapView;
}
 
@end

We open the file MapKVOViewController.xib with Interface Builder and add a MKMapView to assign the previously created IBoutlet, also indicate that the delegate of the map will be the controller.
For annotations on the map we need to add another class to our project, in Xcode add a new class from a NSObject, we import here also the MapKit Framework. This class has to comply with the protocol so modify the MKAnnotation.h to do so.

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
 
@interface MapAnnotation : NSObject {
	NSString *title;
	NSString *subtitle;
	CLLocationCoordinate2D coordinate;
}
 
@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
 
// Title and subtitle for use by selection UI.
- (NSString *)title;
- (NSString *)subtitle;
 
@end

How this class is only for a test, initialize variables at constant values, modify the .m to look like this.

@implementation MapAnnotation
 
@synthesize coordinate;
 
- (id)init {
	[super init];
 
	coordinate.latitude = 25;
	coordinate.longitude = 25;
	title = [NSString stringWithFormat:@"A Testing annotation"];
	[title retain];
	subtitle = [NSString stringWithFormat:@"selecting detection"];
	[subtitle retain];
	return self;
}
 
- (NSString *)title {
	return title;
}
 
- (NSString *)subtitle{
	return subtitle;
}
 
- (void)dealloc{
	[title release];
	[subtitle release];
	[super dealloc];
}
 
@end

To end the project preparation we only need to add an annotation on the map, for example use the viewDidLoad to do so. Remember you have to import your new class to use annotations on the map (here MapAnnotation).

- (void)viewDidLoad {
    [super viewDidLoad];
	MapAnnotation *newAnnotation = [[MapAnnotation alloc] init];
	[theMapView addAnnotation:newAnnotation];
}

Using KVO

In our example, object X is the view of the annotation, the pin you see on the map, in one hand we have the annotation itself and in another the view that represents it on the map, as the action of selection is made on the map, is the view of the annotation which has an attribute called selected, which is what we will want to monitor.

The object Y, will be our MapKVOViewController, which is responsible for adding annotations to the map.

First step, tell the object X we want to observe the selected attribute, if we want to do this with all the entries in the map, a good place is the method MapView:didAddAnnotationViews: in MKMapViewDelegate protocol, add this method to our controller and modify it to be like this

- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
	for (MKAnnotationView *anAnnotationView in views) {
		[anAnnotationView setCanShowCallout:YES];
		[anAnnotationView addObserver:self
						 forKeyPath:@"selected"
					              options:NSKeyValueObservingOptionNew
						      context:ANNOTATION_SELECTED_DESELECTED];
	}
}

Please note that this will be done for each annotation, so if there are different types of annotations, you have to differentiate between which one you want to be notified and which ones not.

The method that interests us is addObserver:forKeyPath:options:context:, to the latter we will indicate who will be the observer, self, which attribute to observe, selected, with which options, NSKeyValueObservingOptionNew indicates that we want the new value, and a context that is used to give us more information, such as what we are seeing, here you can use nil if you observe only one thing, if you have to distinguished it is useful to use constants for each case, here we use

static NSString* const ANNOTATION_SELECTED_DESELECTED = @"mapAnnotationSelectedOrDeselected";

defined at the beginning of our .m

Finally, in order to take any action, once notified of the change, we need to overwrite the method observeValueForKeyPath:ofObject:change:context:

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {
 
    NSString *action = (NSString *)context;
	if ([action isEqualToString:ANNOTATION_SELECTED_DESELECTED]) {
		BOOL annotationSelected = [[change valueForKey:@"new"] boolValue];
		if (annotationSelected) {
			NSLog(@"Annotation was selected, do whatever required");
                        // Accions when annotation selected
		}else {
			NSLog(@"Annotation was deselected, do what you must");
                        // Accions when annotation deselected
		}
	}
}

Add the code to perform the action once we know if the annotation has been selected or deselected, for example, play a sound.

VN:F [1.9.8_1114]
Rating: 4.8/5 (5 votes cast)
VN:F [1.9.8_1114]
Rating: +3 (from 3 votes)
Tagged with:
May 16

Today I will explain how we can play a sound when a button is pressed, in fact, what I will explain can be used in many other situations and not only for buttons, because what I will do is to create a SystemSoundID which is used, among another things, to play short (30 seconds or less) sounds. But as an example, I will use a button.

To be able to reproduce sounds we will need to add the AudioToolbox Framework to our project.

Imagine we have a UIViewController and the view it is controlling, add a UIButton to the view using Interface Builder or do it programmatically, as you like most. If you haven’t added yet the Framework to the project, do it now, once you have done it we have to import it to our view controller.

In the header file (.h) of our controller add a variable of type SystemSoundID and a method which will be called when the button is pressed.

#import <UIKit/UIKit.h>
#import <AudioToolbox/AudioToolbox.h>
 
@interface testKeyboardViewController : UIViewController <UITextFieldDelegate> {
 
	SystemSoundID buttonSoundID;
}
- (IBAction)buttonPressed;
 
@end

Now we need a sound file, with the sound we want, for example call it ButtonSound.caf, now, and in the viewDidLoad of our controller add the following lines to create the reference to our sound.

- (void)viewDidLoad {
    [super viewDidLoad];
	NSString *path = [[NSBundle mainBundle] pathForResource:@"ButtonSound" ofType:@"caf"];
	AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:path], &buttonSoundID);	
}

As you can see in the code, we need the path for our file, if you have add the file to your group Resources in Xcode, the code above should work for you. Take a look at NSBundle if that doesn’t work to look for another method that allows you to find the path to the file.

With this we have the reference to the sound, now we only need to play it when we need, in this case, we want to play it when the button is pressed. Add to the method that is called when the button is pressed, the following lines

- (IBAction)buttonPressed {	
	AudioServicesPlaySystemSound(buttonSoundID);
}

Now you should be hearing the sound when you press the button.

When you don’t need anymore the sound, you can use the following function to remove the reference, for example in the viewDidUnload of our controller.

- (void)viewDidUnload {
	AudioServicesDisposeSystemSoundID(buttonSoundID);
}

I hope that this post is useful and now you are able to add all kind of short sounds to your application to give it a bit more of life.

VN:F [1.9.8_1114]
Rating: 5.0/5 (2 votes cast)
VN:F [1.9.8_1114]
Rating: +2 (from 2 votes)
Tagged with:
preload preload preload