В проблеме с удержанием NSMutableArray - PullRequest
0 голосов
/ 04 ноября 2011

У меня была эта проблема уже пару дней, я много гуглил, но ничего полезного не нашел, поэтому подумал спросить здесь.У меня проблема с хранением NSMutableArray, однако я не могу понять, где проблема и как ее исправить.Я рисую линейную диаграмму с использованием Quartz 2D, и для этого я создал подкласс UIView с GraphView.Заголовок выглядит так:

@interface GraphView : UIView {
    NSMutableArray *data;
}

- (void)drawBar:(CGRect)rect context:(CGContextRef)ctx;
- (void)drawLineGraphWithContext:(CGContextRef)ctx;
- (void)addValue:(float)value;

@property(nonatomic, retain) NSMutableArray *data;

@end

Я использую массив «data» для хранения точек данных для рисования в методе drawLineGraphWithContext:.С другой стороны, метод addValue: используется в главном контроллере для заполнения массива данных.В viewDidLoad контроллера я заполняю массив данных:

graphView = [[GraphView alloc] init];

float data[] = {0.7, 0.4, 0.9, 1.0, 0.2, 0.85, 0.11, 0.75, 0.53, 0.44, 0.88, 0.77, 0.99, 0.55};

for(int i = 0; i < 14; i++)
{
    [graphView addValue:data[i]];
}

На этом этапе все хорошо, и в отладке я вижу, что массив заполнен всеми элементами.Проблема в том, что вызывается drawLineGraphWithContext: метод;по какой-то причине массив внезапно становится пустым, и его счетчик хранения равен 0. Я попытался изменить способ доступа к объекту, используя точечные обозначения или опуская self, однако поведение выглядит так же.Как ни странно, я пытался идентифицировать зомби (как с GDB, так и с инструментами), однако ни один из них, похоже, не был найден.На самом деле, тогда запускается основной цикл в drawLineGraphWithContext: ниже массив данных имеет ноль элементов, и ничего не рисуется.Ниже полные файлы (я опускаю несущественные части).

Я использую Xcode 4.2 с автоматическим подсчетом ссылок.

Заранее спасибо всем, кто помогает!

GraphView.h:

@interface GraphView : UIView {
    NSMutableArray *data;
}

- (void)drawBar:(CGRect)rect context:(CGContextRef)ctx;
- (void)drawLineGraphWithContext:(CGContextRef)ctx;
- (void)addValue:(float)value;

@property(nonatomic, retain) NSMutableArray *data;

@end

GraphView.m:

#import "GraphView.h"

@implementation GraphView
@synthesize data;

- (id) init
{
    self = [super init];
    if(self) {
        data = [NSMutableArray array];
        NSLog(@"%s", __FUNCTION__);
    }
    return self;
}

- (void)addValue:(float)value
{
    NSMutableArray *tempArr = [self data];
    NSNumber *val = [NSNumber numberWithFloat:value];
    [tempArr addObject:val];
    [self setData:tempArr];
}

- (void)drawLineGraphWithContext:(CGContextRef)ctx
{
    CGContextSetLineWidth(ctx, 2.0);
    CGContextSetStrokeColorWithColor(ctx, [[UIColor colorWithRed:1.0 green:0.5 blue:0 alpha:1] CGColor]);

    int maxGraphHeight = kGraphHeight - kOffsetY;

    CGContextBeginPath(ctx);

    CGContextMoveToPoint(ctx, kOffsetX, kGraphHeight - maxGraphHeight * [[[self data] objectAtIndex:0] floatValue]);

    int i = 0;
    NSMutableArray *arr = [self data];

    for(NSNumber *elem in arr)
    {
        float val = [elem floatValue];
        CGContextAddLineToPoint(ctx, kOffsetX + i * kStepX, kGraphHeight - maxGraphHeight * val);
       i++;
    }

    CGContextDrawPath(ctx, kCGPathStroke);    

}

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetLineWidth(context, 0.6);
    CGContextSetStrokeColorWithColor(context, [[UIColor lightGrayColor] CGColor]);

    CGFloat dash[] = {2.0, 2.0};
    CGContextSetLineDash(context, 0.0, dash, 2);

    int lines = (kDefaultGraphWidth - kOffsetX)/kStepX;
    for(int i = 0; i < lines; i++)
    {
        CGContextMoveToPoint(context, kOffsetX + i * kStepX, kGraphTop);
        CGContextAddLineToPoint(context, kOffsetX + i * kStepX, kGraphBottom);
    }

    int horizontalLines = (kDefaultGraphWidth-kOffsetY)/kStepY;
    for(int i = 0; i < horizontalLines; i++)
    {
        CGContextMoveToPoint(context, kOffsetX, kGraphBottom - kOffsetY - i * kStepY);
        CGContextAddLineToPoint(context, kDefaultGraphWidth, kGraphBottom - kOffsetY -i * kStepY);
    }
    CGContextStrokePath(context);
    CGContextSetLineDash(context, 0, NULL, 0);

    [self drawLineGraphWithContext:context];
}

@end

GRViewController.m:

#import "GRViewController.h"

@implementation GRViewController
@synthesize scroller;
@synthesize graphView;

#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];
scroller.contentSize = CGSizeMake(kDefaultGraphWidth, kGraphHeight);
    graphView = [[GraphView alloc] init];

    float data[] = {0.7, 0.4, 0.9, 1.0, 0.2, 0.85, 0.11, 0.75, 0.53, 0.44, 0.88, 0.77, 0.99, 0.55};

    for(int i = 0; i < 14; i++)
    {
        [graphView addValue:data[i]];
    }
}

@ end

GRViewController.h:

#import <UIKit/UIKit.h>
#import "GraphView.h"

@interface GRViewController : UIViewController
@property (retain, nonatomic) IBOutlet UIScrollView *scroller;
@property (retain, nonatomic) IBOutlet GraphView *graphView;

@end

Ответы [ 3 ]

2 голосов
/ 04 ноября 2011

Похоже, у вас есть два разных экземпляра GraphView - один, который вы создаете в этом методе с помощью [[GraphView alloc] init], и другой экземпляр (вероятно, в кончике), который фактически отображается.GraphView, который получает данные, не отображается, а отображаемое GraphView никогда не получает никаких данных.Вы можете подтвердить, что это так, выполнив NSLog(@"I am %@", self) в соответствующих методах GraphView.Вы увидите два разных объекта отчетности.

1 голос
/ 04 ноября 2011

Попробуйте это.

- (void)addValue:(float)value
{
    NSNumber *val = [NSNumber numberWithFloat:value];
    [data addObject:val];
}

Вы можете просто использовать данные ivar, и не беспокоиться о получении или установке свойства.Это может исправить это, так как он не будет использовать ваш метод получения и установки каждый раз, когда вызывается addValue.

1 голос
/ 04 ноября 2011

В вашем методе init используйте либо ...

self.data = [NSMutableArray array];

, либо ...

data = [[NSMutableArray alloc] init];

Вы не проходите через свойство без использования «self».и, следовательно, не сохраняя массив.

...