Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Infinite recursion when creating my own setter for a property

I've stumbled over some strange behaviour in Objective-C. I have a main.m:

#include <Foundation/Foundation.h>
#include "AClass.h"

int main(int argc, char* argv[]) {
  AClass* tmpClass = [[AClass alloc] init];
  [tmpClass setAVariable:12];
  return -1;
}

A header AClass.h:

#include <Foundation/Foundation.h>

@interface AClass: NSObject; 

-(void) setAVariable:(int) bVariable;

@property int aVariable;

@end

and a corresponding implementation file AClass.m:

#include <Foundation/Foundation.h>
#include <AClass.h>

@implementation AClass
@dynamic aVariable;
int aVariable;

-(void) setAVariable:(int)bVariable {
  NSLog(@"foo:");
  self.aVariable = bVariable;  
}

@end

When compiling this code with either clang on Linux or via Xcode on OSX the setAVariable: is triggering an endless recursion. I wonder if this is a bug in clang/Objective-C.

like image 862
Christian Richter Avatar asked Mar 24 '23 06:03

Christian Richter


1 Answers

This is expected. You are accessing your setter inside your setter.

self.aVariable = bVariable is actually calling [self setAVariable:bVariable], hence the recursion. The dot syntax is just that, a special syntax that is really just a shorthand for the actual setter method. When you are writing your own setter method, you should access the backing instance variable, not the property itself. E.g.

- (void) setAVariable:(int)bVariable {
  NSLog(@"foo:");
  aVariable = bVariable;  
}

It's common practice to use a leading underscore for your instance variables so it's easy to recognize when you are accessing the instance variable directly versus the property (which goes through the getter and setter to get to the backing instance variable).

Also, it's best practice to use #import instead of #include as #import only includes the file once even if there are multiple #import statements for the same file, potentially speeding up compile times.

like image 126
Andrew Avatar answered Apr 08 '23 11:04

Andrew