【问题标题】:How do I repeat an ASIHTTPRequest?如何重复 ASIHTTPRequest?
【发布时间】:2011-06-03 01:06:40
【问题描述】:

给出下面的示例代码:

// ExampleModel.h

@interface ExampleModel : NSObject <ASIHTTPRequestDelegate> {

}

@property (nonatomic, retain) ASIFormDataRequest *request;
@property (nonatomic, copy) NSString *iVar;

- (void)sendRequest;


// ExampleModel.m

@implementation ExampleModel

@synthesize request;
@synthesize iVar;

# pragma mark NSObject

- (void)dealloc {
    [request clearDelegatesAndCancel];
    [request release];
    [iVar release];
    [super dealloc];
}

- (id)init {
    if ((self = [super init])) {
        // These parts of the request are always the same.
        NSURL *url = [[NSURL alloc] initWithString:@"https://example.com/"];
        request = [[ASIFormDataRequest alloc] initWithURL:url];
        [url release];
        request.delegate = self;
        [request setPostValue:@"value1" forKey:@"key1"];
        [request setPostValue:@"value2" forKey:@"key2"];
    }
    return self;
}

# pragma mark ExampleModel

- (void)sendRequest {
    // Reset iVar for each repeat request because it might've changed.
    [request setPostValue:iVar forKey:@"iVarKey"];
    [request startAsynchronous];
}

@end

# pragma mark ASIHTTPRequestDelegate

- (void)requestFinished:(ASIHTTPRequest *)request {
    // Handle response.
}

- (void)requestFailed:(ASIHTTPRequest *)request {
    // Handle error.
}

当我从UIViewController 执行[exampleModel sendRequest] 之类的操作时,它可以工作!但是,然后我从另一个 UIViewController 再次执行 [exampleModel sendRequest] 并得到:

Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '*** -[NSOperationQueue addOperation:]:
operation is finished and cannot be enqueued`

我该如何解决这个问题?

【问题讨论】:

    标签: iphone objective-c asihttprequest nsoperationqueue


    【解决方案1】:

    您不应尝试重用请求对象。它保持状态。真正设计为在请求结束后处理掉。

    该设计不像 NSURLConnection、NSURLRequest、NSURLResponse 类那样简洁(基本上将所有三者合二为一,并将底层核心基础类封装在下面)。如果您需要处理低级别的 HTTP 内容,它仍然比以普通方式使用 NSURLConnection 好得多。如果你不这样做,高级类有一些优势(比如访问 UIWebView 使用的相同缓存)。

    【讨论】:

    • 因此,我不建议将您的请求作为实例变量,因为它被设计为一次性的。如果您希望模型对象发出请求,但从控制器触发它(我认为您想要这样做),最好从控制器向模型发送通知并让侦听器调用 sendRequest。你仍然可以从控制器中传递一些东西,但你不太可能遇到问题。
    • @Alec Sloman,所以,如果我将请求设为局部变量并在 requestFinishedrequestFailed 回调中释放它,那么如果模型在其中任何一个之前是 dealloced 会发生什么回调被调用?那么,请求将永远不会被释放,对吗?这不是潜在的内存泄漏吗?
    • @MattDiPasquale 是的,完全正确。但我不知道为什么你会在你的请求完成之前允许你的模型被发布。您可以查询请求以查看它是否已完成。如果期望您的模型以您描述的方式发布,您可能会考虑处理该问题。
    • 如果你想释放你的模型,有一个 [request clearDelegatesAndCancel] 函数。我将我的请求设置为一个实例变量,但我在 requestFinished/requestFailed 回调中将其设置为 nil(因为它会自行处理)然后我在自己的 dealloc 中调用 [request clearDelegatesAndCancel] (如果它是 nil 则不会去任何地方)。我在一种情况下保留它。一个问题是,如果委托被释放并且它没有被取消,ASIHTTPRequest 将会崩溃(由于明显的原因它不会保留它)。对于积木,您需要同样小心。
    【解决方案2】:
    【解决方案3】:

    ASIHTTPRequest 及其子类符合NSCopying 协议。只需这样做:

     ASIFormDataRequest *newRequest = [[request copy] autorelease];
     [newRequest startAsynchronous];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多