Why is MoGenerator falling afoul of ARC?

1.1k views Asked by At

My command line (a build phase) for MoGen is

mogenerator -m PT1/Data/DataModel.xcdatamodeld -O PT1/Data -–template-var arc=true

This is supposed to work for ARC. However in the machine classes I get something like

extern const struct ClientInfoAttributes {
    NSString *accountNumber;
    ...
} ClientInfoAttributes;

This gives the error "ARC forbids Objective-C objects in struct". Presumably I have made some kind of mistake here. Can anybody point out my problem?

I am working with the iOS7 and XCode 5 beta, but this does not seem to be related to that. It may be relevant though.

-Bob

2

There are 2 answers

1
LostInTheTrees On BEST ANSWER

I WAS using the correct option to mogenerator for ARC. It is --template-var arc=true as you see above in my original question. However, I copied the command line from this blog entry, raptureinvenice.com/getting-started-with-mogenerator. In this entry the interwebs software had changed the author's "--" to an long dash or m-dash. When I copied and pasted I got a dash that looked right but was not. The mogen software does not currently flag this as an error. It just silently ignores it.

When I finally retyped the -- from scratch it worked correctly. Mogen uses __unsafe_unretained to prevent the compiler errors.

The blog author has already fixed the blog entry and I have lodged an issue with the mogen project to report errors of this type in the future.

1
Gabriele Petronella On

I suspect the order matters. Use

mogenerator --template-var arc=true -m PT1/Data/DataModel.xcdatamodeld -O PT1/Data


About the error, it is self-explanatory

ARC forbids Objective-C objects in struct

As explained in the clang documentation

4.3.5 Ownership-qualified fields of structs and unions

A program is ill-formed if it declares a member of a C struct or union to have a nontrivially ownership-qualified type.

Rationale

The resulting type would be non-POD in the C++ sense, but C does not give us very good language tools for managing the lifetime of aggregates, so it is more convenient to simply forbid them. It is still possible to manage this with a void* or an __unsafe_unretained object.

So, as the documentation suggests, the quick and dirty solution for this is to declare the object as __unsafe_unretained. Something like:

extern const struct ClientInfoAttributes {
    __unsafe_unretained NSString *accountNumber;
    ...
} ClientInfoAttributes;

Anyway beware since from now on you have to take care of memory management for such object.