ios - 我错过了 ARC 的东西吗?

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

我正在 xcode 中使用 ARC 为 iOS 5 开发一个大型应用程序。该系统似乎运行良好,除了当我试图取消分配我的接口(interface)之一时。我正在使用一个名为 WhirlyGlobe 的框架在第一个 View Controller 中创建一个 3D 交互式地球仪。

当我切换 View Controller (在我拥有的 4 个 View Controller 之间)时,我注意到用于地球 View Controller 的内存没有被释放。所有其他 View Controller (仅使用简单的 View 和图像)都可以很好地释放它们的内存 - 但地球保持常驻状态,或者看起来如此。当导航回地球时,由于在“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。这是最佳做法吗?

地球设置代码: [ super 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];

最佳答案

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

关于ios - 我错过了 ARC 的东西吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8888551/

相关文章:

ios/iphone 照片连拍模式 api

ios - 无法附加值并在 Collection View 中显示

objective-c 内存友好的背景图像方式

ios - 苹果 llvm 5.1 报错

iphone - UITable View 到详细 View 使用 AFNetworking 解析 JSON

ios - 调用 viewWillTransitionToSize : manually

iPhone 照片裁剪

ios - 我的导航栏出现在故事​​板中,但未出现在模拟器中

c# - 在 while 循环中调试 .NET 内存泄漏调用 StringBuilder.ToString()

iphone - 无法修复 Open AL 中的严重内存泄漏