2013-05-07 19 views
9

私はActivityDetailViewと呼ばれるカスタムUIViewをインスタンス化し、親ビューコントローラ内のスクロールビューに追加しました。このカスタムビューが割り当てられると、メモリが追加されるたびに約1MBのメモリが消費され、ビューと親ビューコントローラにはそれぞれdeallocメソッドが呼び出されてもメモリが解放されないことが表示されます。私はメモリの警告を受け取り、アプリケーションが最終的に殺されてしまっているので、明らかに何か間違っています。メモリがMKMapView/ARCで解放されていません

が原因で、マップビューについての情報/ wを更新しましたが、私はカスタムActivityDetailView nibファイル内で修正

を必要とし、ズームやユーザーの位置を中心とするマップビューがあります。このマップビューをペン先から削除して画面上に描画しないようにすると、メモリ割り当ての問題が解消されました。しかし、私は明らかにマップビューが必要です。マップビューが範囲外になったときにマップビューのデータが解放されないのはなぜですか?

ビューが表示されているときには、1つだけActivityDetailViewと1 ActivityDetailViewControllerがあります。私がスタックからビューをポップするとすぐに、彼らはもはや生きていません。インストゥルメントで示されているようにオブジェクトが強制終了されても、メモリがどのくらい増え続けるかはわかりません。親ビューの割り当てを解除すると、マップビューのデータが割り当て解除されないのはなぜですか?

私は間違っていますか、何を確認すればよいですか?ここ

カスタムビューである:親ビューコントローラで

@interface ActivityDetailView() 
{ 
    CLLocation *location; 
    __weak id parentViewController; 
    int scrollViewX; 

    ImageUtility *imageUtility; 
} 
@end 

@implementation ActivityDetailView 

-(id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) 
    { 
     NSArray *xibViews = [[NSBundle mainBundle] loadNibNamed:@"ActivityDetailView" owner:nil options:nil]; 
     if ([xibViews count] < 1) return nil; 
     ActivityDetailView * xibView = [xibViews objectAtIndex:0]; 
     [xibView setFrame:frame]; 
     self = xibView; 
    } 
    return self; 
} 

- (id)initWithLocation:(CLLocation *)loc parentController:(id)parent 
{ 
    self = [self initWithFrame:CGRectMake(0, 0, 320, 1000)]; 
    if (self) 
    { 
     imageUtility = [ImageUtility sharedManager]; 

     location = loc; 
     parentViewController = parent; 
     scrollViewX = 0; 

     [self centerMapForActivityLocation]; 
     [self addPhotoButtonWithImageNamed:@"addActivityPhoto.png" target:parentViewController selector:@selector(addPhotoToActivity:)]; 
    } 
    return self; 
} 

- (void)dealloc 
{ 
    NSLog(@"ActivityDetailView was dealloced"); 
} 

@interface ActivityDetailViewController() 
{ 
    ActivityDetailView *detailView; 
} 
@end 

@implementation ActivityDetailViewController 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    // Some code left out for clarity 

    [self setupView]; 
} 

- (void)didReceiveMemoryWarning 
{ 
    NSLog(@"Purging image cache"); 
    [[ImageUtility sharedManager] purgeCache]; 
} 

- (void)dealloc 
{ 
    // These essentially do nothing to help the problem 
    detailView.mapView = nil; 
    [detailView removeFromSuperview]; 
    detailView = nil; 
    self.scrollView = nil; 

    NSLog(@"ActivityDetailViewController was dealloced"); 
} 

- (void)setupView 
{  
    // Add the activity detail view to the scroll view 
    detailView = [[ActivityDetailView alloc] initWithLocation:self.activityLocation parentController:self]; 
    [self.scrollView addSubview:detailView]; 
    self.scrollView.contentSize = detailView.frame.size; 

    // Setup the map view 
    detailView.mapView.delegate = self; 
    MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init]; 
    annotation.coordinate = self.activityLocation.coordinate; 
    [detailView.mapView addAnnotation:annotation]; 
    if (self.activity.mapImageName) { 
     detailView.mapView.scrollEnabled = YES; 
     detailView.mapView.zoomEnabled = YES; 
    } else { 
     detailView.mapView.scrollEnabled = NO; 
     detailView.mapView.zoomEnabled = NO; 
    } 

    // Add the weather area to the view 
    dayView = [[DailyButtonView alloc] initWithFrame:CGRectMake(0, -17, 60, 70)]; 
    dayView.hidden = YES; 
    [detailView.weatherView addSubview:dayView]; 
} 

ここでメモリの大部分がニブローディング

からのものであることを示すインスツルメンツから画像ですInstruments screenshot

私には何もないgを現時点でキャッシュする。ビューは基本的にスクロールビューであり、その内部にはマップビューといくつかのラベルといくつかのテーブルビューがあります。テーブルビューには何も入力されていません。スクロールビューの背景イメージ以外のビュー内のイメージはロードされませんが、ビューが終了すると解放されます。

+1

これが問題であるかどうかはわかりません(そうではありません)。しかし、これらの2行のコードは間違っています。detailView = nil; [detailView removeFromSuperview] ;. removeFromSuperViewを呼び出すと、それ以降はnilに設定する必要があります。 – Cosmin

+0

@コスミンよく、私はそれが別のビューに追加されている場合deallocになることはありません問題はないと思う...私は私のOPはちょうど試していたと推測して、それを残しました –

+0

@コスミンAs Grady私はそれが違いを生み出したかどうかを確認するために、その時点で何かを試していただけですが、そうではありませんでした。 – ZeNewb

答えて

22

明らかになったように、iOS 6とMKMapViewで正しくメモリを解放していない既知のバグがあります。残念ながら、メモリを解放することに大きな影響を与えないキャッシュをパージするようにマップビューに強制しようとする以外には、実際の修正はありません。

奇妙なことは、アプリケーションがメモリ警告を受け取っていても、マップビューのキャッシュがまだ正しくパージされていないことです。最終的に、アプリケーションは不安定になり、OSによって殺されます。

アップルは最近、テストで非常にうんざりしています。これはMKMapViewの2番目のバグです(もう1つはmapViewDidFinishLoadingMap:と呼ばれています)。両方のバグは、パフォーマンスと健全性のテストを行ったばかりの場合、本当に明らかです。ここで

助けるかもしれないいくつかのコードです:

- (void)viewDidDisappear:(BOOL)animated 
{ 
    [super viewDidDisappear:animated]; 

    // This is for a bug in MKMapView for iOS6 
    [self purgeMapMemory]; 
} 

// This is for a bug in MKMapView for iOS6 
// Try to purge some of the memory being allocated by the map 
- (void)purgeMapMemory 
{ 
    // Switching map types causes cache purging, so switch to a different map type 
    detailView.mapView.mapType = MKMapTypeStandard; 
    [detailView.mapView removeFromSuperview]; 
    detailView.mapView = nil; 
} 

あなたができる他の事はあなたの全体のアプリを通じてMKMapViewの1つのインスタンスを使用し、そのたびにビューを割り当てられているどのくらいのメモリ最小限に抑える必要がありますマップビューはすでに割り当てられているため、表示されます。

+0

新しい提案を毎回alloc/deallocするのではなく、MKMapViewの1つのインスタンスを使用することをお勧めします。私も同様の問題が発生しています...このバグがiOS 9以降で修正されているかどうかはわかりますか? –

+1

@ AdamW.Dennis私は2,3年前にアップルマップで作業していませんでしたので、OpenRadarまたはアップルのデベロッパーフォーラムで詳細情報を確認することができます。 https://openradar.appspot.com/search?query=mkmapview+memory – iwasrobbed

0

これは本当にあなたのnibファイルからカスタムビューを作成する最良の方法ではありません。私がお勧めするのは、.nibファイルから取得したビューをサブビューとして自己に追加することです。コードは次のようになります。

-(id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) 
    { 
     NSArray *xibViews = [[NSBundle mainBundle] loadNibNamed:@"ActivityDetailView" owner:nil options:nil]; 
     if ([xibViews count] < 1) return nil; 
     ActivityDetailView * xibView = [xibViews objectAtIndex:0]; 
     [xibView setFrame:frame]; 
     [self addSubview:xibView]; // This is where I have changed your code 
    } 
    return self; 
} 
+0

残念ながら、これはメモリ割り当てのために何の違いもありません。 – ZeNewb

+0

しかし、あなたは彼が何を言っているのかを考えなければなりません。常に助けてください。 –

0

おそらくキャッシュに問題があります。

多量の画像を使用している場合は、この画像をxibから削除し、コードを使用して追加することをお勧めします。私はあなたがあなたのテーブルとも他の機能を起動する方法を知っておく必要があり、より良い支援すること

NSData* dataImg = [NSData dataWithContentsOfFile:@"yourfile.png"]; 
UIImage* img = [UIImage imageWithData:dataImg]; 

:それとも、[UIImage imageNamed:@""]

を使用して画像を読み込むしかし、そのようなものを使用している場合。

+0

私は現時点でキャッシュするものはありません。ビューは基本的にスクロールビューであり、その内部にはマップビューといくつかのラベルがあります。テーブルビューには何も入力されていません。スクロールビューの背景イメージ以外のビュー内のイメージはロードされませんが、ビューが終了すると解放されます。 – ZeNewb

+0

Nop、あなたがビューに追加した画像、imagenamedを使った画像、またはxibからの画像はキャッシュされ、ときどきアプリケーションがクラッシュする可能性があります。 – ggrana

+0

背景画像はペン先で追加され、それはアプリの残りの部分で使用されているものと同じ背景画像なので、これは問題ではないと思います。他のビューには割り当て問題はありませんが、これだけは問題ありません。 – ZeNewb

関連する問題