【问题标题】:Best practices, fire-and-forget asynchronous classes?最佳实践,即发即弃的异步类?
【发布时间】:2011-04-10 15:37:26
【问题描述】:

我有一个类,其唯一目的是从网上下载特定文件,将其存储在本地,然后返回存储文件的本地路径。

我根据我是否有相关文件的本地副本来使用这个类,如果需要下载多个文件,我有时会同时调用它多次。我的使用方式很简单

Loader *l = [[Loader alloc] initWithDelegate:self];
[l downloadFile:someFile];
[l release];

问题是,为了在下载完成之前保留它,我实际上是在课堂上做[self retain];,然后在完成后做[self autorelease];。不过,这感觉很hacky。人们如何处理这个问题?

【问题讨论】:

  • 我做过类似的事情,但我将 NSOperation 和 NSOperationQueue 包装在一个单例中。这种方法处理内存和线程。如果操作已经在进行中,我首先查询 OperationQueue,如果是我忽略请求,这样多次调用它不会产生多个线程或停止下载一半的文件。

标签: iphone objective-c ios asynchronous


【解决方案1】:

我同意[self release][self autorelease] 感觉很奇怪,但这并不意味着他们。在某些情况下,它们可能是正确的使用方式(我以前也使用过)。

但是,如果你想避免它们,你可以考虑创建一个 LoaderManager 类,它只拥有 Loader 对象,直到它们完成加载内容。它本质上是一个数组的包装器,您可以像这样(或其他方式)使用它:

@interface LoaderManager : NSObject {
  NSMutableSet *loaders;
}
@end
@implementation LoaderManager
- (id)init {
  self = [super init];
  if (self) {
    loaders = [[NSMutableSet alloc] init];
  }
  return self;
}
- (void)dealloc {
  [loaders release];
  [super dealloc];
}
- (void)addLoader:(Loader *)loader {
  [loaders addObject:loader];
}
@end

然后你的Loader 对象就可以了:

[myLoader downloadFile:someFile manager:aLoaderManager];

内部会简单地调用:

[aLoaderManager addLoader:self];

【讨论】:

  • 加载器管理器听起来是解决自保留问题的好方法。谢谢!
【解决方案2】:

在这种情况下,我认为您的 Loader 可以保留并自动释放自己。最方便的解决方案可能是在您的代码中添加一个详细的注释,解释它为什么这样做。最大的问题是 Loader 需要一个委托。委托人通常不会保留他们的委托以避免保留循环,但在这种情况下,委托似乎有可能在加载程序完成下载其文件之前被释放。如果发生这种情况,很可能会发生崩溃。因此,如果您想继续使用这种即发即弃的风格,您可能希望 Loader 保留其委托。

【讨论】:

  • 是的,很好。不久前我遇到了这个问题,并在代码中放入了代表在解除分配之前向所有当前“加载程序”发送中止消息的代码。
  • 将@Dave DeLong 的 LoaderManager 改为委托,您不必保留委托。如果创建 Loader 的类需要知道文件何时下载,您总是可以让 LoaderManager 发布通知。或者,完全跳过整个委托,让加载程序自己发布通知。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-09
  • 1970-01-01
  • 2011-02-16
  • 2011-08-12
  • 2013-02-02
  • 1970-01-01
相关资源
最近更新 更多