1
votes

It will be probably a simple problem, but I have been staring on this for a while now and I can't find it!

I have a SOAPRequest class like following:

@interface SoapRequest : NSObject

@property (retain, nonatomic) NSURL *endPoint;
@property (retain, nonatomic) NSString *soapAction;
@property (retain, nonatomic) NSString *userName;
@property (retain, nonatomic) NSString *passWord;
@property (retain, nonatomic) NSString *postData;
@property (retain, nonatomic) NSObject *handler;
@property SEL action;

+ (SoapRequest*) create: (NSObject*) target endPoint: (NSString*) endPoint action: (SEL) action soapAction: (NSString*) soapAction postData: (NSString*) postData;

- (id)sendSynchronous;
- (void) send;

@end

Implementation like following:

@synthesize endPoint = _endPoint, soapAction = _soapAction, userName = _userName, passWord = _passWord, postData = _postData, action = _action, handler = _handler;

+ (SoapRequest*) create: (NSObject*) target endPoint: (NSString*) endPoint action: (SEL) action soapAction: (NSString*) soapAction postData: (NSString*) postData
{
    SoapRequest *request = [[SoapRequest alloc] init];
    request.endPoint = [NSURL URLWithString:endPoint];
    request.soapAction = soapAction;
    request.handler = target;
    request.action = action;
    request.postData = postData;

    return [request autorelease];
}

And my send function:

- (void) send
{
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:self.endPoint];
    [request setDelegate:self];

    [request addRequestHeader:@"Content-Length" value: [NSString stringWithFormat:@"%d",[self.postData length]]];
    [request addRequestHeader:@"Content-Type" value:@"text/xml"];

    if(self.soapAction)
    {
        [request addRequestHeader:@"soapAction" value:self.soapAction];
    }

    [request appendPostData:[self.postData dataUsingEncoding:NSUTF8StringEncoding]];
    [request startAsynchronous];
}

I do have the default ASIHTTPRequest methods to listen for error or finish, my finish looks as following:

- (void)requestFinished:(ASIHTTPRequest *)request
{
    [self.handler performSelector:self.action];
}

The case is, it crashes when I want to make this class a delegate for the ASIHTTPRequest, [request setDelegate:self]. I figured it has something to do with the Autoreleasing in the first function. But I don't have any idea how to fix it!

Edit:

This is how I init my SoapRequest:

- (SoapRequest*) DefinedEntities: (id) _target action: (SEL) _action
{

// some data inits

    SoapRequest *request = [SoapRequest create: _target endPoint:endPoint action:_action soapAction:soapAction postData:xmlString];
    [request send];

    return request;
}

And this i init as following:

Metadata *service = [[Metadata alloc] init];
[service DefinedEntities:self action:@selector(MetadataFinished:)];
4
Please run your app in the debugger with NSZombies enabled, and add into youe question a stack trace for the first call to an invalid object.JosephH
What happens when you replace 'return [request autorelease]' with 'return request'?dragonfly
Then it works, i already know this.Wesley

4 Answers

6
votes

Had the same problem like you. The problem is, it gets deallocated before the delegate method gets called. Simply put a retain in your start method and a release in your finished method (and don't forget to release it in the error methods). This will let the object at life as long as the request is performing.

1
votes

Please post the code where you're creating the instance of a SOAPRequest object using:

+ (SoapRequest*) create: (NSObject*) target endPoint: (NSString*) endPoint action: (SEL) action soapAction: (NSString*) soapAction postData: (NSString*) postData;

You may need to retain it. As an aside, you should use 'id' instead of NSObject* for your target parameter, as your target will not be an instance of NSObject (it will be a subclass) of sorts.

1
votes

If the crash only occurs when you set self (SOAPRequest) as the delegate, are you sure that self isn't being deallocated (then the bad access occurs when the ASIHTTPRequest calls the did finish on its delegate which no longer exists).

- (SoapRequest*) DefinedEntities: (id) _target action: (SEL) _action
{

// some data inits

    SoapRequest *request = [SoapRequest create: _target endPoint:endPoint action:_action soapAction:soapAction postData:xmlString];
    [request send];

    return request;
}

When you do this, request is autoreleased and you should make sure it is retained by someone until the ASIHTTPRequest it sent has finished or failed.

0
votes

Retaining was indeed a good option, I found some typo's in my code and figured out what i did wrong already.

I had to do with the class in-between:

- (SoapRequest*) DefinedEntities: (id) _target action: (SEL) _action
{

// some data inits

    SoapRequest *request = [SoapRequest create: _target endPoint:endPoint action:_action soapAction:soapAction postData:xmlString];
    [request send];

    return request;
}