Friday, June 3, 2011

Key-Value Validation

Along with all the other features of Key-Value Coding, there are methods in the API for validating the properties of an object. These methods are known as Key-Value Validation (KVV). The format for a validation method is -(BOOL)validate<Key>:(id*)error: (NSError**) where “Key” is the name of the property to validate. You must be sure to spell the property name properly, otherwise the validator may not be called properly. When calling a validator, you have two choices. First you can call the validator directly. Second, you can call -(BOOL)validateValue:(id*)forKey:(NSString*)error:(NSError**). The second choice will infer the name of the validator method, which is why it is important to spell the method name properly.

The following gives a simple template of how to implement a validator. This template may be copied directly into Xcode.

- (BOOL)validate<#Key#>:(id *)ioValue error:(NSError **)outError {
        
        if (<#Value is not valid#>) {

                // Try to coerce the value into a valid value.
                // The coerced value must be autoreleased.
                *ioValue = <#Some valid value#>;

                if (<#Value cannot be coerced#>) {
                        
                        if (error != NULL) {
                                
                                // Create an error object.
                                // Merge errors if necessary.
                        }

                        return NO;
                }
        }

        return YES;
}

Implementing validators has several gotchas to watch for. One of the things to notice is the value being passed in for validation is of type id*. This means that you can return a new value by reference. For example, if you want to ensure that a name is unique, you can use the validator to append a number to the name to coerce it to be unique.

Coercing a value has some critical memory management issues. The value passed in for validation must be autoreleased, and a coerced value, if any, must likewise be autoreleased. Furthermore, if you do return a coerced value it must be return a new value rather than modifying the old value, even if the old value is mutable.

When implementing a validator you must never call -set<Key> within the validator. The validator is responsible for validating, not setting.

Primitives cannot be validated since the validators expect an object. However, you may wrap the primitive value in an NSValue or NSNumber object.

Another gotcha to note is that validators are not called automatically. It is up to your discretion when you want your objects to be validated. When calling a validator, there is a general form to follow as shown below:

// Note that the value is autoreleased.
NSString * someName = [[[NSString alloc] initWithFormat”@“Timmy”] autorelease];
NSError * error = nil;

if ([obj validateName:&someName error:&error) {
        
        // The setter is called since the value could have been coerced and to properly retain the value.
        [obj setName:someName];
}
else {
        // Report an error to the user or whatever else you want.
}

Aside from the above template, you could validate the parameters of your Objective-C setters by using NSParameterAssert([obj validateValue:&someValue forKey:@“someKey” error:NULL]). This is good for debugging since asserts can be disabled by defining NS_BLOCK_ASSERTIONS.

Core Data extends the ability of KVV. Although KVC does not automatically call validation methods, Core Data provides three points which validators can be called automatically. These methods are -(BOOL)validateForInsert:(NSError**), -(BOOL)validateForUpdate:(NSError**), and -(BOOL)validateForDelete:(NSError**). These methods are called when an NSManagedObject is inserted into a managed object context, updated, or deleted, respectively. You may override these methods in your subclasses of NSManagedObject to call your validators. Additionally, you may perform inter-property validation here. There may be instances where certain combinations of values are incorrect. For example, in a family tree, it is incorrect to set a female person as someone’s father.

When using the Core Data validation methods, you must be careful to not recursively dirty the managed object context. Dirtying the MOC can be done in numerous ways such as coercing property values on every validation request. If you do recursively dirty the MOC, then you will get a message like this: ‘Failed to process pending changes before save. The context is still dirty after 100 attempts. Typically this recursive dirtying is caused by a bad validation method, -willSave, or notification handler.’ If you face this situation, you will either need to find another way to implement your validator or don’t have your validator called automatically. If you opt to not call your validator automatically, then you will probably want to call your validator anytime you try to set the associated property.

In order to avoid your validators from being called automatically you have a few options. You could avoid calling NSManagedObject’s -validateForX: methods (where ‘X’ is ‘Insert’, ‘Update’, or ‘Delete’) by not calling [super validateForX:&error]. However, this may not be wise since NSManagedObject may do more than call each of the validators. You could instead try having your object reject one or more validation messages from itself. The easiest and best option is to make a validator that is not KVC-compliant. In other words, name the validator method so it doesn’t match with a property name.

When using the Core Data validation methods, you may have multiple errors occur. You have two options to handle this. First, you can return the first error as soon as it is reached. Second, you can merge the errors into a single error with error code NSValidationMultipleErrorsError.

KVV is very useful, especially for Core Data. I’m surprised it isn’t used more frequently. However, Core Data does automatically generate some basic KVV methods from the MOM file. Hopefully, this tutorial will increase the custom usage of KVV.

Friday, April 29, 2011

Delegates and Memory Management

The iOS SDK uses the delegate pattern everywhere. Occasionally, you may want to create your own delegate protocol for some custom object. When doing so, keep in mind the subtleties of memory management. Always use @property (nonatomic, assign) rather than @property (nonatomic, retain) with delegates. It is often habit to use “retain,” but a delegate must use “assign.”

Consider the following scenario. When creating an object, its delegate is often set to “self.” Using retain as the setter policy will cause the object to retain itself. The problem is that objects (usually) don’t ever call release on delegates. Hypothetically, if a delegate is released, it’s likely to be done in -dealloc. Since the object retained itself, -dealloc will never be called. The result is a memory leak. Xcode’s static analyzer will not be able to catch this type of leak. One of the major pitfalls of reference counting is circular dependencies. The only solutions in iOS are to avoid such dependencies or force the cycle to be broken somewhere. The first option is highly preferred.

By using assign, we avoid a circular dependency. However, this doesn’t mean we can’t retain a delegate if needed. It just has to be done manually. For example: [self setDelegate:[aDelegate retain]];. This also means that the release must be done manually. Typically this can be done in -dealloc. Additionally, you may want to include a check for delegate != self. Sending [self release] in -dealloc will result in an infinite loop.

Tuesday, March 15, 2011

BYU CocoaHeads Presentations

Recently, I have added links to my presentations I have given for the BYU CocoaHeads. You can find them in the right-hand column of my blog. Among the presentations, I have include Grand Central Dispatch, Core Data, and Quick Look for iOS. Each of the presentations are shared via iWork.com. If there is interest, I may also add links for my sample projects.

Friday, February 25, 2011

Blog Traffic

Ever since I blogged about raster map overlays for iOS back in August, I have been getting some substantial traffic. In fact, my raster map post shows up as the first three results on Google. If you don’t believe me, do a Google search for “WWDC10 Tilemap.” Regardless of the high traffic, no one has left any comments. My goal is to help answer many iOS developers’ questions. So far I have been using Blogger analytics to gauge what my readers want. Analytics can only do so much though. If a post helped you or didn’t answer what you were looking for, let me know. I would love your feedback.

Monday, February 21, 2011

Quick Look for iOS

Many apps work directly with files. Quick Look is the perfect framework for previewing those files. Right out of the box, it supports all the common file formats. Like many of Apple’s other frameworks, it takes very few lines of code to add. Quick Look has been in Mac OS X for a while now and has recently been made available for iOS in 4.0.

Adding Quick Look is a few easy steps:
  1. Import QuickLook.framework.
  2. Create a QLPreviewItem (or NSURL).
  3. Create a QLPreviewControllerDataSource.
  4. Create a QLPreviewControllerDelegate.
  5. Present a QLPreviewController.
Any item can be previewed. It simply needs to conform to the QLPreviewItem protocol. This protocol only has two methods. The first, previewItemURL, returns the URL to locate the file to preview. The second, previewItemTitle, returns the title to show for the document. If this method is not defined, then the document name will be the title. One important item to note is that NSURL conforms to the QLPreviewItem protocol. You may use NSURLs instead of making a class that conforms to the protocol. Another important gotcha, any URLs returned from previewItemURL must use the file protocol (ex. file://some/file/path.txt). This is easily done with [NSURL fileURLWithPath:someFilePath]. If you don’t use the file scheme, then you will get an error message like this: “UIDocumentInteractionController: invalid scheme (null). Only the file scheme is supported.”

Next, setup a QLPreviewControllerDataSource and QLPreviewControllerDelegate. QLPreviewControllerDataSource needs to know how many QLPreviewItems you want to show (numberOfPreviewItemsInPreviewController:) and which QLPreviewItem is at each index (previewController:previewItemAtIndex:). These are often one line if you already have your documents in an array. Once the delegate and data source are set up, all you need to do is present the view however you like. The most convenient way on iPhone is [self presentModalViewController:previewController animated:YES];. QLPreviewControllerDelegate adds some extra callbacks that may be helpful, but it may be unnecessary depending on your needs.

Quick Look also comes with other features for free. First, it presents the option to open the file in another app that accepts that file format. For example, CSV files can be opened in Numbers and PDFs can be opened in iBooks. Second, files can be printed. If you don’t have a printer to test it on, Apple provides Printer Simulator in the developer tools.

Simple table views works well for managing file previews; however, you may want a more custom UI and more control. UIDocumentInteractionController is the class to use for that. I won’t go into details on document interaction. Session 106 of WWDC 2010 goes into great detail about UIDocumentInteractionController. The sample code is also available in the developer docs.

EDIT:
Since writing this post I have written a subclass of QLPreviewController that includes many conveniences, and have removed the old sample code. If you are using my old Quick Look sample, you should switch over to RBFilePreviewer. You can find it here on Github. You can also find a demo of RBFilePreviewer in my demo repository.

Thursday, August 26, 2010

Raster Map Overlays for iPhone

The release of iOS 4.0 included the ability to add custom image overlays to maps. I recently took advantage of this in FastTrac. Previously, FastTrac was using OpenGL to handle the map. This worked well but required an unreasonable amount of memory. It also wasn’t easy to maintain. Changing to a map overlay fixed both problems. Session 127 of WWDC10 covered briefly how to implement such a map. Some sample code is also available to all developers that makes the process much easier. This session gives a good overview, but is missing some of the fine details. It is my intent to fill in the gaps. I will start with my own overview.

  1. Download and install GDAL (available at gdal.org)
  2. Download the TileMap sample project.
  3. Get the coordinates of your image’s bounding rect.
  4. Generate a .vrt file.
  5. Generate the mercator projected map tiles.
  6. Add the tiles to the sample project.
First, download and install Geospatial Data Abstraction Library (GDAL). This can be found at gdal.org. It can also be installed with MacPorts by using “sudo port install gdal”. Make sure you set your PATH variable properly. I won’t go into any details of how to do this. This shouldn’t be hard.

Next, download the TileMap sample project. This is available to all iOS developers through the WWDC10 website http://developer.apple.com/videos/wwdc/2010/. The sample code can be hard to find. It’s on the iTunes page where you download WWDC10 session videos. Between GDAL and this sample project, you as a developer won’t need to do much to get your map working.

This is where things get interesting. You will need to find the coordinates of the bounding rect of your image to overlay. Google Earth makes this easy. I got this tip from a fellow developer on the Apple developer forums. First, find the area you want to place the image overlay. Next, right click on ‘My Places’ (it’s on the left column). Select Add > Image Overlay. This will open a pop up window. From here you can open your image, change the opacity, and move/resize your image. Make your image transparent enough to see both your image and the underlying map. Once you have adjusted your image to match, click on the ‘Location’ tab. There you will find your latitudes/longitudes. You will need to convert those to a decimal value. A quick Google search will turn up a tool to make that conversion for you.

Now to put GDAL to work. The first part is to generate a .vrt (virtual raster) file. This is probably the hardest part of the process. It’s very easy to make a mistake. You will use gdal_translate to map your corner pixels to the coordinates you just found. The terminal command is as follows:

gdal_translate -of VRT -a_srs EPSG:4326 \
-gcp x1 y1 long1 lat1 \
-gcp x2 y2 long2 lat2 \
-gcp x3 y3 long3 lat3 \
-gcp x4 y4 long4 lat4 \
image.jpg image.vrt

There are a few things to note. First, your map image doesn’t have to be .jpg. Several formats are supported. Also, be very careful with your coordinates. Small errors make big problems. Notice that longitude comes first. I had them backwards and spent two days trying to figure out why it wouldn’t work. As for the x and y values, these are your pixel coordinates. (0,0) is the top left of the image.

If you have done everything correctly, the rest is easy. gdal2tiles.py will take your .vrt file and image overlay and generate mercator projected map tiles. The command is simple - “gdal2tiles.py -p mercator image.vrt.” You only need to give it the .vrt file. The .vrt file keeps a relative path to the image overlay. gdal2tiles.py will generate your map tiles along with other various files. If you don’t want these extra files there are command line options to skip them.

With your new map tiles, you simply need to add them to the TileMap project. First, delete the old tiles in the sample. Make sure they are deleted both in XCode and the source directory. If you have previously run the app, you may need to delete the app from your device/simulator. Next, copy your map tiles into your project. When copying your files, there is a vital gotcha to watch out for. You will need to create folder references instead of groups (see image below). Folder references will appear as a blue folder icon, whereas groups appear as a yellow folder icon. The reason for this is because the code is dependent on not just the files but also the directory structure.



If you named your map tiles directory any other than “Tiles,” you will need to change the code to use your directory instead. Finally, run the app and everything should work. If there is a problem, it likely occurred while generating your .vrt file.

Friday, August 13, 2010

Using a UITextField in a UIAlertView

In an app I have been working on, FastTrac WT, there is a UIAlertView with a UITextField added as a subview. Anytime the alert view was dismissed, the error “wait_fences: failed to receive reply:” would show up. It doesn’t make much sense without knowing what the problem is. That seems to be the irony of error messages. The problem turns out to be that the text field must resign its first responder status before it is released. Knowing this the error message makes more sense. The system couldn’t get a reply from the first responder. The solution to this is to resign the first responder status in the alertView:didDismissWithButtonIndex: method. Using it here makes a smooth animation. The alert view will be dismissed followed by the keyboard. An alternative is to resign the first responder status in alertView:willDismissWithButtonIndex:. The alert view and the keyboard will be dismissed at the same time and the alert view will fade and move downwards with the keyboard. This animation also looks nice and the transition is faster. However, resigning the first responder status in alertView:didDismissWithButtonIndex: does not create a smooth animation. The keyboard is dismissed before the alert view. This creates a sudden jump as the alert view re-centers itself to the viewable area. Either of the first two methods are good candidates for fixing this error. Try both and judge which animation fits best with your app.

Saturday, August 7, 2010

My First Quartz Composition

Quartz composer is often used for making screensavers. So, to learn QC, I decided to make a screensaver of my own. I started with a simple concept, two spheres orbiting around each other. I thought it would be simple anyway. All of the motion is accomplished through the use of LFOs (low-frequency oscillators). At first, I thought I could use three LFOs, one for each axis, to generate the desired motion. I couldn’t find anyway to get this to work. In the end, I found an alternative solution. Each sphere has two LFOs that cause the sphere to orbit in the yz-plane. From there, I used a 3D transformation patch to rotate the two spheres about the y and z axes. This achieved the movement I mentally envisioned. Much of my efforts were trial and error. There is very little documentation available for QC. I hope this to change in time.

Below is a link to my Quartz Composition for anyone interested.

http://dl.dropbox.com/u/2998162/Quartz%20Composer/Orbiting_Spheres.qtz

My First Quartz Composer Patches

While playing around with some of the standard Quartz Composer patches, I discovered the Apple remote patch. I just so happen to have an Apple remote, so I wanted to give it a try. I found it to work well. However, the remote only emitted a quick “true” signal. For what I wanted to do, I needed to store a boolean state. A previous electrical engineering course helped me come up with the solution. I built an RS flip flop patch. An RS flip flop is a simple electrical circuit that stores a single state. It consists of only two NOR gates that are cross-coupled. By setting one wire high (true) the stored bit will go high. When the other wire is set high, the stored bit will go low (false). While both wires are low, the bit will remain unchanged. However, both wires shouldn’t ever both be set high. The result is undefined.

This new patch suited me well. The only problem was that it required using two buttons and those buttons couldn’t be pressed simultaneously. I, of course, could do better. I added a few more components to my patch and changed it to a toggle switch. This permitted one button to toggle between the two states. I later discovered that there is a standard toggle patch, but it can toggle between any two numbers. Mine specifically uses boolean values.

Below are links to download the two patches I developed for those who are interested. Note that since these are patches, not macros, the underlying logic is not available to view.

http://dl.dropbox.com/u/2998162/Quartz%20Composer/RS_Flip_Flop.qtz
http://dl.dropbox.com/u/2998162/Quartz%20Composer/Toggle_Switch.qtz

Tuesday, July 6, 2010

C++ Templates

Today I was working on some standard C++ data structures for a CS class. I wanted to make them generic so that they could be used to hold any primitive or object. C++ offers this flexibility with templates. I found some simple tutorials and went at it. When I was finished, I couldn’t get them to work. I kept getting an undefined reference error during the linking process. What made it the most challenging is that everything was syntactically correct. I had to scour the internet to find the answer. It turns out that with C++ templates, the implementation must be included in the header file. There are a few ways to accomplish this. First, is to use the “export” keyword just before declaring the template. This option isn’t supported by most compilers. I have been using g++ which does not support this feature. Second, the .cpp file can be #included at the end of the .h file. I didn’t prefer that approach. Third, the implementation can be copied to the end of the header file. This is essentially the same as the second option. The fourth option is to simply define each method as soon as it is declared. Any of these four options will essentially merge the implementation and header files directly or indirectly. I took the last option. Once my files were merged, my data structures worked perfectly. Again, it is always the fine details that create the biggest problems.