willia4 / wsdl2objc

Automatically exported from code.google.com/p/wsdl2objc
MIT License
1 stars 0 forks source link

Support for NSCoding of Complex Types #78

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
If you happen to cache your data between application sessions it's useful to 
be able to use the NSKeyedArchiver and NSKeyedUnarchiver.

This patch adds some generic "attribute" encoding to the ComplexType 
template and support for encoding to the USEncoding as well. There may 
be cases for some data types (any remaining custom ones I missed?) that 
will need encoders implemented, but our testing so far shows everything is 
working great.

The generic property encoding code is from: 
http://davedelong.com/blog/2009/04/13/aspect-oriented-
programming-objective-c

It would not be a far stretch to template generated handlers for this instead 
of doing it with runtime reflection. A change for slightly better performance 
in that case, but likely at the minor expense of library size...

Original issue reported on code.google.com by james.sa...@gmail.com on 24 Mar 2010 at 5:52

Attachments:

GoogleCodeExporter commented 9 years ago
Issue 62 has been merged into this issue.

Original comment by hasse...@gmail.com on 26 Apr 2010 at 9:09

GoogleCodeExporter commented 9 years ago
This patch has errors and the resulting code doesn't compile. It's missing an 
include for the header declaring 
Ivar, and has mistyped allocations.

Original comment by hasse...@gmail.com on 3 May 2010 at 1:45

GoogleCodeExporter commented 9 years ago
I'll see what I can do, to provide a new patch.

Original comment by james.sa...@gmail.com on 3 May 2010 at 2:45

GoogleCodeExporter commented 9 years ago
The changes merge fine with the latest SVN. Project builds without a single 
error for me. I'm going to need 
more information before I can figure out what's going on for you. The generated 
code compiles without 
warnings as well.

What version of Xcode you using to compile the wsdl2objc?
What type of project are you compiling the generated code in?
What version of Xcode are you using?

I wouldn't mind if you told me which mistyped allocations you've found as well, 
I quickly looked it over but 
didn't see anything that stood out. 

Original comment by james.sa...@gmail.com on 3 May 2010 at 3:36

GoogleCodeExporter commented 9 years ago
Just chiming in, since I wrote the generic property encoding code...  The patch 
also applies cleanly for me and 
compiles without any significant warnings.  I'm running Xcode 3.2.3 to compile 
wsdl2objc.

Original comment by davedel...@gmail.com on 3 May 2010 at 4:46

GoogleCodeExporter commented 9 years ago
I'm also using XCode 3.2.3 (Pre-release).
When I generate the code for a wsdl, I'm getting the following:

  Ivar * ivars = class_copyIvarList([self class], &numIvars);
  for(int i = 0; i < numIvars; i++) {
    Ivar thisIvar = ivars[i];
    NSString * key = [NSString stringWithUTF8String:ivar_getName(thisIvar)];

In the first line, it says Ivar is undeclared. So it's missing an include.
In the 3rd line, it looks like it should be instead a pointer:
Ivar *thisIvar = ivars[i];

And in the 4th line, due to the error in the 3rd line, I'm getting thisIvar is 
undeclared.

Original comment by hasse...@gmail.com on 4 May 2010 at 12:42

GoogleCodeExporter commented 9 years ago
class_copyIvarList returns an array of Ivars.  In other words, it returns 
Ivar*.  An individual element of that array is 
an Ivar, not an Ivar* (so the code is correct as it stands).

It's possible that it's missing a #import <objc/runtime.h>.

Original comment by davedel...@gmail.com on 5 May 2010 at 4:44

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
static analyzer complains about memory leaks for generated classes after using 
this
patch.

Object with +0 retain counts returned to caller where a +1 (owning) retain 
count is
expected

this is in the -(id)initWithCoder:(NSCoder *)decoder function

Original comment by newk...@gmail.com on 19 May 2010 at 9:04

GoogleCodeExporter commented 9 years ago
Ahhhhh the problem is the performSelector:withObject: code path.  I put that in 
there to avoid a potential 
compiler warning about super not responding to initWithCoder:, but it's 
probably OK to just do [super 
initWithCoder:decoder]; instead of using the performSelector:withObject: method.

Original comment by davedel...@gmail.com on 19 May 2010 at 5:17

GoogleCodeExporter commented 9 years ago
Could you provide an updated patch please?
This is a useful feature and I'd like to get it in, assuming it doesn't break 
things. :)
Thanks.

Original comment by hasse...@gmail.com on 19 May 2010 at 5:44

GoogleCodeExporter commented 9 years ago
I just added the patch in with a couple of changes, revision 168.

I used [(id)self initWithCoder:decoder] which is cleaner than your original 
patch. I also put in the objc runtime 
include in Schema.h

Original comment by hasse...@gmail.com on 26 May 2010 at 10:32

GoogleCodeExporter commented 9 years ago
when compiling with the LLVM the addition of the (id) casting causing 
compilation failure.

Error received is "cannot cast super"

removing the casting allows successful compilation

Original comment by newk...@gmail.com on 23 Jul 2010 at 8:57

GoogleCodeExporter commented 9 years ago
Hi all,

I've a problem with the line

  if (value == nil) { value = [NSNumber numberWithFloat:0.0]; }

in the

  - (id) initWithCoder:(NSCoder *)decoder  

method.

Actually if the archived attribute is nil, unarchived object will contain a 
NSNumber with float 0.
In my case the attribute is a NSDate, so it should remain nil.

I've commented out the line and it works fine for me.

Let me known if that I've missed something.

Thanks

Original comment by davide.r...@gmail.com on 2 Jul 2012 at 7:24

GoogleCodeExporter commented 9 years ago
Another problem with NSCoding ...

If type1 extends type2, type2 is not coded into 

   - (void)encodeWithCoder:(NSCoder *)aCoder

because 

   [self isKindOfClass:[super class]] == TRUE

1) the 

   [super performSelector:@selector(initWithCoder:) withObject:decoder]

is never executed,

2) and

   Ivar * ivars = class_copyIvarList([self class], &numIvars);

doesn't get superclass ivars.

PROPOSED SOLUTION:

1) Check the superclass to perform [super encodeWithCoder:]

  if ([super respondsToSelector:@selector(encodeWithCoder:)] && ![self isMemberOfClass:[self superclass]] && [self isKindOfClass:[self superclass]] )

2) Don't get superclass ivars with class_copyIvarList([self class], &numIvars) 
but with static Class name, otherwise it gets subclass ivars:

   Ivar * ivars = class_copyIvarList([IWS_myClassName class], &numIvars);

If this makes sense, let me known.

Original comment by davide.r...@gmail.com on 2 Jul 2012 at 10:00

GoogleCodeExporter commented 9 years ago
Sorry,

the test 

  if ([super respondsToSelector:@selector(encodeWithCoder:)] && ![self isMemberOfClass:[self superclass]] && [self isKindOfClass:[self superclass]] )

is wrong, it loops.

I fixed rewriting the methods to cycle the class hierarchy, from the current 
class up to NSObject:

- (id) initWithCoder:(NSCoder *)decoder {

    self = [super init];
    if (self == nil) { return nil; }

    Class myClass = [self class];

    while (myClass && myClass != [NSObject class])
    {   
        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
        unsigned int numIvars = 0;
        Ivar * ivars = class_copyIvarList(myClass, &numIvars);
        for(int i = 0; i < numIvars; i++) {
            Ivar thisIvar = ivars[i];
            NSString * key = [NSString stringWithUTF8String:ivar_getName(thisIvar)];
            id value = [decoder decodeObjectForKey:key];
            [self setValue:value forKey:key];
        }
        if (numIvars > 0) { free(ivars); }

        [pool drain];

        myClass = [myClass superclass];
    }

    return self;
}
- (void) encodeWithCoder:(NSCoder *)encoder {

    Class myClass = [self class];

    while (myClass && myClass != [NSObject class])
    {
        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

        unsigned int numIvars = 0;
        Ivar * ivars = class_copyIvarList(myClass, &numIvars);
        for (int i = 0; i < numIvars; i++) {
            Ivar thisIvar = ivars[i];
            NSString * key = [NSString stringWithUTF8String:ivar_getName(thisIvar)];
            id value = [self valueForKey:key];
            [encoder encodeObject:value forKey:key];
        }
        if (numIvars > 0) { free(ivars); }

        [pool drain];

        myClass = [myClass superclass];
    }

}

Original comment by davide.r...@gmail.com on 2 Jul 2012 at 11:48