Categories
english

UILocalizedIndexedCollation shows empty sections

A client wanted his app to show a list of contacts. He wanted each contacts whose name began with the same letter to be in the same section of a table view. However, he was not satisfied with the first version I coded, because empty sections would show. For instance, if there was no contact whose name began with a B, there would be an empty B section.

So, I went back to my code, and I came up with this result:

Capture d’écran 2013-11-18 à 11.29.20

My code only handles letters from A to Z, with no diacritics.  I was not aware of the UILocalizedIndexedCollation class at the time I programmed the first version, and when I discovered it, it seemed to present an interesting feature: it can handle other locales, in particular, Arabic or Asian alphabets.

For the second version, I thought it would be better using it, but I really wasted two hours:

Capture d’écran 2013-11-18 à 11.04.49

UILocalizedIndexedCollation uses a fixed list of indexes, so empty sessions are shown. Just like the first version I came up with. I thought Apple would have had produced a much better implementation.

By the way, Apple’s documentation is way too spare. NSHipster provides us with a good starting point to understand how to use this class.

Categories
english

Reading Barcodes on iOS 7

iOS 7 introduced APIs to read bar codes using the camera. I could have easily overlooked it without this excellent post from doubleencore.

NSHipster provided sample code, but it missed some details to work. Here is a sample which does.

Sample code

@import AVFoundation;

@interface CEViewController () <AVCaptureMetadataOutputObjectsDelegate>

@property (strong) AVCaptureSession *captureSession;

@end

@implementation CEViewController

- (void)viewDidLoad
{
	[super viewDidLoad];

	self.captureSession = [[AVCaptureSession alloc] init];
	AVCaptureDevice *videoCaptureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
	NSError *error = nil;
	AVCaptureDeviceInput *videoInput = [AVCaptureDeviceInput deviceInputWithDevice:videoCaptureDevice error:&error];
	if(videoInput)
		[self.captureSession addInput:videoInput];
	else
		NSLog(@"Error: %@", error);

	AVCaptureMetadataOutput *metadataOutput = [[AVCaptureMetadataOutput alloc] init];
	[self.captureSession addOutput:metadataOutput];
	[metadataOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
	[metadataOutput setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode, AVMetadataObjectTypeEAN13Code]];

	AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];
	previewLayer.frame = self.view.layer.bounds;
	[self.view.layer addSublayer:previewLayer];

	[self.captureSession startRunning];
}

#pragma mark AVCaptureMetadataOutputObjectsDelegate

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
	for(AVMetadataObject *metadataObject in metadataObjects)
	{
		AVMetadataMachineReadableCodeObject *readableObject = (AVMetadataMachineReadableCodeObject *)metadataObject;
		if([metadataObject.type isEqualToString:AVMetadataObjectTypeQRCode])
		{
			NSLog(@"QR Code = %@", readableObject.stringValue);
		}
		else if ([metadataObject.type isEqualToString:AVMetadataObjectTypeEAN13Code])
		{
			NSLog(@"EAN 13 = %@", readableObject.stringValue);
		}
	}
}

@end

Pitfalls

The issue I had with NSHipster’s sample code is the delegate method was not called at all. I quickly understood this was because the AVCaptureMetadataOutput must be configured to tell which metadata to recognise.

But, and this was not obvious to me, -[AVCaptureMetadataOuput setMetadataObjectTypes:] must be called after -[AVCaptureSession addOutput:]. Otherwise, the following message shows in the console:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[AVCaptureMetadataOutput setMetadataObjectTypes:] - unsupported type found.  Use -availableMetadataObjectTypes.'

I did try to look at the output of -availableMetadataObjectTypes, and it returns an empty array.

Therefore, -addOuput: must be called before setMetadataObjectTypes. In retrospect, it makes sense: the output object must know it is linked to a video session to know which metadata it may provide.

Categories
english

Add git tracking to an existing Xcode project

When creating a new project on Xcode 4, you are given the opportunity to activate git versioning  for this project.

You might have not checked this option in the first place and wish to add git tracking to the project later. Here is how to do it:

1) Open a Terminal window and go to the Project’s directory (the one that contains the .xcodeproj).

2) Type

  • git init

This adds git version control to the directory and creates a .git repository. The project is now under version control.

3) Some files which should not be versioned. git uses a .gitignore text file for that purpose which contains a list of files (you may use wildcard characters).

To edit .gitignore, you may create an empty file:

touch .gitignore

Then open it in your favourite text editor.

I think it should at least contain:

.DS_Store

You may also add:

MyProject.xcworkspace/xcuserdata/

Because you do not want information specific to a user (e.g. the list of breakpoints) to be pushed to a remote git repository.

4) To track project files (in other words, add them to the “staging area”), type

git add .

5) Finally, commit these files

git commit -m "Initial commit"