13

Now that Xcode4 is publicly available I'm moving this question out of Apple's secret dev forum:

Can someone explain why the code generated in the following procedure is different than in Xcode3? Is the code better or might this be a bug?

I use Core Data custom managed classes and this was the procedure I followed in Xcode3:

  1. Go to the model editor
  2. Select the entity you wish to generate source code for
  3. Go to File->New->New Files
  4. Choose managedobject class (or whatever it was, I can't open xcode3 anymore to verify)
  5. Select entities you wish to generate (the previously selected entity in step 2 is checked off)
  6. Click Finish

Now, in Xcode4, I THINK this is how to do it, but I'm not sure because it generates different code:

  1. Go to model editor
  2. Select entity
  3. Go to File->New->New File
  4. Choose "NSManagedObject subclass"
  5. Choose location and create.

The code it is generating is different for a number of reasons:

  1. The generated code for adding and removing members of a set in the entity are no longer declared in the @interface, but instead @implementation. This causes code sense to fail detecting these methods.
  2. The same generated code for adding and removing objects is now fully defined, no longer autogenerated using CoreDataGeneratedAccessors

For example, Xcode3 would have generated this code in the HEADER file:

@interface SampleEntity (CoreDataGeneratedAccessors)
- (void)addChildObject:(Child *)value;
- (void)removeChildObject:(Child *)value;
- (void)addChild:(NSSet *)value;
- (void)removeChild:(NSSet *)value;
@end

Now, Xcode4 generates this code in the IMPLEMENTATION file:

@implementation SampleEntity
@dynamic children;
- (void)addChildObject:(Child *)value {    
    NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1];
    [self willChangeValueForKey:@"children" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects];
    [[self primitiveValueForKey:@"children"] addObject:value];
    [self didChangeValueForKey:@"children" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects];
    [changedObjects release];
}

Can someone weigh in on why this is different? Xcode4 code sense does not like this new way of generating NSManagedObject subclasses.

pokstad
  • 3,411
  • 3
  • 30
  • 39
  • Starting a bounty to get more input on this. Monogenerator doesn't plugin with Xcode 4, so that doesn't seem like an ideal solution right now. – GendoIkari Mar 16 '11 at 20:10
  • @Gendolkari: Don't let the bounty expire :) – Goz Mar 21 '11 at 21:58
  • I hope not to! But so far no answer has at all addressed the question of why the code generation system that worked just fine has been removed from Xcode 4, or if there's something different that Apple expects us to do. The code that is generated now is worthless because it doesn't put declarations in the .h file. – GendoIkari Mar 22 '11 at 20:44

6 Answers6

11

Short answer: Don't use Xcode's code generation. Use mogenerator and enjoy an easier life.

As for the why, it is hard to say. I have never been a fan of the way that Xcode generates the Core Data subclasses and would not recommend them. We could guess as to why they did the things they have done but based on other issues with Xcode4 and Core Data I would chalk it up to "not ready" or "not fully tested".

File a radar if you would like to continue to use Xcode code generator.

Marcus S. Zarra
  • 46,571
  • 9
  • 101
  • 182
  • Is mogenerator's generated code easier to read? One thing I do like about Xcode3's generated code using CoreDataGeneratedAccessors is that it's simple. – pokstad Mar 10 '11 at 01:29
  • 1
    +1 You can also modify mogenerator to produce classes as you would like them look. Takes a little Ruby but it can be worth your time. – TechZen Mar 10 '11 at 14:56
  • Yes it is easy to read and more important it separates the generated code from your code (two levels of files, one human one machine) that the generated code can be re-generated without damaging your code. It is a better solution. – Marcus S. Zarra Mar 10 '11 at 19:42
  • I'm guessing the change of template code is like what happens with the other Xcode templates it generates for you. I swear that the OpenGL ES Application template has been different for every iOS SDK version I've tried it on. Anyway, mogenerator's the way to go. – Brad Larson Mar 10 '11 at 22:18
1

It looks like all Xcode4 has done is make explicit what the @dynanmic directive makes implicit. The generated code looks exactly like that generated by Xcode3 when you asked it to generate accessors for a particular attribute (to the clipboard.)

I'm not sure why they decided to do it that way. Possibly they thought it would make it easier for people to create custom accessors if they just gave them the full basic accessor.

It shouldn't be that hard for someone to shoehorn MOGenerator into Xcode4. Hint, hint. Anyone? Come on guys! Anyone? Bueller?

Sigh, looks like it me.

TechZen
  • 64,370
  • 15
  • 118
  • 145
  • If they're just explicitly defining what gets defined implicitly, then [can I delete Core Data's dynamically genereated methods?](http://stackoverflow.com/questions/5836179/can-i-delete-core-datas-dynamically-generated-methods-in-xcode-4) – ma11hew28 Apr 29 '11 at 20:43
1

Monogenerator doesn't plugin with Xcode 4 so you could use a runscript triggering mogenerators commandline util:

mogenerator -m Resources/CoreData/XcodeProj.xcdatamodeld/XcodeProj1.xcdatamodel --base-class RootManagedObjectClass --template-path Resources/MoGenerator -O Sources/Classes
Tycho Pandelaar
  • 7,367
  • 8
  • 44
  • 70
0

I discovered the same problem a month or so ago and posted about it on the Xcode 4 preview forums at apple. There's been no reply. To get mine working I just grabbed the method signatures from the .m file and created the category in the .h file. Basically hacked the generated code back to how XCode 3 would have done it. I haven't tried with the new release version of Xcode 4.

drekka
  • 20,957
  • 14
  • 79
  • 135
0

I use the old XCode 3 way you described in XCode 4 (latest with iOS4.3) and it works as before and what it generates for me is this:

    
#import <CoreData/CoreData.h>
@class JiraIssueType;
@class JiraPriority;
@class Customer;
@class JiraComment;
@class JiraComponent;
@class JiraUser;
@class Report;
@class Tag;

@interface JiraIssue :  NSManagedObject  
{
}

@property (nonatomic, retain) NSString * jiraId;
@property (nonatomic, retain) NSString * summary;
@property (nonatomic, retain) NSString * detailedDescription;
@property (nonatomic, retain) NSDate * createdDate;
@property (nonatomic, retain) NSDate * lastUpdatedDate;
@property (nonatomic, retain) NSString * key;
@property (nonatomic, retain) Report * report;
@property (nonatomic, retain) NSSet* comments;
@property (nonatomic, retain) JiraPriority * priority;
@property (nonatomic, retain) NSSet* components;
@property (nonatomic, retain) JiraIssueType * type;
@property (nonatomic, retain) Customer * customer;
@property (nonatomic, retain) NSSet* tags;
@property (nonatomic, retain) JiraUser * assignedTo;

@end


@interface JiraIssue (CoreDataGeneratedAccessors)
- (void)addCommentsObject:(JiraComment *)value;
- (void)removeCommentsObject:(JiraComment *)value;
- (void)addComments:(NSSet *)value;
- (void)removeComments:(NSSet *)value;

- (void)addComponentsObject:(JiraComponent *)value;
- (void)removeComponentsObject:(JiraComponent *)value;
- (void)addComponents:(NSSet *)value;
- (void)removeComponents:(NSSet *)value;

- (void)addTagsObject:(Tag *)value;
- (void)removeTagsObject:(Tag *)value;
- (void)addTags:(NSSet *)value;
- (void)removeTags:(NSSet *)value;

@end
0

Generating those accessors was really handy, not sure why they've changed that.

I use this snippets as an alternative:

- (void)add<#entity#>sObject:(<#entity#> *)value;
- (void)remove<#entity#>sObject:(<#entity#> *)value;
- (void)add<#entity#>s:(NSSet *)value;
- (void)remove<#entity#>s:(NSSet *)value;
Bach
  • 2,684
  • 5
  • 26
  • 36