注意:澄清我在这里要做的事情:
我有一个UIView子类的实例。当此实例从View Controller中释放时,我希望调用该实例的dealloc方法。
要点在UIView的子类的实例中释放其他对象。
在视图控制器中:
- (void)viewDidLoad
{
[super viewDidLoad];
self.mav = [[MapAreaView alloc]init];
[self.view addSubview:self.mav];
[self.mav release];
t_ = [NSTimer scheduledTimerWithTimeInterval: 20.0f target: self selector:@selector(onTick) userInfo: nil repeats:NO];
}
和
- (void)onTick
{
NSLog(@"Releasing...");
[t_ invalidate];
t_ = nil;
[self.mav release];
[self.mav release];
[self.mav release];
NSLog(@"Done releasing.");
}
在MapAreaView中:
- (void)dealloc
{
NSLog(@"map view area dealloc called.");
[super dealloc];
}
我正在尝试发布MapAreaView并调用它的dealloc方法。
此外,当我运行此应用时,Releasing...
和Done releasing.
会被打印,但不会map view area dealloc called
。尽管我将所有过多的释放消息发送到self.mav,但应用程序不会崩溃。怪异。
想法?
编辑1
@interface MemoryManagmentViewController : UIViewController {
MapAreaView *mav_;
NSTimer *t_;
}
@property (nonatomic, retain) MapAreaView *mav;
然后合成:@synthesize mav = mav_;
编辑2
请注意,计时器不适用于我的实际应用程序。我只是用它来学习内存管理。
答案 0 :(得分:2)
首先,请勿使用[self.mav release]
。这是对属性的错误使用,并不保证释放您的对象。请改用self.mav = nil
。
其次,我认为你的疯狂计时器只是试图强制释放你的视图,而不是你正在使用的代码?因为它真的不应该在那里!
要管理要保留指针并将其作为子视图添加到主视图的视图的内存,请从viewDidLoad中删除发布和计时器消息。您现在通过您的属性有一个保留指向mav
的指针,并且视图将保留它,因为它是子视图。
在viewDidUnload中,您的视图不再存在,因此它将不再具有指向mav
的指针。因此,如果您将self.mav = nil
放在那里,mav
将被释放。
当它仍然是另一个视图的子视图时,你不应该尝试释放它。
答案 1 :(得分:2)
您无法在dealloc
运行时选择
您不知道iOS框架中还有哪些内容会保留您的地图视图。
你应该考虑所有权方面的内存管理 - 当你想要一个对象时,确保你retained
它(明确地或作为一个属性),当你完成它时,请确保你释放它(通过致电release
,autorelease
或将您的财产设置为nil
来启动它。
你的地图视图最终会被释放,不要试图强迫它!
(并且在许多其他答案中已经说过,但它非常重要,所以在这里再次 - 不要拨打self.property release
,而是self.property = nil;
代替:)
*对于您自己编写的库中的对象来说并不完全正确,但对于来自第三方框架的对象(包括来自Apple的对象)来说肯定是正确的!
答案 2 :(得分:0)
该行:
[self.view addSubview:self.mav];
将保留self.mav
,并且应与onTick
中的此行配对。
[self.mav removeFromSuperview];
我不确定为什么你在onTick
中的过度释放不会释放self.mav
- 但如果你做了奇怪的事情,你可以保证会发生奇怪的事情。
答案 3 :(得分:0)
请勿再次在onTick
内发布。执行以下两个步骤:
[self.mavview removeFromSuperView];
self.mavview = nil;
就是这样。将不再有任何参考,因此将被解除分配。
答案 4 :(得分:-1)
首要的是 永远不要在self.iVar上发布释放
分配时不要使用用户self.iVar。
这些是内存管理的基本内容。