2012-01-17 99 views
0

我正在開發iOS 5的大規模應用程序,在xcode中使用ARC。除了當我試圖釋放其中一個接口時,系統似乎運行良好。我使用名爲WhirlyGlobe的框架在第一個視圖控制器中創建3D交互式地球儀。我是否錯過了ARC?

當我切換視圖控制器(我有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]; 
} 

我m設置我不再需要的所有零。這是最佳做法嗎?

全球設置代碼: [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]; 
+2

你在應用程序上運行泄漏儀器嗎?我的第一個傾向將是檢查WhirlyGlobe的泄漏。 – 2012-01-17 01:19:35

+0

我已經運行泄漏儀器 - 無論如何,每次全球部分打開時,只有1mb內存分配的巨大跳躍......如果我彈出視圖控制器並設置,整個部分不應該被釋放它爲零? – 2012-01-17 01:26:59

+4

您可以使用此分配工具。使用堆鏡頭,您可以在應用程序的生命週期中的各個點上標記堆,並比較構成每個快照點處內存當前分配的對象圖。這應該有助於縮小保留的內容和由誰來保存的內容。 – 2012-01-17 01:33:11

回答

3

您可以使用此分配工具。使用堆鏡頭,您可以在應用程序的生命週期中的各個點上標記堆,並比較構成每個快照點處內存當前分配的對象圖。這應該有助於縮小保留的內容和由誰來保存的內容。

0

這是軼事,但可能會有類似的情況。

我剛剛遇到了這樣的情況,即使它們是以靜態方式訪問(例如,[SingletonThing instance].thing),因爲autorelease池沒有耗盡,我的對象在ARC中仍然沒有被釋放。這個原因是一個奇怪的無盡循環,它運行在自己的線程上。爲封閉代碼單獨放置一個@autorelease塊。

在另一方面,即使你的(或庫)對象中的一個具有UIView作爲一個子視圖,我覺得 UIViewController中永遠不會viewDidUnload,因此從來沒有的dealloc。我必須根據經驗來檢查。

0

確保您的-(void)viewDidDisappear:(BOOL)animated被調用。

如果使用

[self.view addSubview:yourViewController.view];

[yourViewController.view removeFromSuperview];

然後viewDidDisappear:viewDidAppear:將不會被調用

當您使用這些回調只會被調用 在IOS 5 或presentModalViewController:dismissViewControllerAnimated:在IOS 5 或dismissModalViewControllerAnimated: 或使用UINavigationController提出並解散你的viewController

0

我發現這個問題使用堆鏡頭(感謝馬克·亞當斯)之後 - 原來我沒」不會讓一些代表弱實體,所以在更改視圖控制器時不會被釋放。默認強壯的代表保持居民身份。

感謝所有的建議,他們都幫助我指出了正確的方向:)

+0

觸摸或與全球互動現在崩潰(因爲我將所有代表轉換爲弱實體)......只是將所有代表設置爲零可以接受嗎? – 2012-01-19 00:42:40