So I'm relative new to objC programming. But not to C. In a more complicated app I think I have a memory leaks. I've programmed this just for make some tests. The app is very simple: it store in a MutableArray a series of integer that rappresent timers scheduled. The app has one NSTimer in the current runloop that check every second if it is the right time to ring comparing a counter with the right element of the MutableArray. Everything works, but memory in debug panel grow up, grow up, grow up… I've try some variants but something still missing for me about ARC. I simply don't understand, since ARC is NOT a garbage collector, why memory grow and what I do wrong. Here is the code:
-(id)initWithLabel:(UILabel *)label {
self = [super init];
self.list = [[mtAllarmList alloc]init];
self.label = label;
return self;
}
My class init function. I pass a label reference (weak beacause it is own by viewcontroller) to my class. I also allocate and init the class mtAllarmList that contain the MutableArray and other information (in the original app, file to play, volumes, eccetera).
-(void)ClockRun {
NSMethodSignature * signature = [mtClockController instanceMethodSignatureForSelector:@selector(check)];
NSInvocation * selector = [NSInvocation invocationWithMethodSignature: signature];
[selector setTarget:self];
[selector setSelector:@selector(check)];
[[NSRunLoop currentRunLoop] addTimer: self.time = [NSTimer scheduledTimerWithTimeInterval:1
invocation:selector
repeats:YES]
forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] runUntilDate:[[NSDate alloc]initWithTimeIntervalSinceNow: 30]];
}
ClockRun: is the method the app call to start everything. It simply start the timer that fires every second to check:
-(void)check {
self.counter++;
int i = [self.list check:self.counter];
if(i == 1) {
[self writeAllarmToLabel:self.label isPlayingAllarmNumber:self.counter];
}
else if (i == 2) {
[self writeAllarmToLabel:self.label theString: @"Stop"];
[self.time invalidate];
self.counter = 0;
}
else {
[self writeAllarmToLabel:self.label theString:[[NSString alloc]initWithFormat:@"controllo, %d", self.counter]];
}
NSLog(@"controllo %d", self.counter);
}
Check: simply reacts to the return value of [list check: int] methods of mtAllarmList. It returns 1 if timer must ring, 0 if not, and 2 if the sequence ends. In that case self.counter will be set to 0 and the NSTimer will be invalidate.
-(id)init {
self = [super init];
self.arrayOfAllarms = [[NSMutableArray alloc]initWithCapacity:0];
int i;
for(i=1;i<=30;++i) {
[self.arrayOfAllarms addObject: [[NSNumber alloc]initWithInt:i*1]];
}
for(NSNumber * elemento in self.arrayOfAllarms)
NSLog(@"ho creato un array con elemento %d", [elemento intValue]);
return self;
}
In mtAllarmList init method simulates the costruction an array (I've try a variety of patterns) and log all the elements.
-(int)check:(int)second {
int maxValue = [[self.arrayOfAllarms lastObject] intValue];
if(maxValue == second){
self.index = 0;
return 2;
} else {
if ([[self.arrayOfAllarms objectAtIndex:self.index] intValue] == second) {
self.index++;
return 1;
} else {
return 0;
}
}
}
Check methods instead is very elementary and I don't think needs explanations.
So, why this simple very stupid app leaks?