Home Blog Is it time to say goodbye to Mogenerator?

Is it time to say goodbye to Mogenerator?

7th December 2015

For iOS and OS X developers who use Core Data, a little tool called Mogenerator has arguably been the preferred way to generate Objective C (and Swift) classes for your data model. But improvements in Xcode 7 may mean that the need for Mogenerator is less compelling than it once was.

If you’re developing iPhone and iPad Apps that need to store complex data structures on the device, there’s a good chance you’re using Apple’s Core Data API to read and write that data. Core Data uses an SQLite database under the hood, but provides an Object Oriented abstraction layer that developers can use to read and write to the SQLite datastore. In fact Core Data is a very rich API that provides a whole range of conveniences – but we won’t go into that here.

The first step after you’ve decided to use Core Data is to design your data model. Xcode provides a modelling tool that allows you to do just that as illustrated here:

model

In this example we’ve created a simple Model composed of two Entities – Person and Address. An Address belongs to a SINGLE and very lonely Person who lives alone. On the other hand, with no dependants – that Person may have managed to save up some money and built a property empire. As a result a Person can have MANY Addresses.

As a developer I need a way to store Persons and Addresses so I can use that data in my App. Xcode has always provided a tool (NSManagedObject Generator) to generate Objective C – and now Swift – classes to represent that data. But that tool – up until very recently anyway – wasn’t really that good. It suffered from a few drawbacks not the least of which was the fact that re-generating your classes when your model evolved was something of a chore if you added any code to those classes that you wanted to keep.

Enter Mogenerator

Mogenerator is an open-source tool that also can generate classes from your data model that you can use in your App. But it added some great features that made it significantly more useful than pre-Xcode-7’s  built-in tool. In particular it generates two files for your Object: one file you can modify and be assured never gets touched, the other you leave alone. Whenever your model changed – for example you decide Persons can have a birthdate – you run mogenerator again and voila, your classes are up to date AND your custom code is untouched.

Compared to pre-Xcode 7, mogenerator does a better job of generating class files from your data model, especially in projects where your model is evolving over time which, in my experience, is pretty much any project. But it is a third party tool and as a general rule if you’re going to invest in a dependancy then it had better provide a unique and compelling offer – which it does. In fact it would seem that Apple noticed and as a result Xcode 7 introduced some significant improvements to it’s generator tool. In fact in my test-drive to-date on a new project, I find Apple’s revamped generator to be more than fit for purpose, albeit with a few caveats.

NSManagedObject Generator And Swift

As I mentioned, Apple’s Generator can produce Objective C or Swift representations of the Entities in your data model. We’ve embraced Swift here for new projects and have been really happy with Apple’s new programming language. So naturally it made sense to generate Swift classes from our model. The generator produces two files: Person.swift and Person+CoreDataProperties.swift. The first is an empty class definition which is the file we are meant to use to add custom code to the Person managed object. The second file contains the properties and relationships defined in our model.

Here’s what the key bits of that file looks like:

extension Person {

    @NSManaged var name: String?
    @NSManaged var addresses: NSSet?

}

There’s a couple of problems here. First off the addresses relationship is declared as an NSSet. NSSet is immutable which means I can’t add items to it – like new Addresses – nor can I delete. So I would need to make a mutable copy of the existing NSSet, modify the copy and then replace the addresses NSSet with an immutable copy of the mutable copy. Yuck!

Secondly the variables are declared as Swift optionals – by adding the ‘?’ after the type e.g. String? and NSSet?. This means that I need to do nil checks when accessing these, even if I have marked these as non-optional in the model.

Last but not least the addresses NSSet has no type information, so when pulling objects from the Set I need to do type-checking and casting. This is perhaps clearer if you take a look at the Objective C code generated by Apple’s tool:

#import "Person.h"

NS_ASSUME_NONNULL_BEGIN

@interface Person (CoreDataProperties)

@property (nullable, nonatomic, retain) NSString *name;
@property (nullable, nonatomic, retain) NSSet<Address *> *addresses;

@end

@interface Person (CoreDataGeneratedAccessors)

- (void)addAddressesObject:(Address *)value;
- (void)removeAddressesObject:(Address *)value;
- (void)addAddresses:(NSSet<Address *> *)values;
- (void)removeAddresses:(NSSet<Address *> *)values;

@end

NS_ASSUME_NONNULL_END

A few things to note about the Objective C code generated:

  • The use of NS_ASSUME_NONNULL_BEGIN / NS_ASSUME_NONNULL_END tells calling Swift code that the properties and function return-values are non-optional so no nil-checks needed.
  • The Addresses NSSet uses generics to assign a type to the members of the Set – namely Address. So no ugly type-checking and casting required when pulling data from the Set.
  • Most critically, the generator has provided methods to add and remove individual Address objects from a Person, e.g. addAddressesObject(). This means we can manipulate a Person’s Addresses without having to bother with copying immutable objects into mutable objects and replacing them.

So when using Apple’s tool there are some pretty compelling reasons for generating Objective C code rather than Swift. But if you are committed to moving into Swift as your de-facto language for iOS development you might think it makes sense to stick with mogenerator. Unfortunately mogenerator has similar issues with the Swift code it generates – exactly why that is we’ll leave for another blog post. So no advantage using mogenerator there.

Like the swift version above, Apple provides us with a file where we can add custom code that the generator will not overwrite. It’s an Objective C file though. But, we can still write our custom code in Swift by using an extension:

extension Person {
    func addressCount() -> Int {       
        return (addresses?.count)!;
    }
}

The above is admittedly a bit contrived, but hopefully illustrates how we can add code to our Person object – in Swift – and still be able to re-generate our classes as our data model evolves, while keeping our existing hard work.

Mogenerator is still a great tool for generating a set of class files from a Core Data data model. But it is a third party library that requires extra effort to setup and a willingness to assume that it will be maintained as the iOS platform evolves. When it provided important functionality not available in Apple’s off-the-shelf offerings, it made great sense to use it.

Xcode 7 introduced a re-vamped NSManagedObject generator that seems to be feature-comparable with mogenerator. Given this, it makes sense to use it – especially on new projects – rather than mogenerator. Unfortunately the ‘generate Swift code’ option is not as mature as the ‘generate Objective C’ option. So you’ll want to generate Objective C and optionally use Swift extensions to extend the generated NSManagedObject subclasses, as we’ve shown above.

Related Articles


on 7th December 2015