2010-09-14 79 views
2

我有一个关于覆盖自动生成存取器方法的问题。以下将无法工作(我相信),因为每个getter引用另一个getter。有没有一个规则,访问器方法不应该使用其他访问器方法,或者你只需​​要单独注意这些情况?访问器/获取器和延迟初始化

-(UIImage *) image{ 

    if(image == nil){ 
     if(self.data == nil){ 
      [self performSelectorInBackground: @selector(loadImage) withObject: nil] 
     }else{ 
      self.image = [UIImage imageWithData: self.data]; 
     } 
    } 

    return image; 
} 

-(NSData *) data { 

    if(data == nil){ 
     if(self.image == nil){ 
      [self performSelectorInBackground: @selector(loadData) withObject: nil] 
     }else{ 
      self.data = UIImageJPEGRepresentation(self.image, 0.85); 
     } 
    } 

    return data; 
} 

我要强调的是,这里所呈现的图像的使用是一个例子,关于如何在这个特殊的例子做的想法是不是在一般情况下不太重要。

回答

3

首先,不要为自己的利益太聪明。如果你想克服一些瓶颈,首先要测量并确定它确实存在。我相信UIImageNSData都会进行一些内部延迟加载,因此您的代码可能本质上是无用的。其次,即使你真的想手工做这样的事情,试着将缓存代码分成一个单独的类,这样你就不会污染主类的代码。

没有关于访问器的规则(至少没有我知道的),因为人们不会在访问器中执行很多延迟加载。有时我会陷入由懒惰[UIViewController loadView][UIViewController view]组合引发的无限循环,但就是这样。

2

没有什么可以禁止它,但你绝对是写一些混淆的代码。实质上,这两个属性具有循环依赖性。这很难读取和调试。目前尚不清楚为什么在“加载图像”之前你想“加载数据”,或者你为什么还想在“加载数据”之前支持“加载图像”,或者真的如何将这两个属性实际上是两回事。

+0

它是循环的事实是我的问题源于。 – 2010-09-14 07:15:46

0

您在本示例中实际执行的操作可能需要很长时间才能加载;最好确保它是线程安全的。另外,如果你将数据对象作为一个真正的数据提供者(通常使用协议),从类中分离出来,并使图像容器公开它正在处理一个延迟加载的对象(这可能会引起一些人的强烈抗议)。具体来说,您可能需要从提供者调用加载数据/图像,并从awakeFromNib调用它(例如) - 然后加载程序运行并将数据加载到辅助线程(尤其是如果下载)。给数据提供者一个回调通知视图图像已准备就绪(通常使用协议)。一旦视图获取未存档的图像,则使数据提供者无效。

最后,如果你正在处理应用程序资源,那么'系统'会为你缓存一些这样的内容,所以你会试图对付已经在幕后优化的内容。简而言之,它通常是可以的(例如,不是懒惰的初始化) - 但是这个特定的设计(如另一张海报所说)具有应该最小化的循环依赖性。

+0

谢谢,我的意思是不停止线程的功能 - 我已经更新了示例以分离出后台线程(他们可能会在完成时发出回调或通知) – 2010-09-14 07:38:43

+0

pt1:关于更新:实际上最好是让数据提供者执行后台加载。在你的例子中,任何简单的成员访问都可以创建一个新的线程(也就是说,直到数据准备就绪)。所以最好让数据提供者根据它是否为NotRequested,Fetching,Loaded来跟踪模式(以及线程安全) - 然后在图像不可用时调用数据提供者来加载图像。如果它是NotRequested,则在后台开始加载,如果Fetching或者断言,则忽略该请求,因为数据应该在获取后传递。 – justin 2010-09-15 06:36:54

+0

pt2:锁定回调/访问。随着你使用的结构,你可能最终会创建一个每个访问的后台请求 - 这可能意味着你要求多个后台加载并在每次访问时创建一个新线程==你最终可能会有12个(或更多)线程告诉数据提供者加载数据。 – justin 2010-09-15 06:40:40