Я читал много постов и не понимаю, почему это проблема - разве ARC не справится с этим?
Используя приведенные ниже ответы, я смог изолировать проблему как "Moves" как виновника - она, кажется, никогда не освобождается и продолжает потреблять память, даже если для нее установлено значение nil. Moves устанавливается в двух местах внизу Grid.m - методы FindRandomMove, и это вызывается в подпрограмме recursiveProcess.
Общая структура представляет собой сетку из столбцов, составленную из ячеек. Значение Cells генерируется случайным образом для составления загадки. Это делается много раз для тестирования решений головоломки.
Программа запускается при запуске generateTest в Grid.m
(Я ценю все комментарии к любой части кода, если я делаю что-то, что не соответствует передовым методам или есть лучший / правильный способ сделать это).
Полный код проверки:
Cell.h
@interface Cell : NSObject {
CFMutableBitVectorRef _validNumbersBitVector;
NSUInteger _answerNumber;
UIColor * _color;
NSUInteger _cellRow;
NSUInteger _cellCol;
}
@property CFMutableBitVectorRef validNumbersBitVector;
@property NSUInteger answerNumber;
@property (nonatomic, strong) UIColor * color;
@property NSUInteger cellRow;
@property NSUInteger cellCol;
// набор методов
- (void) setValid: (BOOL)valid number:(NSUInteger)numberToChange;
- (void) setAllNumbersToValidState:(BOOL) valid;
// get methods
- (BOOL) numberIsValid: (NSUInteger)numberToCheck;
- (NSUInteger) getRandomValidNumber;
- (NSUInteger) validNumberCount;
@end
Cell.m
#import "Cell.h"
#define RANGE CFRangeMake(0,9)
@implementation Cell
@synthesize validNumbersBitVector = _validNumbersBitVector;
@synthesize answerNumber = _answerNumber;
@synthesize color = _color;
@synthesize cellRow = _cellRow;
@synthesize cellCol = _cellCol;
-(id) init {
if ((self = [super init])){
_answerNumber = 0;
_validNumbersBitVector =CFBitVectorCreateMutable(NULL,10);
}
return self;
}
- (void) setValid:(BOOL)valid number:(NSUInteger)numberToChange {
CFBitVectorSetBitAtIndex(self.validNumbersBitVector, numberToChange - 1, !valid);
}
-(void) setAllNumbersToValidState:(BOOL) valid{
CFBitVectorSetBits(self.validNumbersBitVector, RANGE, !valid);
}
-(NSUInteger) validNumberCount{
return CFBitVectorGetCountOfBit(self.validNumbersBitVector, RANGE, 0);
}
- (BOOL) numberIsValid: (NSUInteger)numberToCheck{
return !CFBitVectorGetBitAtIndex(self.validNumbersBitVector, numberToCheck - 1);
}
- (NSUInteger) getRandomValidNumber{
NSUInteger pos;
NSUInteger counter = 0;
NSUInteger number = 0;
NSUInteger validCount = 0;
validCount = CFBitVectorGetCountOfBit(self.validNumbersBitVector, RANGE, 0);
if (validCount > 0) {
pos = (rand() %(validCount)) + 1;
while (counter < pos){
number ++;
if (!CFBitVectorGetBitAtIndex(self.validNumbersBitVector, number - 1) ) {
counter ++;
}
}
}
return number;
}
@end
Moves.h
#import "Cell.h"
@interface Moves : NSObject {
NSUInteger _row;
NSUInteger _col;
NSUInteger _newValue;
Cell * _cell;
}
@property NSUInteger row;
@property NSUInteger col;
@property NSUInteger newValue;
@property (nonatomic,retain) Cell * cell;
@end
Moves.m
#import "Moves.h"
@implementation Moves
@synthesize row = _row;
@synthesize col = _col;
@synthesize newValue = _newValue;
@synthesize cell = _cell;
-(id) init {
if ((self = [super init])) {
_row = 0;
_col = 0;
_newValue = 0;
}
return self;
}
@end
Grid.h
#import "Col.h"
#import "Moves.h"
@interface Grid : NSObject {
NSMutableArray* _rowData;
NSMutableArray* _emptyCells;
BOOL _puzzleSolved;
BOOL _bruteForceEnd;
}
@property (nonatomic, retain) NSMutableArray * rowData;
@property (nonatomic, retain) NSMutableArray * emptyCells;
@property BOOL puzzleSolved;
@property BOOL bruteForceEnd;
- (void) generateTest;
- (void) initializePuzzle;
- (Cell *) cellAtRow:(NSUInteger) pRow andCol:(NSUInteger) pCol;
- (void) setAnswerNumber:(NSUInteger)newAnswerNumber cell:(Cell *) pCell;
- (Moves*) FindRandomMove;
- (NSUInteger) recursiveProcess:(NSUInteger)BFCount;
@end
Grid.m
#import "Grid.h"
#import <QuartzCore/QuartzCore.h>
@implementation Grid
@synthesize rowData = _rowData;
@synthesize emptyCells = _emptyCells;
@synthesize puzzleSolved = _puzzleSolved;
@synthesize bruteForceEnd = _bruteForceEnd;
- (id) init
{
if ((self = [super init])) {
_rowData = [[NSMutableArray alloc] initWithCapacity:10];
_emptyCells = [[NSMutableArray alloc] init];
NSUInteger i;
for (i = 0; i<9; i++) {
Col *tmpCol = [[Col alloc] initWithRow:i + 1];
[_rowData addObject:tmpCol];
}
}
return self;
}
- (void) generateTest {
for (int mloop2 = 1; mloop2 < 10000;mloop2 ++) {
for (int mloop = 0; mloop < 1000; mloop ++) {
[self initializePuzzle];
[self recursiveProcess:0];
}
}
}
- (void) initializePuzzle{
self.bruteForceEnd = NO;
[self.emptyCells removeAllObjects];
for (Col * tmpCol in self.rowData){
for (Cell * answerCell in tmpCol.colData){
answerCell.answerNumber = 0;
[self.emptyCells addObject:answerCell];
}
}
}
- (Cell *) cellAtRow:(NSUInteger) pRow andCol:(NSUInteger) pCol {
Cell * tmpCell;
tmpCell = [[self.rowData objectAtIndex:pRow - 1] cellAtCol:pCol];
return tmpCell;
tmpCell = nil;
}
- (void) setAnswerNumber:(NSUInteger)newAnswerNumber cell:(Cell *) pCell{
if (pCell.answerNumber != newAnswerNumber) {
if (newAnswerNumber == 0 ) [self.emptyCells addObject: pCell];
if (pCell.answerNumber == 0) [self.emptyCells removeObject:pCell];
pCell.answerNumber = newAnswerNumber;
}
pCell = nil;
}
- (NSUInteger) recursiveProcess:(NSUInteger)BFCount{
Moves * nextMove;
Cell * answerCell;
NSUInteger counter;
NSUInteger number;
NSUInteger row;
NSUInteger col;
BFCount ++;
nextMove = [self FindRandomMove];
number = nextMove.newValue;
row = nextMove.row;
col = nextMove.col;
nextMove = nil;
answerCell = [self cellAtRow:row andCol:col];
[self setAnswerNumber:number cell:answerCell];
answerCell = nil;
if (BFCount > 48) self.bruteForceEnd=YES;
if (self.puzzleSolved) self.bruteForceEnd = YES;
if (self.bruteForceEnd) return BFCount;
counter = [self recursiveProcess:BFCount]; // try again
if (counter > 50) NSLog(@"brute force 50");
return BFCount;
}
- (Moves *) FindRandomMove{
Moves * tMove =[[Moves alloc] init];
NSUInteger col = 0;
NSUInteger row = 0;
NSUInteger possibleCount = 0;
NSMutableArray * possibleCells = [[NSMutableArray alloc] initWithCapacity:82];
NSUInteger selectedPossible;
NSUInteger numberToUse = 0;
Cell * answerCell ;
NSUInteger validCount = 0;
for ( Cell * tmpCell in self.emptyCells){
validCount=tmpCell.validNumberCount;
[possibleCells addObject:tmpCell];
possibleCount ++;
}
if (possibleCount != 0){
selectedPossible = 0;
if (possibleCount > 1) selectedPossible = rand() % (possibleCount - 1);
answerCell = [possibleCells objectAtIndex:selectedPossible];
row = answerCell.cellRow;
col = answerCell.cellCol;
numberToUse = answerCell.getRandomValidNumber;
answerCell = nil;
}
possibleCells = nil;
tMove.row = row;
tMove.col = col;
tMove.newValue = numberToUse;
return tMove;
}
@end