我一直在我的应用程序中进行春季大扫除。我注意到一些奇怪的事情,当我试图纠正它时,完全崩溃我的应用程序。
我的应用中有两条“路径”;要么你在“A”部分,要么你在“B”部分。从“A”部分,您可以转到“B”部分,反之亦然。
我设计了它,以便app委托类有两种方法; switchToAView
和switchToBView
因此,在BView
的中间并在应用委托上调用switchToAView
方法应该完全释放与BView
相关的所有内容并将用户发送到AView
}。
我在切换到AView
时发现BView
视图仍然保留。
每个视图都由一个属性持有。
interface;
@property(nonatomic, retain) UIView *viewA
@property(nonatomic, retain) UIView *viewB
implementation;
@synthesize viewA, viewB
我在两个视图的dealloc方法中放了一个断点。 (viewA
和viewB
)。
现在这发生了;
加载viewA
并从那里切换到viewB
时,不会释放任何内容(按预期方式)。然后当我从viewB
切换到viewA
时,viewA
首先被释放(由生成的setter,据我所知)。
然后初始化并显示viewA
。
这种方法很好但有一个缺点,即viewA
和viewB
同时在堆栈上存活:/这是不可取的,因为它们是互斥的。 viewA
仅在新viewA
出现时发布,但viewA
应在viewB
添加到窗口时发布
然后我尝试在viewA
方法中发布switchToBView
。
从viewA
到viewB
时,这种方法很有效。我检查了仪器,viewA
的保留计数降为0。现在当切换回viewA时,应用程序崩溃了,我认为这是因为:
self.viewA = newlyInstantiatedViewA;
setter,首先向viewA发送一条释放消息,但我之前发布了viewA,这导致崩溃。
我无法理解这种方式使用setter会导致崩溃。 (“发送到deallocated instance的消息”并在调用[super dealloc]时添加到A的最后一个子视图的dealloc方法中断)
我应该一起选择不同的方法吗? 我将如何构建坚固的东西,确保一次只保留一个视图?
对于冗长的写作感到抱歉,如果我有更多时间,我会写得更少: 提前感谢您提出任何解决方案或设计建议:)
答案 0 :(得分:4)
我应该选择不同的 一起接近?
很明显,您将视图控制器逻辑混合到视图中,并且您可以在看似循环引用的内容中相互保持视图。
(1)视图不应具有加载其他视图的逻辑。加载和卸载视图是视图控制器的功能。视图应仅关注与显示器直接相关的逻辑。它甚至不应该存储或操纵任何用户数据。
(2)视图控制器应该很少调用其他视图控制器。视图控制器应该关注管理视图以及从视图读取和写入数据到数据模式。
(3)如果需要关联视图,请使用UINavigation控制器。它不仅仅适用于严格的视觉分层视图模式。另外,您可以隐藏导航栏,以便用户永远不会看到它。你需要有一个推动viewA的视图控制器,当你需要viewB时,调用nav来弹出viewA并推送viewB。对于用户来说,看起来就像是简单地交换视图。有关类似用法,请参见实用程序翻转视图。
您的应用程序暂时有效,因为语言或API中没有任何内容阻止您将几乎整个应用程序逻辑塞入视图子类。然而,保持这样的设计运行和可靠几乎是不可能的。