保留“自我”的坏习惯?
Posted
技术标签:
【中文标题】保留“自我”的坏习惯?【英文标题】:Bad-practice to retain 'self'? 【发布时间】:2010-10-17 13:36:06 【问题描述】:我有一个简单的问题想请人解决……保留自己是不是不好的做法?
我想要创建一个服务器请求对象。我希望能够以下列方式使用它:
ARequest *request = [ARequest request: someParam];
request.delegate = self;
[request begin];
为了让对象在自动释放池耗尽后不会自毁,我想我需要在它的 init 方法中调用一个保留,然后在收到服务器响应后释放,处理并传递给它委托。
但是,这种方法在我脑海中敲响了警钟。更好的方法?
【问题讨论】:
【参考方案1】:保留self
并没有错,只要你按照正常的内存管理协议在某个明确定义的点释放它。如果一个对象要求自己存在直到满足某些条件,它应该为此负责,就像它对任何其他需要继续存在的对象一样。
引入其他无关的管理器对象或出于迷信的原因将责任强加给对象的所有者将是这里真正的反模式。
(垃圾收集代码中的等效方法是让对象在结果未决时将自己从垃圾收集中排除,或者如果您不喜欢该想法,则通过某种收集将其根植。)
【讨论】:
【参考方案2】:这并非闻所未闻,但有些罕见。我看到它使用(并自己使用)的主要方式是当你处理某种半同步对象时(半同步我的意思是它不会阻塞主线程,但它也不会阻塞主线程)在后台线程上执行;NSURLConnection
符合此要求)。例如,我编写了NSWindowController
的子类,专门用于将窗口显示为工作表并用于调用某些特定的委托回调。基本上,您将 alloc
/init
一个新的工作表控制器并调用 beginSheetForWindow:
。这将半同步运行工作表,然后在工作表被关闭时调用适当的回调。
由于调用对象不一定“拥有”工作表(将其视为 ios 上模态视图控制器的 Mac 版本),工作表控制器在显示工作表之前立即执行 [self retain]
和 [self release]
在清理并调用回调后立即。这样做的目的是确保 controller 对象在工作表完成之前一直存在。 (工作表 IIRC 由 runloop 保留,但我还需要控制器保持不变)
就像我说的那样,您想[self retain]
的情况很少见,但这并非不可能。但是,作为一般经验法则,如果您认为需要 [self retain]
,您可能需要再考虑一下。
【讨论】:
【参考方案3】:最简单的方法是为您的请求创建一个 iVar,在您启动它时保留该请求,并在调用最后一个委托方法时释放它。
ARequest
是您创建的类吗?它会创建一个新线程来异步提交请求吗?
【讨论】:
是的,ARequest 基本上是一个创建 NSURLConnection 以异步提交请求的类。我可以使用 ivar,但我可能会同时发送几个请求,所以我必须维护某种请求的集合。然而,Apple 似乎使用了一种不需要维护这种类型的模式(例如 SKProductsRequest)。【参考方案4】:我曾经和你做过同样的事情。我在 NSString 上编写了一个 Category-Method 以将其发送到服务器,该服务器将打印它。在 Category-Method 中,我必须调用 [self retain]
,以便回调方法可以是 NSString-Categroy-Method。
我对此感到非常难过,以至于我重写了所有内容以使用由 Category-Method 访问的 Singleton。因此,Singleton 将根据需要保留字符串。
【讨论】:
是的,就是这样……出于某种原因,它确实感觉“不好”,但我想知道它是否真的如此?例如,Apple 在 SKProductsRequest 中以某种方式管理此问题,但它是通过 [self retain] 还是他们在某处维护一组未完成的请求?以上是关于保留“自我”的坏习惯?的主要内容,如果未能解决你的问题,请参考以下文章