Счетчик NSMutableArray постоянно меняется - PullRequest
0 голосов
/ 17 марта 2011

У меня слишком много кода, чтобы знать, что мне нужно здесь цитировать, но в моем делегате приложения у меня есть NSMutableArray. Затем в другом классе он создает новую запись в NSMutableArray, но при передаче обратно в другой класс, который должен использовать это для отображения чего-либо на экране, он ничего не отображает. Помещение NSLog для счетчика NSMutableArray в конец создаваемого класса отображает число 1, а затем помещает тот же код NSLog в начало класса, который должен использовать, который возвращает 0.

Есть идеи, почему это так?

РЕДАКТИРОВАТЬ: Хорошо, я постараюсь включить весь связанный код ..

приложение делегат.h:

@interface palettesAppDelegate : NSObject <UIApplicationDelegate> {
 NSMutableArray *colourPalettesContainer;

}
@property (assign, readwrite) NSMutableArray *colourPalettesContainer;
@end

приложение делегат.m:

#import "palettesAppDelegate.h"

@implementation palettesAppDelegate

@synthesize colourPalettesContainer;

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


@end

Homeview.h:

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

@interface HomeView : UIViewController {

    HandlingPalettes *handlingPalettes;

}


@end

Homeview.m:

#import "HomeView.h"
#import <QuartzCore/QuartzCore.h>


@implementation HomeView


- (void)viewDidLoad {
    [super viewDidLoad];
handlingPalettes = [[HandlingPalettes alloc] init];

    [handlingPalettes newPalette];

}

-(void)viewWillAppear:(BOOL)animated {


    NSLog(@"view will appear: %i", [dataCenter.colourPalettesContainer count]);
    int numberOfExisting = [dataCenter.colourPalettesContainer count];

}

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


@end

HandlingPalettes.h:

#import <UIKit/UIKit.h>

@interface HandlingPalettes : UIViewController {

}


-(void)newPalette;



@end

HandlingPalettes.m:

#import "HandlingPalettes.h"
#import "HomeView.h"
#import "palettesAppDelegate.h"



@implementation HandlingPalettes


-(void)newPalette {

    palettesAppDelegate *dataCenter = (palettesAppDelegate *)[[UIApplication sharedApplication] delegate];

    //If this is the first palette
    if (dataCenter.colourPalettesContainer == nil) {
    dataCenter.colourPalettesContainer = [[NSMutableArray alloc] init];
    }
    //Add a new palette

        [dataCenter.colourPalettesContainer addObject:@"Test1", @"Test2", nil];


    NSLog(@"Handling:    %i", [dataCenter.colourPalettesContainer count]);


}- (void)dealloc {
   [super dealloc];
}


@end

Ответы [ 3 ]

1 голос
/ 17 марта 2011

Я был бы склонен избавиться от метода newPalette и вместо этого создать метод получения для colourPalettesContainer в делегате приложения. то есть:

appdelegate.h

@interface PalettesAppDelegate : NSObject <UIApplicationDelegate> {
   NSMutableArray *colourPalettesContainer;

} 
@property (non-atomic, retain) NSMutableArray *colourPalettesContainer;
@end

@implementation palettesAppDelegate

appdelegate.m

#import "appdelegate.h"
@synthesize colourPalettesContainer;
- (NSMutableArray *) colourPalettesContainer{
    if(colourPalettesContainer==nil){
        colourPalettesContainer=[[NSMutableArray alloc] init];
    }
    return colourPalettesContainer;
}
- (void)dealloc {
    [colourPalettesContainer release];
    [super dealloc];
}
@end

тогда вы сможете добавлять предметы, позвонив по номеру

[appDelegate.colourPalettesContainer addObject:object];
1 голос
/ 17 марта 2011

Я подозреваю, что проблема в конечном счете связана с запутанным управлением памятью члена colourPalettesContainer. Вы освобождаете его в методе dealloc делегата приложения, но этот класс никогда не сохраняет его! Было бы намного чище, если бы вы следовали рекомендациям Apple по управлению памятью : ваши классы должны выпускать только те объекты, которыми они владеют (то есть, которые они сами сохранили ранее). Например, вы можете сделать это, объявив свойство массива retain:

@property (retain) NSMutableArray *colourPalettesContainer;

(Чтобы предотвратить утечку массива, вам также необходимо освободить или автоматически выпустить его в методе newPalette. Сохранение и освобождение всегда должны происходить в тесных парах.)

Но еще лучше, почему бы просто не создать массив в методе init делегата приложения или в его методе доступа (если по какой-то причине вы хотите продолжить создавать его только при первом его использовании)? Если вы не хотите заменить все палитры одновременно, нет никаких оснований позволять назначать массив извне делегата приложения.

@interface PalettesAppDelegate : NSObject <UIApplicationDelegate> {
@private
    NSMutableArray *colourPalettesContainer;
}
@property (readonly) NSMutableArray *colourPalettesContainer;
@end

@implementation PalettesAppDelegate

- (NSMutableArray *)colourPalettesContainer {
    if (colourPalettesContainer == nil) {
        colourPalettesContainer = [[NSMutableArray alloc] init];
    return colourPalettesContainer;
}

- (void)dealloc {
    [colourPalettesContainer release];
    [super dealloc];
}
@end

Чтобы сделать дизайн еще чище, измените тип свойства colourPalettesContainer на NSArray * и добавьте метод -addPalette: к делегату приложения. (Редко хорошей идеей является публичное представление изменяемого массива внутри класса.) Затем вы можете просто избавиться от -newPalette в HandlingPalettes. (Если вы хотите, чтобы все ваши методы обработки палитр были в HandlingPalettes, просто переместите массив туда. Если вам нужен доступ к палитрам из случайных мест в вашем приложении, тогда вы можете просто поместить сохраненную ссылку на ваш HandlingPalettes объект в приложении делегат.)

Как только вы уберете беспорядок владения объектами, несоответствие счетчиков будет устранено "по волшебству", или причина, вероятно, станет намного более очевидной. В последнем случае убедитесь, что HomeView dataCenter на самом деле является тем же объектом, что и HandlingPalettes. (Вы не указали, как HomeView получает его ссылку - вы уверены, что случайно не создаете другой экземпляр делегата приложения?)

(Кстати, вы, вероятно, хотели использовать -addObjects:, а не -addObject: в newPalette. Обратите внимание также, что все имена классов должны быть написаны заглавными буквами, без исключений: т. Е. Всегда используйте PalettesAppDelegate, никогда palettesAppDelegate. Если по какой-то причине шаблон проекта Xcode создал его таким образом, просто переименуйте класс. Имена классов в нижнем регистре слишком легко спутать с именами переменных. Также попробуйте найти более подходящие имена в целом: например, вместо HandlingPalettes Я бы использовал PalettesViewController (чтобы отразить тот факт, что это подкласс UIViewController), а вместо dataCenter я бы просто выбрал appDelegate.)

1 голос
/ 17 марта 2011

Ваш основной mutablearray находится в вашем приложении-делегате.Итак, посмотрите, что произойдет, если в КАЖДОМ МЕТОДЕ, когда вы хотите получить доступ к массиву, у вас есть строка для установки отношения делегата приложения

    palettesAppDelegate *dataCenter = (palettesAppDelegate *)[[UIApplication sharedApplication] delegate];

Теперь, когда вы вызываете объект dataCenter, вы будете ссылаться на приложениеДелегируйте и ваша программа найдет массив.

Вы также можете обнаружить, что вам нужно иметь #import "palettesAppDelegate.h" в каждом объекте, который будет ссылаться на делегат приложения.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...