我正在使用xcode中的ARC开发iOS 5的大型应用程序。除了当我试图释放我的一个接口时,系统似乎运行良好。我正在使用一个名为WhirlyGlobe的框架在第一个视图控制器中创建一个3D交互式地球仪。
当我切换视图控制器(在我有4个之间)时,我注意到用于带有globe的视图控制器的内存未被释放。所有其他视图控制器(仅使用简单的视图和图像)可以很好地释放内存 - 但是全球仍然保持驻留,或者看起来如此。当导航回地球时,由于“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];
}
我正在设置我不再需要的所有内容。这是最好的做法吗?
全球设置代码: [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];
答案 0 :(得分:3)
您可以使用分配工具。使用堆镜头,您可以在应用程序的生命周期中的各个点标记堆,并比较构成每个快照点内存中当前分配的对象图。这应该可以帮助你缩小保留的内容和由谁保留。
答案 1 :(得分:0)
这是轶事,但可能是类似的情况。
我只是遇到过我的对象在ARC中没有被释放的情况,即使它们是以静态方式访问的(例如[SingletonThing instance].thing
),因为自动释放池没有耗尽。原因是一个奇怪的无限循环,它在自己的线程上运行。为封闭代码添加单独的@autorelease
块。
另一方面,即使你的一个(或libs)对象有UIView
作为子视图, 我认为 你的UIViewController永远不会viewDidUnload
因此永远无法解除。我必须凭经验检查。
答案 2 :(得分:0)
确保调用-(void)viewDidDisappear:(BOOL)animated
。
如果您使用
[self.view addSubview:yourViewController.view];
和
[yourViewController.view removeFromSuperview];
然后不会调用viewDidDisappear:
和viewDidAppear:
只会调用这些回调
在IOS 5中使用presentViewController:
时
或presentModalViewController:
和IOS 5中的dismissViewControllerAnimated:
或dismissModalViewControllerAnimated:
或使用UINavigationController
来展示和解散你的viewController
答案 3 :(得分:0)
我在使用堆镜头后发现了这个问题(感谢Mark Adams) - 原来我没有让几个代表弱实体,所以在更改视图控制器时它们没有被释放。默认的强代表留在那里。
感谢所有的建议,他们都帮助我指出了正确的方向:)