1

iOS 6 でマップにピンをドロップする方法を学習しようとしています。コンパイルして実行するコードがありますが、明らかにメモリ リークが発生しますが、mapData オブジェクトを解放 (または autoRelease) すると、アプリがクラッシュします。エラーは

キー値オブザーバーがまだ登録されている間0x1b7ac0に、クラスのインスタンスの割り当てが解除されました。AddressAnnotation観測情報が漏洩し、他の天体に誤って付着する可能性さえあります。NSKVODeallocateBreakデバッガーでここで停止するようにブレークポイントを設定します。

MapKit に関しても、このエラーに関する以前の投稿があります:
NSKVODeallocateBreak でブレークポイントを設定する

しかし、それは私には役に立ちません:
まず、私は答えをよく理解していませんが、オブザーバーを設定していないため (私が知っていることです!)たとえば、コードのどこにも行がありません

[addressAnnotation addObserver:self forKeyPath:kSelectedAnnotationObserverKeyPath options:NSKeyValueObservingOptionNew context:@"selectedOrDeselected"];

または、問題であると示唆された、リモートで類似したもの。

そうは言っても、私はオブザーバーの概念を本当に理解していないと言わなければなりません-もちろん、カスタムクラスを作成しましたMapDataが、これは NSObject <MKAnnotation>問題の原因でもあると思います. しかし、私は基本的に頭がおかしいです。

提案されたシンボリック ブレーク ポイントを設定しようとしましたが、役に立ちませんでした。BAD ACCESS状態があることはわかりますが、それが本当に理解していることのすべてです。

私が書いたコードはこれです:

- (void) showRecordsOnMap
{
    NSMutableArray *projectMapAnnotationsArray;
    projectMapAnnotationsArray = [[NSMutableArray alloc] init];

    int i = 0;
    for (i = 0; i < [currentProject.recordArray count]; i++)
    {
        Record *record = [[[Record alloc] init]autorelease];
        record = [currentProject.recordArray objectAtIndex:i];

        CLLocationCoordinate2D newCoordinate;
        newCoordinate.latitude = record.latitude;
        newCoordinate.longitude = record.longitude;
        int tag = 0;
        NSString *title;
        title = [[[NSString alloc] init] autorelease];
        title =  [NSString stringWithFormat:@"Record %d",record.record_ID];
        NSString *subtitle;
        subtitle = [[[NSString alloc] init] autorelease];
        subtitle =  [NSString stringWithFormat:@"Record %d",record.record_ID];

        MapData *mapData =[[MapData alloc] initWithCoordinate:newCoordinate withTag:tag withTitle:title withSubtitle:title];

        [projectMapAnnotationsArray addObject:mapData];

        //[mapData release];

    }

    [projectMap addAnnotations:projectMapAnnotationsArray];
    [projectMapAnnotationsArray release];

}

そして次に必要なビット

- (MKAnnotationView *) mapView:(MKMapView *)mapView
             viewForAnnotation:(MapData *)annotation
{       
    static NSString *record = @"record";

    //the result of the call is being cast (MKPinAnnotationView *) to the correct
    //view class or else the compiler complains
    MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[projectMap
                                                                  dequeueReusableAnnotationViewWithIdentifier:record];
    if(annotationView == nil)
    {
        annotationView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:record] autorelease];
    }

    //if((annotation).tag == 2) annotationView.pinColor = MKPinAnnotationColorRed;
    //else annotationView.pinColor = MKPinAnnotationColorGreen;

    annotationView.pinColor = MKPinAnnotationColorGreen;
    //pin drops when it first appears
    annotationView.animatesDrop=TRUE;

    //tapping the pin produces a gray box which shows title and subtitle
    annotationView.canShowCallout = YES;

    return annotationView;
}

このコードは、mapData オブジェクトが解放されない限り実行されます。しかし、明らかに私はそれを解放する必要があります。別の手がかりとして、コメントを外すと

// if((annotation).tag == 2) annotationView.pinColor = MKPinAnnotationColorRed;
// else annotationView.pinColor = MKPinAnnotationColorGreen;

別のエラーが発生します:

[MKUserLocation タグ]: インスタンス0x9fcb010 2013-05-22 23:05:13.726 Geo360[1175:c07] に'NSInvalidArgumentException'認識-[MKUserLocation tag]:されないセレクターが送信されました0x9fcb010

しかし、この 2 番目のエラーは、少なくとも見つけ方を知っている私の単純な愚かさのように思えます。しかし、「クラスAddressAnnotation」というエラーにより、私は完全に失われました。どんな助けでも大歓迎です!


編集:

こんにちは -- お時間を割いていただきありがとうございます。私はまだ混乱しています。AnnaKarenina によって提案された MapData オブジェクトのコードが添付されています。Verbumdei は、配列を ViewDidLoad メソッドに強力なプロパティとして配置することを提案しました。それで遊んだことがありますが、データが多いか少ないかの配列でマップ ピンを更新できるようにしたいので、私にはそう見えました。毎回アレイを新しく作成する必要がありました。おそらくそうではありませんか?AnnaKarenina は、MapData にリリースの問題がある可能性があることを示唆しており、今見てみると、タグをリリースしていないのではないかと少し疑っていますが、リリースすると警告が生成されます!

助けてくれてありがとう...まだ解決されていません。

MapData.h :

#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>

@interface MapData : NSObject <MKAnnotation>
{
    NSString *_title;
    NSString *subtitle;
    NSUInteger tag;
    CLLocationCoordinate2D _coordinate;
}

@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *subtitle;
@property(nonatomic) NSUInteger tag;
// Getters and setters

- (id)initWithCoordinate:(CLLocationCoordinate2D)c withTag:(NSUInteger)t withTitle:(NSString *)tl withSubtitle:(NSString *)s;
@end

およびMapData.m :

#import "MapData.h"

@implementation MapData

@synthesize coordinate;
@synthesize title;
@synthesize subtitle;
@synthesize tag;

-(id)initWithCoordinate:(CLLocationCoordinate2D)c withTag:(NSUInteger)t withTitle:(NSString *)tl withSubtitle:  (NSString *)s
{
    if(self = [super init])
    {
        coordinate = c;
        tag = t;
        title = tl;
        subtitle = s;
    }
    return self;        
}

- (void) dealloc
{
    [title release];
    [subtitle release];
    [super dealloc];
}

@end
4

2 に答える 2

0

注釈がマップに表示されている間は、MapData オブジェクトを解放しないでください。MapData オブジェクトを解放する場合は、最初に注釈をマップから削除する必要があります。

projectMapAnnotationsArray をビュー コントローラーの強力なプロパティとして作成することをお勧めします。メソッドで割り当てviewDidLoadます。dealloc次に、View Controllerのメソッドでそれを解放するだけです。

メソッド内ではshowRecordsOnMap、配列自体を解放せずにオブジェクトを projectMapAnnotationsArray に追加するだけです。

于 2013-05-23T00:08:47.207 に答える