Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why am I getting "unrecognized selector" errors when subclassing GDataEntryBase from Google Data Objective-C Client Library?

I've built the Google Data APIs Objective-C Client Library and have it linking and working with my application (incl. GTMOAuth2) and can pull data back. I need to work with the Provisioning API (still XML-only) so am building out the additions I need within my own application. I think I have finally figured out how all of this works and I'm very close to reading custom elements, but I'm missing something.

I've subclassed GDataServiceGoogle, GDataEntryBase, and GDataFeedBase and am getting correct data back. I'm starting with a simple & straightforward element type: quota. In the Users feed, the quota element looks like this:

<apps:quota limit="2048"/>

So, I've added the following value construct:

@interface GDataQuotaProperty : GDataValueConstruct <GDataExtension>
+ (NSString *)extensionElementURI;
+ (NSString *)extensionElementPrefix;
+ (NSString *)extensionElementLocalName;
@end

@implementation GDataQuotaProperty
+ (NSString *)extensionElementURI       { return kGDataNamespaceGApps; }
+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGAppsPrefix; }
+ (NSString *)extensionElementLocalName { return @"quota"; }
@end

And I've added the following methods to my GDataEntryBase subclass:

- (GDataQuotaProperty *)quota;
- (void)setQuota:(GDataQuotaProperty *)val;

Implemented as follows:

- (GDataQuotaProperty *)quota {
    return [self objectForExtensionClass:[GDataQuotaProperty class]];
}

- (void)setQuota:(GDataQuotaProperty *)val {
    [self setObject:val forExtensionClass:[GDataQuotaProperty class]];
}

As documented in the comments in GDataObject.h (and I've been working off of GDataServiceGoogleCalendar, GDataEntryCalendar, and GDataFeedCalendar as a reference implementation), in my GDataBaseEntry subclass I've implemented addExtensionDeclarations as follows:

- (void)addExtensionDeclarations {
    [super addExtensionDeclarations];

    Class entryClass = [self class];

    // User extensions
    [self addExtensionDeclarationForParentClass:entryClass
                                   childClasses:[GDataQuotaProperty class], nil];
}

However, when I try to call the quota method as follows in my callback:

GDataTextConstruct *titleTextConstruct = [user title];
NSString *title = [titleTextConstruct stringValue];
GDataQuotaProperty *quotaConstruct = [user quota];
NSString *quota = [quotaConstruct stringValue];

I get an exception and this error:

2012-11-19 12:42:22.667 Google Apps Open Directory Sync[47679:903] -[GDataEntryBase quota]: unrecognized selector sent to instance 0x2836d0

In the above example I do get the user's name (the element's title) back correctly without error. Also, the user object is actually of the type of my GDataEntryBase subclass, not GDataEntryBase itself (verified in the debugger), plus the classForEntries method in my GDataFeedBase subclass correctly returns the class of my subclass of GDataEntryBase) so between the two of those it really has to be the correct class. I have a breakpoint on my GDataEntryBase subclass's quota method which is never being tripped, so what am I missing here?

As mentioned, I've been comparing with the Service/Feed/Entry implementation for Calendar (specifically the accessLevel & color elements and methods) and am just not seeing what I'm missing.

Thanks in advance for any assistance you can provide.

like image 465
morgant Avatar asked Nov 12 '22 17:11

morgant


1 Answers

While I had implemented the classForEntries method in my GDataFeedBase subclass and was correctly returning the class of my GDataEntryBase subclass from it, as follows:

- (Class)classForEntries {
    return [GDataEntryUser class];
}

I had missed the implementation of standardKindAttributeValue in the same GDataFeedBase subclass, which should've been returning the appropriate category schema URL ("http://schemas.google.com/apps/2006#user" in the case of Google Provisioning API User feeds). So, I implemented as follows (although I actually use a constant):

+ (NSString *)standardKindAttributeValue {
    return @"http://schemas.google.com/apps/2006#user";
}

Once addExtensionDeclarations, classForEntries, and standardKindAttributeValue were all implemented correctly, GDataEntryBase was able to correctly determine that my subclass should be used for the objects in the feed and so my selectors were recognized.

Many thanks to Greg Robbins of Google for pointing me in the right direction in this thread on the Google Data APIs Objective-C Client Libraries discussion group.

like image 97
morgant Avatar answered Nov 15 '22 07:11

morgant