How UISegmentControl works?


#1

Hi,

I have completed an exercise of adding additional tab bar to HypnoTime project which displays the MapKit. In MKMapKit view, I have added a view of UISegmentedControl with two segments, one for “Satellite” map type view and other for “Standard” map type view. Clicking on respective segments displays simulated location (I am using simulator) on corresponding map type. My code works fine but I am not sure how it works fine.

This is what I am doing in viewDidLoad of my Map Kit Controller

-(void) viewDidLoad
{
[super viewDidLoad];

NSArray *segArray = [NSArray arrayWithObjects:@"Standard",@"Satellite",nil];
seg = [[UISegmentedControl alloc]initWithItems];

locationManager = [[CLLocationManager alloc]init];
[locationManager setDelegate:self];
[MapView setDelegate:self];

[[self view]addSubview:MapView];

[MapView setShowsUserLocation:YES];

[seg setSelectedSegmentIndex:0];
[[self view] addSubview:seg];
[seg addTarget:self action:@selector(touchedType) forControlEvents:UIControlEventValueChanged];

}

-(void) touchedType
{
if([seg selectedSegmentIndex] == 1)
{
[MapView setMapType:MKMapTypeSatellite];
}
else if ([seg selectedSegmentIndex] == 0)
{
[MapView setMapType:MKMapTypeStandard];
}
else
{
[MapView setMapType:MKMapTypeStandard];
}
[locationManager startUpdatingLocation];

}

As far as my understanding most of the events are handled by delegates which have protocols which are implemented. In this case the code which triggers the selector is inside viewDidLoad method and how does a runloop knows to call that line of code with viewDidLoad?

In other words, what exactly happens inside the runloop when a segmented is touched? how does the run loop know to call [seg addTarget:self action:@selector(touchedType) forControlEvents:UIControlEventValueChanged] which itself is not a implemented method.

PS: I like the book very much and I enjoy reading your book

Thank you
Bharath


#2

Delegation is one form of callbacks, but another is target-action pairs. Some objects use delegation, other use target-action pairs.

All subclasses of UIControl (UIButton, UISegmentedControl, etc.) use target-action pairs instead of delegation.

When you send addTarget:action:forControlEvents:, you are registered an object and a message to be sent to that object whenever the segmented control is tapped. So when the run loop picks up the tap on the screen and sends it to the segmented control, the segmented control looks through its list of targets (whatever object you registered in this method) and sends it the message that is the action parameter.