【问题标题】:Am I missing something with ARC?我错过了 ARC 的东西吗?
【发布时间】:2012-02-11 21:33:38
【问题描述】:

我正在使用 xcode 中的 ARC 为 iOS 5 开发一个大型应用程序。该系统似乎运行良好,除非我试图解除分配我的一个接口。我正在使用一个名为 WhirlyGlobe 的框架在第一个视图控制器中创建一个 3D 交互式地球。

当我切换视图控制器(在我拥有的 4 个视图控制器之间)时,我注意到用于带有地球的视图控制器的内存没有被释放。所有其他视图控制器(仅使用简单的视图和图像)都可以很好地释放它们的内存 - 但是地球保持常驻,或者看起来如此。当导航回地球时,由于“glsmLoadTextureLevelBuffer”中的 1mb 分配,我的内存几乎增加了 10mb。

继续我的问题 - 在激活 ARC 的情况下,我还能做些什么来帮助释放我的对象?我注意到我的 viewDidUnload 和 dealloc 方法根本没有被调用,我可以触发任何东西的唯一方法是使用 viewDidDisappear (这显然不理想) - 见下文:

- (void)clear
{
[[NSNotificationCenter defaultCenter] removeObserver:self];

if (self.layerThread)
{
    [self.layerThread cancel];
    while (!self.layerThread.isFinished)
        [NSThread sleepForTimeInterval:0.001];
}

self.glView = nil;
self.sceneRenderer = nil;

if (theScene)
{
    delete theScene;
    theScene = NULL;
}
self.theView = nil;
self.texGroup = nil;

self.layerThread = nil;
self.earthLayer = nil;
self.vectorLayer = nil;
self.labelLayer = nil;
self.interactLayer = nil;

self.pinchDelegate = nil;
self.panDelegate = nil;
self.tapDelegate = nil;
self.longPressDelegate = nil;
self.rotateDelegate = nil;
}

- (void)viewDidDisappear:(BOOL)animated {
    NSLog(@"dealloc - viewDidDisappear");
    [self clear];
}

我将不再需要的所有内容都设置为 nil。这是最好的做法吗?

地球设置代码: [超级viewDidLoad];

AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];

// Set up an OpenGL ES view and renderer
EAGLView *ev = [[EAGLView alloc] initWithFrame:CGRectMake(0, 0, 824, self.view.frame.size.height)];
self.glView = ev;
self.sceneRenderer = [[SceneRendererES1 alloc] init];
UIColor *whiteC = [UIColor whiteColor];
[sceneRenderer setClearColor:whiteC];
glView.renderer = sceneRenderer;
glView.frameInterval = 2;  // 60 fps (2)
[self.view addSubview:glView];
self.view.backgroundColor = [UIColor blackColor];
self.view.opaque = YES;
self.view.autoresizesSubviews = YES;
//glView.frame = self.view.bounds;
glView.frame = CGRectMake(275, GLOBE_HEIGHT_FIX, 768, SCREEN_HEIGHT+STATUS_BAR_HEIGHT); // was 260 x
glView.backgroundColor = [UIColor whiteColor];
self.view.backgroundColor = [UIColor whiteColor]; // red for debug

// Create the textures and geometry, but in the right GL context
[sceneRenderer useContext];

self.texGroup = [[TextureGroup alloc] initWithInfo:[[NSBundle mainBundle] pathForResource:@"bdGlobe_info" ofType:@"plist"]];

// Need an empty scene and view
theScene = new WhirlyGlobe::GlobeScene(4*texGroup.numX,4*texGroup.numY);
self.theView = [[WhirlyGlobeView alloc] init];
[theView setFarPlane:5.0];
[theView setHeightAboveGlobe:GLOBE_HEIGHT_VIEW];
if (globeShouldAnimate) glView.alpha = 1.0;

// Need a layer thread to manage the layers
self.layerThread = [[WhirlyGlobeLayerThread alloc] initWithScene:theScene];

// Earth layer on the bottom
self.earthLayer = [[SphericalEarthLayer alloc] initWithTexGroup:texGroup];
[self.layerThread addLayer:earthLayer];

// Set up the vector layer where all our outlines will go
self.vectorLayer = [[VectorLayer alloc] init];
[self.layerThread addLayer:vectorLayer];

// General purpose label layer.
self.labelLayer = [[LabelLayer alloc] init];
[self.layerThread addLayer:labelLayer];

self.interactLayer = [[InteractionLayer alloc] initWithVectorLayer:self.vectorLayer labelLayer:labelLayer globeView:self.theView
                                                       countryShape:[[NSBundle mainBundle] pathForResource:@"10m_admin_0_map_subunits" ofType:@"shp"]
                                                         oceanShape:[[NSBundle mainBundle] pathForResource:@"10m_geography_marine_polys" ofType:@"shp"]
                                                        regionShape:[[NSBundle mainBundle] pathForResource:@"10m_admin_1_states_provinces_shp" ofType:@"shp"]]; 
self.interactLayer.maxEdgeLen = [self.earthLayer smallestTesselation]/10.0;
[self.layerThread addLayer:interactLayer];

// Give the renderer what it needs
sceneRenderer.scene = theScene;
sceneRenderer.view = theView;

// Wire up the gesture recognizers
self.panDelegate = [PanDelegateFixed panDelegateForView:glView globeView:theView];
self.tapDelegate = [WhirlyGlobeTapDelegate tapDelegateForView:glView globeView:theView];
self.longPressDelegate = [WhirlyGlobeLongPressDelegate longPressDelegateForView:glView globeView:theView];

// Kick off the layer thread
// This will start loading things
[self.layerThread start];

【问题讨论】:

  • 您是否在您的应用程序上运行过泄漏工具?我的第一个想法是检查 WhirlyGlobe 是否有泄漏。
  • 我已经运行了泄漏工具 - 没有任何泄漏,每次打开地球部分时,只有 1mb 内存分配的巨大跳跃......如果我不应该释放整个部分m 弹出视图控制器并将其设置为零?
  • 您可以为此使用分配工具。使用堆快照,您可以在应用程序生命周期的各个点标记堆,并在每个快照点比较构成当前内存分配的对象图。这应该可以帮助您缩小保留的范围以及由谁保留。
  • @MarkAdams 如果你把它作为答案,我会赞成。这是我见过的关于堆射击的最清晰的迷你解释。
  • 谢谢马克,这是一个非常方便的技巧 - 我使用了堆镜头并复制了我正在做的事情。打开我提到的地球部分时,堆快照显示了 16mb 的堆增长,尽管这由 2x 2mb 分配和一大堆 1mb 分配到 glsmLoadTextureLevelBuffer 组成。我正在将地球视图作为子视图添加到视图控制器中,但即使我是,也有关系吗?我没有完全删除视图控制器的全部过程 - ARC 不应该随后删除它下面的所有内容吗?

标签: ios xcode memory-leaks automatic-ref-counting


【解决方案1】:

我在使用堆镜头后发现了问题(感谢 Mark Adams) - 结果我并没有让几个代理弱实体,所以在更改视图控制器时它们没有被释放。默认的强代表保持常驻。

感谢所有的建议,他们都帮助我指明了正确的方向:)

【讨论】:

  • 触摸地球或与地球交互现在崩溃(因为我将所有代表都转换为弱实体)... 将所有代表设置为 nil 是否可以接受?
【解决方案2】:

确保您的 -(void)viewDidDisappear:(BOOL)animated 被调用。

如果你使用

[self.view addSubview:yourViewController.view];

[yourViewController.view removeFromSuperview];

那么viewDidDisappear:viewDidAppear: 将不会被调用

这些回调只会被调用 当您在 IOS 5 中使用 presentViewController: 时 或presentModalViewController:dismissViewControllerAnimated: 在IOS 5 或dismissModalViewControllerAnimated: 或者使用UINavigationController 来展示和关闭你的viewController

【讨论】:

    【解决方案3】:

    您可以为此使用分配工具。使用堆快照,您可以在应用程序生命周期的各个点标记堆,并比较在每个快照点构成内存中当前分配的对象图。这应该可以帮助您缩小保留的范围以及由谁保留。

    【讨论】:

      【解决方案4】:

      这是轶事,但可能是类似的情况。

      我只是遇到了这样一种情况,即我的对象在 ARC 中从未被释放,即使它们以静态方式访问(例如,[SingletonThing instance].thing),因为自动释放池没有耗尽。其原因是一个奇怪的无限循环,它在自己的线程上运行。为封闭代码放置一个单独的 @autorelease 块。

      另一方面,即使您的一个(或库)对象具有 UIView 作为子视图,我认为您的 UIViewController 永远不会 @987654324 @,因此永远不会解除分配。我必须根据经验进行检查。

      【讨论】:

        猜你喜欢
        • 2017-10-19
        • 2021-03-14
        • 1970-01-01
        • 2010-09-06
        • 2019-09-23
        • 2018-01-08
        • 1970-01-01
        • 2015-07-15
        • 2010-10-17
        相关资源
        最近更新 更多