我一直在閱讀很多文章,並且很困惑爲什麼這是一個問題 - ARC不應該處理這個問題嗎?Objective C ARC NSMutableArray - 從函數返回 - 沒有發佈?
利用下面的回覆我能夠將問題隔離爲「移動」作爲罪魁禍首 - 它似乎永遠不會被釋放,並保持消耗內存,即使它被設置爲零。移動在Grid.m底部的兩個地方設置 - 方法FindRandomMove,並在recursiveProcess例程中調用。
一般結構是由列組成的網格,由單元組成。 Cells值是隨機生成的,以製作拼圖。這是多次測試拼圖解決方案。
程序開始在Grid.m運行generateTest
(我欣賞在代碼的任何部分的所有意見,如果我做的東西,不遵循最佳做法或有做的更好/有道它)。
完整的測試代碼如下:
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
感謝您的回覆。我會嘗試零! – user1054717
關於您的評論以提及自我的問題。 Cell.h我定義了接口屬性_xxxx。然後使用屬性與_。 Ex NSUinteger _cellRow;屬性NSUInteger cellRow;在Cell.m中 - 合成cellRow = _cellRow;然後我在Cell.m中的函數中使用self.cellRow。 (我使用_cellRow的唯一時間是在init中);它是否正確 ? – user1054717
您可以在任何地方使用iVars。如果你定義了一個屬性,你可以使用'self.propertyName'。使用getter/setter(例如self.propertyName)表示調用setter/getter函數。綜合版本是根據您的屬性定義生成的。當你使用iVar時,你直接分配你想要的任何值,如果不是在ARC下,你需要確保釋放舊值(如果需要)並保留新值(如果需要的話)。需要什麼取決於數據類型以及您希望iVar /屬性如何工作。 – XJones