Improved Validation for Universal Windows Apps

I wrote a couple weeks back on my attempt to re-write the ValidatableBase class I wrote for Universal Windows Apps. The original idea was great, but in practice it turned out to be a headache. Writing a method per property (in some cases more than one!) really bloated the code and made it difficult to read. So I set out to tackle this in a different way.

To demonstrate the improvements, I want to first revisit how the previous version worked. The following is a simple User model that would perform validation on a user name and password with the old ValidatableBase.

public class User : ValidatableBase
{
    private string email = string.Empty;

    private string password = string.Empty;

    public User()
    {
        this.RegisterProperty("Email", "Password");
    }

    public string Email
    {
        get 
        {
            return this.email;
        }
        set 
        { 
            this.email = value;
            this.OnPropertyChanged("Email");
        }
    }

    public string Password
    {
        get 
        { 
            return this.password; 
        }
        set 
        { 
            this.password = value;
            this.OnPropertyChanged("Password");
        }
    }

    public override void Validate()
    {
        this.ValidateProperty(this.ValidateEmailIsNotEmpty, "Invalid Email Address.", "Email");
        this.ValidateProperty(this.ValidateEmailIsFormatted, "Email Address is not in the correct format.", "Email");
        this.ValidateProperty(this.ValidatePasswordIsNotEmpty, "Password can not be empty.", "Password");
        this.ValidateProperty(this.ValidatePasswordIsToShort, "Password must be greater than 8 characters.", "Password");
        this.ValidateProperty(this.ValidateIfPasswordContainsSpaces, "Password must not contain spaces.", "Password");

        base.Validate();
    }

    private IValidationMessage ValidateEmailIsNotEmpty(string failureMessage)
    {
        if (string.IsNullOrEmpty(this.Email))
        {
            return new ValidationErrorMessage(failureMessage);
        }

        return null;
    }

    private IValidationMessage ValidateEmailIsFormatted(string failureMessage)
    {
        string[] addressParts = this.Email.Split('@');

        if (addressParts.Length < 2)
        {
            var msg = new ValidationErrorMessage(failureMessage);
            return msg;
        }

        string[] domainPiece = addressParts.LastOrDefault().Split('.');
        if (domainPiece.Length < 2)
        {
            var msg = new ValidationErrorMessage(failureMessage);
            return msg;
        }

        return null;
    }

    private IValidationMessage ValidatePasswordIsNotEmpty(string failureMessage)
    {
        if (string.IsNullOrEmpty(this.Password))
        {
            return new ValidationErrorMessage(failureMessage);
        }

        return null;
    }

    private IValidationMessage ValidatePasswordIsToShort(string failureMessage)
    {
        if (this.Password.Length < 8)
        {
            return new ValidationErrorMessage(failureMessage);
        }

        return null;
    }

    private IValidationMessage ValidateIfPasswordContainsSpaces(string failureMessage)
    {
        if (this.Password.Contains(' '))
        {
            return new ValidationErrorMessage(failureMessage);
        }

        return null;
    }
}

As you can see, I had to write a single method for each different type of validation I wanted to perform. In this case, as shown in the Validate() method, I have 5 different methods to validate 2 properties. Imaging a more complex model? This quickly turned in to a messy model.

The solution

I heavily modified the ValidatableBase class and its interface initially, but ultimately ended up being able to keep it mostly unchanged and just add on to it. The validation via method delegates certainly has a place, and I didn't want to loose that. The goal this time-around however was to make delegates the last choice instead of the first choice.

The class now supports attribute based validation, very much like Microsoft's DataAnnotation. Since Data Annotations are not supported in Universal Apps, I set out to build my own version, which actually ended up being a bit different with some nifty features.

Let's take the User class, and re-write it to use the new validation scheme.

public class User : ValidatableBase
{

    private string email = string.Empty;

    private string password = string.Empty;

    [ValidateValueIsNotNull(FailureMessage = "E-Mail can not be left blank.", ValidationMessageType = typeof(ErrorMessage))]
    [ValidateWithCustomHandler(DelegateName = "ValidateEmailFormat")]
    public string Email
    {
        get
        {
            return this.email;
        }

        set
        {
            this.email = value;
            this.OnPropertyChanged("Email");
        }
    }

    [ValidateStringIsGreaterThan(GreaterThanValue = 6, FailureMessage = "Password must be greater than 6 characters.", ValidationMessageType = typeof(ErrorMessage))]
    [ValidateStringIsLessThan(LessThanValue = 20, FailureMessage = "Password must be less than 20 characters.", ValidationMessageType = typeof(ErrorMessage))]
    public string Password
    {
        get
        {
            return this.password;
        }

        set
        {
            this.password = value;
            this.OnPropertyChanged("Password");
        }
    }

    [ValidationCustomHandlerDelegate(DelegateName = "ValidateEmailFormat")]
    private bool ValidateEmailIsFormatted(IMessage failureMessage)
    {
        string[] addressParts = this.Email.Split('@');

        if (addressParts.Length < 2)
        {
            return false;
        }

        string[] domainPiece = addressParts.LastOrDefault().Split('.');
        if (domainPiece.Length < 2)
        {
            return false;
        }

        return true;
    }
}

Now we are down to just a single method that performs validation. The Email property has two validation attributes, a ValidateValueIsNotNull and a ValidateWithCustomHandler attribute. The value is not null attribute is self explanatory, it just ensures the value isn't null and progresses. The ValidateWithCustomHandler allows you to specify a delegate name that you want th validator to use when performing validation. You'll notice that there no longer needs to be a method within the model called Validate() as this is part of the base class and handles invoking all of the validation attributes, and their custom handlers if they exist.

We use validation on the Password property as well, by ensuring it meets the minimum and maximum length requirements we define.

A really cool feature of this, is the ability to perform validation based on other property values. For instance, let's assume that validation for the Password can only fire when the Email property has a value set. If that is the case, then we just modify the Password attributes to specify that the Email property must be valid in order for our validation to fire.

    [ValidateStringIsGreaterThan(GreaterThanValue = 6, ValidateIfMemberValueIsValid = "Email",  FailureMessage = "Password must be greater than 6 characters.", ValidationMessageType = typeof(ErrorMessage))]
    [ValidateStringIsLessThan(LessThanValue = 20, ValidateIfMemberValueIsValid = "Email", FailureMessage = "Password must be less than 20 characters.", ValidationMessageType = typeof(ErrorMessage))]
    public string Password
    {
        get
        {
            return this.password;
        }

        set
        {
            this.password = value;
            this.OnPropertyChanged("Password");
        }
    }

As you can see here, by setting the ValidateIfMemberValueIsValid, the validation will only get fired if the Email property is not empty or null. What if we wanted to have validation fire only if the Email property was empty? We can do that be prepending an exclamation mark in from of the string representation of the Email property.

ValidateIfMemberValueIsValid = "!Email"

This works with boolean values by checking if it is true or false, floats, doubles, ints, longs, shorts and decimals by checking if they are zero or not along with empty strings and null objects.

Finally, the method delegate feature still exists, and can be used by external objects to enforce additional validation on the model. Let's use a view model as an example. Assume the view model has a PasswordConfirmation property, that must equal the users Password before user creation validation is considered acceptable. We can do the following in our view model, within a CreateUser method or an ICommand.Execute method.

    public void Execute(object parameter)
    {
        // Perform validation on the user's built in validation.
        this.AppUser.ValidateAll();

        // Piggy-back on top of the user default validation with an additional level of validation in our view model.
        // We ensure the password and password confirmation matches.
        this.AppUser.ValidateProperty(
            () => PasswordConfirmation.Equals(this.AppUser.Password),
            new ErrorMessage("Passwords do not match!"),
                "Password");

        // Check if there are any errors.
        if (this.AppUser.HasValidationMessages<ErrorMessage data-preserve-html-node="true">())
        {
            return;
        }

        // Do stuff.
        return;
    }

Here, we fire the user validation off, then we piggy-back on it by creating our own validation via an anonymous method, and assigning it to the "Password" property of the user. If validation fails, it will be added to the Users validation message collection. We then check if the user has any validation error messages. If they do, we abort the user creation.

The API still has a bit of tightening up to do before I can upload it, but it should be ready before the end of the week on GitHub. It's taken a bit of time due to ensuring that what I end up here can run properly. I managed to wire it up in to the latest build of the Mud Designer engine tonight which will really help with development.

Create objects dynamically in C#

Today I ran into a new class that I had yet to see in the .NET Framework. The ExpandoObject within the System.Dynamic namespace. The class is used as a dynamic object, which I have used in the past.

With a dynamic object, you can do:

static void Main(string[] args)
{
    dynamic car = new Object();
    car.Make = "G35";
    car.Year = 2014;
}

And it would compile, even though the car variable is of a Object type, therefore the Make and Year properties don't exist. This is nice in some cases, but not something that I have really had a large use for as of yet.

Today I learned that you can essentially construct a Type at runtime using the dynamic type. In the example above, the properties that I assigned to the dynamic car object were hard-coded at compile time and not runtime, so they can be used without issue. The .NET Framework ships with an object callec ExpandoObject that allows you to attach properties and methods to a dynamic object during runtime, without recompiling the source.

static void Main(string[] args)
{
    dynamic car = new ExpandoObject();
    car.Make = "G35";
    car.Year = 2014;
}

So what gives? The code above looks the exact same right? With the exception that the dynamic type changed from a object to a ExpandoObject. The ExpandoObject is typed to a dynamic, allowing you to continue to assign properties to the object at compile time. In the event that you want to assign a property to the object at runtime, you invoke the ExpandoObject's IDictionary.Add method.

static void Main(string[] args)
{
    dynamic car = new ExpandoObject();
    car.Make = "G35";
    car.Year = 2014;

    ((IDictionary<string, object>)car).Add("TopSpeed", 180);
}

That essentially adds a new property called "TopSpeed" to the car object and assigns it a value of 180. This can be extremely useful in the event that you are pulling data from an external source such as a local file or a database, and want to construct an object based off of the information loaded. You could in essence do something like this:

dynamic databaseStuff = new ExpandoObject();
foreach (DataColumn column in table.Columns)
{
    ((IDictionary<string, object>)databaseStuff).Add(column.ColumnName, null);
}

Now I have a object who's properties match that of my database Table schema. You can of course assign the value of the column row to the property you just created rather than assigning it to null like I did in my example.

Now, the ((IDictionary<string, object>)someVariable).Add(); method is a real eye sore. You could make that easier by wrapping it.

public class DynamicObject
{
    public dynamic Instance = new ExpandoObject();

    public void AddProperty(string name, object value)
    {
        ((IDictionary<string, object>)this.Instance).Add(name, value);
    }

    public dynamic GetProperty(string name)
    {
        if (((IDictionary<string, object>)this.Instance).ContainsKey(name))
            return ((IDictionary<string, object>)this.Instance)[name];
        else
            return null;
    }
}

With the above code, we can easily add properties to an object at runtime just by invoking the AddProperty method, and retreive the value of the properties either by accessing the dynamic object itself (Instance) or by invoking the GetProperty method. The following code will output the property values to the console. Note that while I am creating the TopSpeed property using our AddProperty method, I am not forced to access it via the GetProperty method, but I can also access it directly from the Instance property since it is a dynamic Type.

    static void Main(string[] args)
    {
        var car = new DynamicObject();
        car.Instance.Make = "G35";
        car.Instance.Year = 2014;

        car.AddProperty("TopSpeed", 180);

        int topSpeed = car.GetProperty("TopSpeed");

        string msg = string.Format("The Top Speed of a {0} is {1}", car.Instance.Make, car.Instance.TopSpeed);
        Console.WriteLine(msg);

        Console.ReadKey();
    }

There are a whole lot of other cool things you could do with this, such as constructing a method at runtime. The above example has been modified to build a method for use at runtime with the car object and a road object. Methods could be obtained by loading code at runtime and assigning methods to a dynamic object as needed. Really useful for application plugins or anything that might need this approach.

We'll start with our wrapper object, by adding a AddMethod method.

    public void AddMethod(Action methodBody, string methodName)
    {
        this.AddProperty(methodName, methodBody);
    }

Since a Action is nothing more than a method delegate, we can attach it as a property and invoke it later. This lets us pass a method into our object and store it as a property. Next, we create a method, add it and invoke it.

    static void Main(string[] args)
    {
        var car = new DynamicObject();
        // Create properties
        car.Instance.Make = "G35";
        car.Instance.Year = 2014;
        car.Instance.CurrentSpeed = 45;

        // Add property in a more dynamic manor.
        car.AddProperty("TopSpeed", 180);
        // Get the property using our wrapper for a more dynamic manor.
        int topSpeed = car.GetProperty("TopSpeed");

        // Access a property we added via our method, directly.
        car.Instance.TopSpeed = 200;

        // Create a Road object.
        var road = new DynamicObject();
        road.AddProperty("SpeedLimit", 65);

        // Add a custom method.
        car.AddMethod(() => { car.Instance.CurrentSpeed = road.Instance.SpeedLimit; }, "MatchSpeedLimit");

        // Invoke our method. Sets the CurrentSpeed (45) to SpeedLimit (65)
        car.Instance.MatchSpeedLimit();
        Console.WriteLine("Current car speed is {0}", car.Instance.CurrentSpeed);

        Console.ReadKey();
    }

That's all there is to it! Of course, you could do all of this directly without the wrapper by using the IDictionary object everywhere, but that's a bit of a pain. I prefer this approach for myself.

The following is the entire source file in full for use.

using System;
using System.Collections.Generic;
using System.Dynamic;

namespace DynamicObjects
{
    public class DynamicObject
    {
        public dynamic Instance = new ExpandoObject();

        public void AddProperty(string name, object value)
        {
            ((IDictionary<string, object>)this.Instance).Add(name, value);
        }

        public dynamic GetProperty(string name)
        {
            if (((IDictionary<string, object>)this.Instance).ContainsKey(name))
                return ((IDictionary<string, object>)this.Instance)[name];
            else
                return null;
        }

        public void AddMethod(Action methodBody, string methodName)
        {
            this.AddProperty(methodName, methodBody);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var car = new DynamicObject();
            // Create properties
            car.Instance.Make = "G35";
            car.Instance.Year = 2014;
            car.Instance.CurrentSpeed = 45;

            // Add property in a more dynamic manor.
            car.AddProperty("TopSpeed", 180);
            // Get the property using our wrapper for a more dynamic manor.
            int topSpeed = car.GetProperty("TopSpeed");

            // Access a property we added via our method, directly.
            car.Instance.TopSpeed = 200;

            // Create a Road object.
            var road = new DynamicObject();
            road.AddProperty("SpeedLimit", 65);

            // Add a custom method.
            car.AddMethod(() => { car.Instance.CurrentSpeed = road.Instance.SpeedLimit; }, "MatchSpeedLimit");

            // Invoke our method. Sets the CurrentSpeed (45) to SpeedLimit (65)
            car.Instance.MatchSpeedLimit();
            Console.WriteLine("Current car speed is {0}", car.Instance.CurrentSpeed);

            Console.ReadKey();
        }
    }
}

Instance run-time defined objects dynamically in Objective-C

In C# I wrote a nice little feature that allowed users to write custom C# script files that the application's runtime would compile, load and instance during the applications life-cycle. The app even supported modifying or creating new scripts and compiling them, loading and instancing without ever re-starting the application. I did most of this with reflection so it wasn't to hard.

I started thinking about it tonight and thought that it would be neat to implement something like that in Objective-C, just for fun. The goal was to accept a user defined class name, check if it exists and instance it. Once it is instanced, allow for invoking the classes methods. All at runtime.

Another nice thing we could do, is check if the object implements a specific protocol. If you are building game development tools, or wanting to provide an abstract way of instancing objects in your app without having to hard-code all of the different types, you could easily do so. You create a new instance based on what object name is provided (such as a object called "Hydrant" and your user selecting a Hydrant in the game, thus requesting an object called Hydrant), then you verify if it implements one or more protocols such as "Interactable" or "destructible" and then invoke the methods or access the properties that are guaranteed to exist.

The Factory

The Factory will be the heart and soul of this example. It's responsibility is to create the object instances, invoke their methods or access their properties for your models and/or view controllers. Assuming you have created a fresh project, we will create new Objective-C class called Factory, which inherits from NSObject. We will provide it with the following public methods in the header.

@interface OFactory : NSObject

- (id)createObject:(NSString *)objectName;
- (void)invokeMethod:(NSString *)methodName onObject:(id)object;

@end

The first method we will implement is the createObject: method. This method will take a NSString object that hopefully has a valid object name. This could be done by creating another method called objectIsValidForCreation:(NSString *)string; that verifies that the object passed as a string has a matching class with the same name. We can look at that in another post. For now, we assume that the user always passes a string with a objectName that matches an existing class. If not, nil will be returned.

Next we have the invokeMethod: onObject: method which will take a string containing a method name and invoke it on the object supplied as an argument.

Let's implement the createObject: method first in our implememtation file.

#import "Factory.h"
@import ObjectiveC.runtime;

@implementation Factory

- (id)createObject:(NSString *)objectName {
    id objectInstance = [[NSClassFromString(objectName) alloc] init];
    return objectInstance;
}

@end

This is a pretty easy method to implement. We just need to make sure that the ObjectiveC.runtime api is imported. Using the Objective-C runtime we can instance a class by providing it with a NSString object containing the name of the class. The NSClassFromString method does just that. It returns a class, which we then alloc and init. You now can invoke this method like such:

Factory *factory = [[Factory alloc] init];
id testObject = [factory createObject:@"NSDate"];

if ([testObject isKindOfClass:[NSDate class]]) {
    NSLog(@"%@", [testObject description]);
}

When you run that code, you should see the current date printed to the debugger. Pretty cool right?

Next, let's build a simple class called "User" that implements two properties and a initializer. The header looks like this.

@interface User : NSObject
@property (strong, nonatomic) NSString *name;
@property (nonatomic) int age;

- (id)initWithName:(NSString *)name andAge:(int)age;
@end

The method we will implement will be done in the .m implementation file. Let's implement the description method, which is a method belonging to the super class NSObject

@implementation OFTestObject

- (id)init {
    self = [super init];
    if (self) {
        self.name = @"Billy";
        self.age = 33;
    }
    return self;
}

- (id)initWithName:(NSString *)name andAge:(int)age {
    self = [super init];
    if (self) {
        self.name = name;
        self.age = age;
    }
    return self;
}

- (NSString *)description {
    return [NSString stringWithFormat:@"The user name is %@ and is %d years old", self.name, self.age];
}
@end

Done. We can use this class to test our next feature, method invoking.

I actually already showed how to do this in my Monitoring Property Changes at Runtime post. There are several changes that I made however to make the implementation more durable in a dynamic environment. This time around it provides support for a unlimited number of arguments that can be passed into the invokeMethod and it returns the same return value that the method you invoked returned.

- (id)invokeMethod:(NSString *)methodName onObject:(id)object withParameter:(id)param, ... {
    if (methodName || object) {
        if ([object respondsToSelector:NSSelectorFromString(methodName)]) {
            // Invoke the getter of the property
            NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[[object class] instanceMethodSignatureForSelector:NSSelectorFromString(methodName)]];
            if (invocation) {
                invocation.target = object;
                invocation.selector = NSSelectorFromString(methodName);

                // Pass the name of the property as the valueForKey: key argument.
                @try {
                    if (param) {
                        // first value is not part of the argument list, so it has to be handled separately.
                        [invocation setArgument:&param atIndex:2];

                        id eachObject;
                        va_list argumentList;

                        va_start(argumentList, param);
                        int index = 3; // Next in the index.
                        while ((eachObject = va_arg(argumentList, id))) {
                            [invocation setArgument:&eachObject atIndex:index];
                            index++;
                        }
                        va_end(argumentList);
                    }

                    id returnValue;
                    [invocation invoke];
                    [invocation getReturnValue:&returnValue];
                    return returnValue;
                }
                @catch (NSException *exception) {
                    NSLog(@"Failed to invoke the method");
                }
            } else {
                NSLog(@"ERROR: Failed to locate the method for @selector:%@", methodName);
            }
        }
    }
    return NULL;
}

Now if you want to test out this code, you can try it with the following code in a view controller some place.

self.factory = [[Factory alloc] init];
id testObject = [self.factory createObject:@"User"];

// user property can be a id, since the class is determined at run time.
self.user = [self.factory invokeMethod:@"description" onObject:testObject withParameter:nil];

The above code will instance a new factory, ask the factory to instance a User class and then invoke that User class method description. If the user class does not exist, nil is returned. In the event that the method does not exist or fails, nil is returned as well. The factory does all of the retrospection required to ensure the app does not crash.

Monitoring Property Changes On Objects

Today we go over the various ways that you can monitor properties in your classes for changes, and act on those changes. There are three ways that I am going to demonstrate.

  • Manually - Notify a specific class of changes to specific properties manually.
  • Monitoring statically via KVO - Notifies specific classes of changes made to specific properties automatically.
  • Monitoring dynamically via KVO - Notifies any class of changes made to any property, without having to specify which properties by using the Objective-C runtime library. Yay C functions!

Object monitoring

There are instancs were monitoring property changes to an object can be very useful. You might want to monitor changes to various object properties that might need to get wrote to a local database, propogate back to a server, or perhaps you want to immediately write out property changes to file. Monitoring an object for changes allows you to save the changes as they happen, and prevent invoking any save methods or update methods when nothing has changed.

In order to monitor the properties of an object, you need to determine what the extent of the monitoring needs to be. Are you only going to monitor a handful of properties in a single object? Perhaps you have several dozen properties spread out over multiple objects, or you might want to make something flexible so you can re-use it on other projects if needed.

I should note that two of the three approachs I'm going to discuss use KVO. If you have a lot of objects and need your app to be fairly performant, this might not be the best solution for you. While KVO is very quick, it does come with some additional overhead. The performance hit is negligible on standard apps, or even hard-core apps with very few KVO's; a large quantity (we're talking hundreds) of KVO setups can significantly affect your performance though. A general rule of thumb is not to use these in any kind of app/game loop and keep the code that they perform fairly short. It should be used primarily as a callback, letting something know that things have changed.

Manually

Manually is the most straight forward approach. You create a property, preferably a BOOL, and set it to YES when a property is changed. In the BOOL properties setter, you would invoke what ever method that is neccessary to commit or process those changes.

It's best to demonstrate with an exampe, so let's say we have a class we are building called PlayerSettings and this class is responsible for saving the players settings in a game. When a setting is changed, we want to automatically save the settings to what ever format you happen to choose. The format isn't important, getting to the save code automatically without manually invoking a [player saveSettings]; method all the time is.

Lets start with the header API, which just exposes the public properties for the player settings class.

#import <Foundation/Foundation.h>

@interface MYPlayerSettings : NSObject

@property (strong, nonatomic) NSString *name;
@property (nonatomic) int age;
@property (nonatomic) double mouseSensitivity;
@property (strong, nonatomic) NSString *currentLevel;

@end

What we did was create four properties that pertain to the player settings. If any of these four properties are changed, we want to instantly save the player settings. Notice that there is no - (void)saveSettings; method? That's because there will be no need to manually save the settings; we'll do it all automatically. In order to do that though, we need to implement the player settings, so lets get to that.

#import "MYPlayerSettings.h"

@interface MYPlayerSettings ()
@property (nonatomic) BOOL settingsChanged;
@end

@implementation MYPlayerSettings
@end

In order to make things simple, we are going to use a BOOL property called settingsChanged. This property will be the only thing responsible for saving the player settings. I'll show you how by implementing the properties setter method next.

#import "MYPlayerSettings.h"

@interface MYPlayerSettings ()
@property (nonatomic) BOOL settingsChanged;
@end

@implementation MYPlayerSettings

// Setter method
- (void)setSettingsChanged:(BOOL)settingsChanged {
    _settingsChanged = settingsChanged;
    if (settingsChanged) [self savePlayerSettings];
    _settingsChanged = NO; // We are saved; no longer changed.
}

- (void)savePlayerSettings {
    // Do stuff.
}
@end

In our settingsChanged setter method, we check if the settingsChanged property is being set to YES. If it is, then we need to save the player settings, so we invoke the [self savePlayerSettings]; method. Note that the savePlayerSettings method is private; just like I said above, the player settings class will handle saving itself, there is no need to expose the method via the public API.

Next, we need to actually provide a way to set the settingsChanged property right? We do that by implementing the setter methods for our four properties like so:

- (void)setName:(NSString *)name {
    _name = name;
    self.settingsChanged = YES;
}

- (void)setAge:(int)age {
    _age = age;
    self.settingsChanged = YES;
}

- (void)setCurrentLevel:(NSString *)currentLevel {
    _currentLevel = currentLevel;
    self.settingsChanged = YES;
}

- (void)setMouseSensitivity:(double)mouseSensitivity {
    _mouseSensitivity = mouseSensitivity;
    self.settingsChanged = YES;
}

Not to bad right? Anytime that your game needs to adjust a setting, the player settings will automatically get saved. Now this does have some drawbacks, such as what happens if you change the player's settings from two different threads or what if you save method is asynchronous? There are some edge cases to consider with this approach, so keep that in mind. For small objects such as this, with quick file I/O operations, this would work just fine.

What if I have a handful of classes, each with a dozen properties that I want to implement this with? Isn't there an easier way? Why yes there is. You can either statically monitor or dynamically monitor an object via KVO, both of which I'll show you next.

Monitoring statically via KVO Part 1:

We will continue to use the PlayerSettings class for this example, but we will build on it because (hypothetically) you have added additional settings to the player that need to be saved. As mentioned above, it's a royal pain to write out a setter method for every single property, just for the sake of setting settingsChanged to YES. Let's do this a bit differently. We will use KVO.

KVO stands for Key-value observing and it provides a mechanism for objects to be notified when changes are made to a object's properties. There are a couple of ways we could do this, one of which modifies the above setter methods to look like such:

#import "MYPlayerSettings.h"

@implementation MYPlayerSettings

- (void)setName:(NSString *)name {
    _name = name;
    [[NSNotificationCenter defaultCenter] postNotificationName:@"settingChanged" object:self];
}

- (void)setAge:(int)age {
    _age = age;
    [[NSNotificationCenter defaultCenter] postNotificationName:@"settingChanged" object:self];
}

- (void)setCurrentLevel:(NSString *)currentLevel {
    _currentLevel = currentLevel;
    [[NSNotificationCenter defaultCenter] postNotificationName:@"settingChanged" object:self];
}

- (void)setMouseSensitivity:(double)mouseSensitivity {
    _mouseSensitivity = mouseSensitivity;
    [[NSNotificationCenter defaultCenter] postNotificationName:@"settingChanged" object:self];
}

- (void)savePlayerSettings {
    // Do stuff.
}
@end

As you can see, we no longer have the @property (nonatomic) BOOL settingsChanged; property, nor the setter method were we invoke the [self savePlayerSettings]; method. Instead, we have this nifty [[NSNotificationCenter defaultCenter] postNotificationName:object:]; call. What this does is send a message to the specified object (in this case self) with a notification called settingChanged. The notification name can be anything, I just happened to use settingChanged because it seems appropriately titled.

Once this happens, NSNotificationCenter will look for any object that is registered to receive the settingChanged message. This is called observing an object and in this case, the above code will do nothing because we have not added any observers. We will do that by implementing the PlayerSettings initializer method.

- (id)init {
    self = [super init];
    if (self) {
        [[NSNotificationCenter defaultCenter]
         addObserver:self
         selector:@selector(savePlayerSettings)
         name:@"settingChanged"
         object:self];
    }
    return self;
}

In the initializer we are adding ourself as on observe to any property within ourself that sends the settingChanged notification. It's important that the object argument has self as the parameter, otherwise our PlayerSettings class will be registering to receive settingChanged notifications from any object, which could be bad. For this example, we only want to receive messages from changes made to ourself. Also note that the parameter selector:@selector(savePlayerSettings) is telling NSNotificationCenter to invoke our [self savePlayerSettings] method when it receives the settingChanged notification. Now, unlike our manual approach, we are no longer manually invoking the save method in our private code either!

Now, let's assume someplace in your game you need to instance some player settings and assign some values. You would do so like this:

MYPlayerSettings *settings = [[MYPlayerSettings alloc] init];
settings.name = @"Bob";
settings.age = 22;
settings.currentLevel = @"Last level";

Each time you assign a property a value, the settings object will be saved automatically. As mentioned before, it works just fine for something small like this, or if you are only saving the changes. In the event that you have a massive amount of properties, or a lot of objects that will have it's entire object saved or transferred, you don't want to have your save code being called after each assignment. What if your save code is sending the data across the network to a server someplace? You are wasting data by just sending the save data across the network multiple times. This needs to be fixed! On top of that, wasn't the point of using KVO to elemenate the need for implementing the setter method on our properties? We're still doing that! Let's take care of that.

Monitoring statically via KVO Part 2:

We will continue to use our previous PlayerSettings.h file, but we are going to start fresh on our PlayerSettings.m file. It should look like this:

#import "MYPlayerSettings.h"

@implementation MYPlayerSettings
@end

Nice and empty! Now, as your class grows, it can be a pain in the behind to continously add new setter method for our properties, so that's going to stop. Instead, we will rely on KVO a bit differently by observing actual properties themselves rather than observing a object for a broadcasted message. Our PlayerSettings will no longer broadcast a settingChanged message when properties are changed, instead the PlayerSettings class will be self-aware and know when it has had it's own properties changed. In order to do this, we need to do a couple of things first. We need to implement a init method, a observeValueForKeyPath:ofObject:change:context: method and finally our savePlayerSettings method.

To get started, the PlayerSettings object needs to know what properties to monitor for changes, so we implement our initializer method and add ourself as an observer to those properties.

- (id)init {
    self = [super init];
    if (self) {
        [self addObserver:self forKeyPath:@"name" options:0 context:NULL];
        [self addObserver:self forKeyPath:@"age" options:0 context:NULL];
        [self addObserver:self forKeyPath:@"currentLevel" options:0 context:NULL];
        [self addObserver:self forKeyPath:@"mouseSensitivity" options:0 context:NULL];
    }
    return self;
}

That's a pretty easy initializer to implement, we just tell ourself that we want to observe ourself, monitoring each property that we specify. Now, when a property is changed, our PlayerSettings object will be made aware of it! How does this happen though? If you remember earlier, we specified that we wanted our savePlayerSettings method to be used right? In the above code, we aren't specifying any method, so what gets invoked? The answer to that lays in the Apple Documentation:

The observer must implement the key-value observing method observeValueForKeyPath:ofObject:change:context:.

Since we are observing ourself, we have to implement the observeValueForKeyPath:ofobject:change:context: method ourself. When a property is changed, this method will automatically be invoked for us. So that means, within that method, we can invoke our savePlayerSettings method.

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
    [self savePlayerSettings];
}

- (void)savePlayerSettings {
    NSLog(@"%@ saved", self.name);
}

Now we have a fully automated save system and it's actually fewer lines of code than before. As you add new properties to the PlayerSettings class, you just need to go and observe them in the initializer.

We still have the same problem however of saving multiple times when we don't really need to. Take the following code, re-used from above:

MYPlayerSettings *settings = [[MYPlayerSettings alloc] init];
settings.name = @"Bob";
settings.age = 22;
settings.currentLevel = @"Last level";
settings.mouseSensitivity = 5.0;

Due to all four properties being changed, the save code will be called four different times. Is that efficient? Not really, so we need to fix that. I chose to take a similar approach as to what Apple did with their UI animations. We will add two new methods and two different properties. The methods will be called beginUpdates and endUpdates and our properties will be two BOOL values called settingsChanged and performingBatchChanges.

First let's create the two properties in our .m file like such:

@interface MYPlayerSettings ()
@property (nonatomic) BOOL settingChanged;
@property (nonatomic) BOOL performingBatchChanges;
@end

When we invoke our observeValueForKeyPath: method, we will need to perform a check. First, check if we are performingBatchChanges and if so, do not save the player settings. Since we are doing batch changes, we will save the player setting once we are completed with all of the changes. Since we know that settings have changed though, we need to set settingChanged to YES.

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
    if (self.performingBatchChanges) {
        self.settingChanged = YES;
    } else {
        [self savePlayerSettings];
    }
}

In order to perform the batch changes, we need to implement our two new methods, beginUpdates and endUpdates. These two methods are really simple and need to be added to your .h file like this:

#import <Foundation/Foundation.h>

@interface MYPlayerSettings : NSObject

@property (strong, nonatomic) NSString *name;
@property (nonatomic) int age;
@property (nonatomic) double mouseSensitivity;
@property (strong, nonatomic) NSString *currentLevel;

- (void)beginUpdates;
- (void)endUpdates;
@end

Next we will add the implementation of these two new methods into our .m file like this:

- (void)beginUpdates {
    self.performingBatchChanges = YES;
}

- (void)endUpdates {
    self.performingBatchChanges = NO;

    if (self.settingChanged) {
        [self savePlayerSettings];
    }
}

This is pretty straight forward. When a property is changed, our observeValueForKeyPath: method is invoked. We check if we are performing batch changes (due to the user invoking beginUpdates prior to changing the property) and we set the settingChanged property to YES to indicate that we have changed settings but not saved them. If this is not a batch change, then we just save the settings. Once the user invokes the endUpdates method, we set our performingBatchChanges to NO because we are no longer making batch changes. Lastly, we have to check if the settings were changed and if they were, save them. Why perform this check? It's possible for the user to do the following:

[self.playerSettings beginUpdates];
[self.playerSettings endUpdates];

If they invoked the beginUpdates and endUpdates methods without ever making any changes, then we would be needlessly saving the player settings.

So, how do we use this? Pretty simply, if you are changing one or two properties, just use the settings file like normal.

self.playerSettings = [[MYPlayerSettings alloc] init];
self.playerSettings.mouseSensitivity = 5.0;

There's no harm in changing one or two settings, but if you are wanting to change several, then you use your new beginUpdates and endUpdates methods.

self.playerSettings = [[MYPlayerSettings alloc] init];
[self.playerSettings beginUpdates];
self.playerSettings.name = @"Bob";
self.playerSettings.age = 22;
self.playerSettings.currentLevel = @"Last level";
self.playerSettings.mouseSensitivity = 5.0;
[self.playerSettings endUpdates];

The player settings will only be saved once now, at the end when endUpdates is invoked. Saves on I/O or data usage if the content is sent over the network.

Alright, we are now monitoring our object's properties and automatically invoking our save method. What if we want to add another object, like a GameSettings to our project? It's simple enough that we can re-use the above code and get it up and running, but what if we could just write the code once and never re-write it again; while using across dozens of classes? Monitoring property changes dynamically via KVO can get the job done.

Monitoring dynamically via KVO

This approach digs into the Objective-C runtime and requires use of it's C runtime functions. I assume the reader has some understanding of what ARC does and is famiiar with introspection. As with most dynamic approaches, this one comes with the largest performance hit. You will not see the hit unless you are using this on hundreds of objects (like in a game).

Let's start off by creating a new class called MYGameSettings and providing it with some properties in the header.

#import <Foundation/Foundation.h>

@interface MYGameSettings : NSObject

@property (strong, nonatomic) NSString *version;
@property (nonatomic) int brightness;
@property (nonatomic) BOOL hardMode;

@end

We will save the implementation for last, as we need to build our dynamic object monitoring class first.

We are going to create a new class called ObjectMonitor. This object will be used to observe our classes from now on, monitoring what happens to the classes and then acting on the changes that take place. Let's set up our ObjectMonitor.h header first.

#import <Foundation/Foundation.h>

@interface ObjectMonitor : NSObject

- (id)initWithMonitoringObject:(NSObject *)objectToMonitor respondingWithSelector:(SEL)selector;

@end

We will implement a new initializer that accepts the object we want to monitor, and a selector which identifies a method that we will invoke on the objectToMonitor. What this will do, is allow ObjectMonitor to monitor our GameSettings and PlayerSettings objects (or any other object you provide it) and each object will tell ObjectMonitor what method to invoke. When a property on the observed class changes, the ObjectMonitor will invoke the requested method, within the provided object, in this case our settings classes. You'll see how it all comes together in the end. For now, we need to implement our ObjectMonitor.m implementation, so let's do that. First, the initializer and our selector property:

#import "ObjectMonitor.h"
#import <objc/objc-runtime.h>

@interface ObjectMonitor ()
@property (nonatomic) SEL selector;
@end

@implementation ObjectMonitor

- (id)initWithMonitoringObject:(NSObject *)objectToMonitor respondingWithSelector:(SEL)selector {
    self = [super init];

    if (self) {
        self.selector = selector;

        unsigned int count;
        objc_property_t *properties = class_copyPropertyList([objectToMonitor class], &count);

        for (size_t i = 0; i < count; ++i) {
            NSString *key = [NSString stringWithUTF8String:property_getName(properties[i])];
            [objectToMonitor addObserver:self forKeyPath:key
                  options:0 context:NULL];
        }

        free(properties);
    }
    return self;
}
@end

The first thing we do in our initializer is store a reference to the selector provided to us for future use. A selector is nothing more than a pointer to a method stored in a variable for us to use at a later date. This can cause some issues, which we will discuss and handle in just a bit.

Next, we have this interesting Objective-C Runtime function: class_copyPropertyList([objectToMonitor class], &count); Here we are calling the C runtime function class_copyPropertyList which takes a class as an argument and outputs the number of properties contained within that class. It also returns an array of every property that the class has. So we have the number of properties that the object has stored in the count variable and an array of every property the object has stored in the properties variable. What next you ask? We itterate through each property and observe them!

In our for-loop we use another C runtime function called property_getName which takes a property from our array and determines it's name and returns it for us. That provides us with a fully qualified property name that belongs to objectToMonitor. We then tell objectToMonitor that we are going to observe it for any changes made to that property. We then loop through the rest of the array, adding ourself as an observer to each property found in the object.

Finally we invoke the C runtime function free which releases the properties array from memory. Since C functions are not managed by ARC, we have to manage the memory ourselves.

A side note on observing the objectToMonitor for property changes. If you wanted, you could expand on this by adding a NSArray argument to this initializer with properties that you want exempt from observation. Then you could adjust your for-loop to be like this:

    for (size_t i = 0; i < count; ++i) {
        NSString *key = [NSString stringWithUTF8String:property_getName(properties[i])];

        // If this property is in our exempt array, we skip it and move on to the next.
        if ([exemptProperties containsObject:key]) {
            continue;
        }
        [objectToMonitor addObserver:self forKeyPath:key
                  options:0 context:NULL];
    }

Instead of providing a list of exemptions, you could just provide a list of properties to observe as well. This could be useful if you have several dozen properties but only want to monitor a handful. In most cases though, manually observing those using static KVO or the manual approach above is probably a better idea.

Alright, we have our initializer wrote and we are now observing any object that instances our ObjectMonitor! The next thing to do would be to do something when the properties are actually changed. Remember the observeValueForKeyPath method we implemented in our PlayerSettings class? Well, our ObjectMonitor class will implement that now, and our PlayerSettings and GameSettings classes won't have to implement this at all.

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    NSLog(@"%@ had %@ changed!", NSStringFromClass([object class]), keyPath);

    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[[object class] instanceMethodSignatureForSelector:self.selector]];
    if (invocation) {
        invocation.target = object;
        invocation.selector = self.selector;
        @try {
            [invocation invoke];
        }
        @catch (NSException *exception) {
            NSLog(@"Failed to invoke the method");
        }
        @finally {

        }
    } else {
        NSLog(@"ERROR: Failed to locate the method for @selector:%@", NSStringFromSelector(self.selector));
    }
}

The first thing we do is print to the debugger that we have entered the method due to an object's properties changing. The method arguments provides us with the property name and the object that the property belongs to. The property name is stored in keyPath and the object that owns the property is object. Since the method provides us with this information, we can print the name of the property using NSLog and include the class name. Since the object is not a string, we get the name of the class by using NSStringFromClass.

The next part can make or break your app, so you really want to make sure and set it up properly. We instance a NSInvocation object, which will be used to actually invoke the method provided to us and stored under self.selector. It's really important that you don't use [object performSelector:self.selector]; because this will not be memory safe and can leak. The runtime needs to know what to do with the result of your method invocation, which could be anything (void,BOOL, MYPlayerSettings). ARC would normally acquire this information from your objects header. With this approach, the ObjectMonitor class has no idea what method is stored in the selector, preventing the runtime from determining what the result is. This causes a compiler warning to be generated stating that a leak could occure. You could potentially acquire the actual method pointer itself by using IMP imp = [methodForSelector:self.selector]; but there is no guarantee that the correct method signature will be returned. So invoking imp could crash your app.

So, how do we get around this safely, keeping the runtime happy? We use NSInvocation. This is not a crash free solution but if you code it right and provide proper documentation on how to use the ObjectMonitor then you can have it work without a hitch.

The [NSInvocation invocationWithMethodSignature: instanceMethodSignatureForSelector:] checks the properties owner (object argument) to see if it has the selector we have a reference stored to. If it does, then a valid NSInvocation object is returned. If no method exists, then nil is returned. We check against nil on the very next line, so if no method is returned, we don't try to invoke it and crash out app.

We tell the invocation which object we want to invoke the method on ( invocation.target = object;) and then we tell it which method to invoke (invocation.selector = self.selector;). Lastly, we invoke the method using [invocation invoke]; and we wrap this invocation in a @try/@catch in the event that the invocation fails.

Using this approach, our ObjectMonitor is fairly safe to use. In the event an invalid method is provided we are protected from crashes. One last item to mention before we move on from our ObjectMonitor class. The [invocation invoke]; call invokes the method specified with zero arguments. What if you would like to know what property changed? You can do that by adjusting the if statement to look like this:

NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[[object class] instanceMethodSignatureForSelector:self.selector]];
if (invocation) {
    invocation.target = object;
    invocation.selector = self.selector;
    [invocation setArgument:&keyPath atIndex:2]; // index 0 = self and index 1 = _cmd
    @try {
        [invocation invoke];
    }
    @catch (NSException *exception) {
        NSLog(@"Failed to invoke the method");
    }
    @finally {

    }
} else {
    NSLog(@"ERROR: Failed to locate the method for @selector:%@", NSStringFromSelector(self.selector));
}

It is critical that the atIndex argument in the setArgument call is 2 or greater. The Objective-C runtime invokes all methods by send a message to the object. The message is objc_msgSend() and it requires at least two arguments. The receiver (in this case our object we are monitoring) and a selector. All Objective-C messages have two arguments that are always included. The first argument is passed as the receiver of the second agument (our method selector) and is most often passed as self. The second argument (selector) is passed as \_cmd and contains a pointer to our actual object method. So we can start adding arguments at index 2. If you would like to invoke the method we specify and provide the property name that was changed, you can do so. Your object that actually implements the method being invoked must have an argument that accepts what you add to the NSInvocation, otherwise it will fail to invoke. Luckily, since we wrapped it in a @try/@catch it won't crash your app. It can be annoying to debug though.

So, that's it, we have built our ObjectMonitor class. Now let's use it. We will return to our PlayerSettings class and re-write it to make use of this. We add our ObjectMonitor as a property and then in our PlayerSettings initializer, we instance it, tell it to observe us and we provide it our savePlayerSettings method for invocation.

#import "MYPlayerSettings.h"
#import "ObjectMonitor.h"

@interface MYPlayerSettings ()
@property (strong, nonatomic) ObjectMonitor *objectMonitor;
@end

@implementation MYPlayerSettings

-(id)init {
    self = [super init];
    if (self) {
        self.objectMonitor = [[ObjectMonitor alloc]
                              initWithMonitoringObject:self
                              respondingWithSelector:@selector(savePlayerSettings)];
    }
    return self;
}

- (void)savePlayerSettings {
    NSLog(@"%@ saved", self.name);
}

@end

And we do the same thing with our GameSettings class.

#import "MYGameSettings.h"
#import "ObjectMonitor.h"

@interface MYGameSettings ()
@property (strong, nonatomic) ObjectMonitor *monitor;
@end

@implementation MYGameSettings

- (id)init {
    self = [super init];
    if (self) {
        self.monitor = [[ObjectMonitor alloc]
                        initWithMonitoringObject:self
                        respondingWithSelector:@selector(saveGameSettings)];
    }
    return self;
}

- (void)saveGameSettings {
    NSLog(@"Game settings saved!");
}
@end

Isn't it nice that we can now add object property monitoring to any class we want with just 2 lines of code? A property declaration and instancing. Now we can use the following code, anywhere in our app:

self.playerSettings = [[MYPlayerSettings alloc] init];
self.playerSettings.name = @"Bob";
self.playerSettings.age = 22;
self.playerSettings.currentLevel = @"Last level";
self.playerSettings.mouseSensitivity = 5.0;

self.gameSettings = [[MYGameSettings alloc] init];
self.gameSettings.brightness = 73;
self.gameSettings.hardMode = NO;
self.gameSettings.version = @"1.0";

Our game settings and player settings will always be saved.

Of course we lost the ability to use our cool beginUpdates and endUpdates, but that can easily be reimplemented. You just re-set it back up and in your savem methods, don't actually save if performingBatchUpdates is YES.

I hope this document on implementing the ability to dynamically monitor any property on any object proves to be useful to you guys. It only took me about 5 hours to write!

Until next post.