1

I have a instance variable mTeacher in my School class:

@interface School : NSObject {
     Teacher *mTeacher;
}
@end

In implementation file, I have method - (Teacher *)getTeacher which is supposed to return either the existing teacher instance if there is one or create one and return it:

- (Teacher *)getTeacher {
    if (mTeacher != nil) {
        return mTeacher;
    }
    return [[Teacher alloc] init];
}

There could be multiple other instance methods calling this method to get the Teacher instance & assign to mTeacher instance variable:

- (void)methodOne {
   mTeacher = [self getTeacher];
   ...
}

- (void)methodTwo {
   mTeacher = [self getTeacher];
   ...
}

So, if one of the method assigned already an instance of Teacher to mTeacher, the other method when calling [self getTeacher] would end up with mTeacher = mTeacher underneath (because - (Teacher *)getTeacher method simply returns mTeacher in this case). My question is , is it fine in objective-C ? Any potential issues with my getTeacher method?

3
  • You're implementing the Singleton design pattern. Here's another related post on the topic that should help: stackoverflow.com/questions/145154/… Commented May 31, 2016 at 12:39
  • 1
    I don't see anything technically wrong with it, but why not just initialize the variable once in an init method and use it where needed rather than trying to set it multiple times? (On style: it would be more in keeping with Objective-C to make teacher a property rather than an explicit variable. Then, along with my suggestion about init, the "getter" would disappear from your code.) Commented May 31, 2016 at 12:40
  • If mTeacher is never nil, why don't you initialize it in the School's init method ? Also, you should check this out Properties in Objective-c Commented May 31, 2016 at 12:43

4 Answers 4

1

The approach is correct, but there are two remarks:

A. You can never have a "no teacher" scheool, that means the property nil'd – for whatever.

B. Obviously you start with Objective-C coming from another language:

  • Do not use a m prefix for "members". (They are no member, but ivars.)

  • Do not declare ivars in interface.

  • Do not use a get prefix for getters.

You can use properties as mentioned by vadian:

@interface School : NSObject 
@property (readonly, strong, nonatomic) Teacher *teacher; // without m
- (Teacher*)teacher; // *Alternatively* without @property
@end

@implementation School
// usually the ivar is created implicitly with the name _teacher. 
// However, you have a readonly property and overwrite all accessors 
// (in the case of a read only property there is only a getter) of the property, 
// no ivar will be created automatically. You have to do that explicitly.
{
    Teacher *_teacher;
}

- (Teacher *)teacher { // no m
  if (!_teacher) 
  {  
    _teacher = [[Teacher alloc] init];
  }
  return _teacher;
}
@end

Additionally this code is not thread-safe.

Sign up to request clarification or add additional context in comments.

Comments

1

It looks like you want to instantiate the variable lazily.

The usual pattern in Objective-C is to declare a readonly (nonatomic) property and use the backing instance variable for the initialization.

@interface School : NSObject 

@property (readonly, strong, nonatomic) Teacher *mTeacher;

@end

@implementation School
@synthesize mTeacher = _mTeacher;

- (Teacher *)mTeacher {
    if (!_mTeacher) {
        _mTeacher = [[Teacher alloc] init];
    }
    return _mTeacher;
}

@end

Edit: Without using a property access the instance variable directly:

@interface School : NSObject
{
  Teacher *mTeacher;
}

@end

@implementation School

- (Teacher *)mTeacher {
  if (!mTeacher) {
     mTeacher = [[Teacher alloc] init];
  }
  return mTeacher;
}

@end

However if you want to use explicitly the getter rather than the instance variable you have to write

[self mTeacher];

8 Comments

I'd be very interested to know the version without using @property for lazy initialization, could you please show me that as well?
I added an example for that
@vadian your example will not compile, because the ivar is not created implicitly, if you overwrite all accessors.
@AminNegm-Awad Thanks, I prefer synthesizing.
However, you have to do that explicitly, as you did in your edit.
|
0

It is fine with objective c..!! You should not got issue with this i think but you can check with if - else like,

 - (void)methodOne {

    if(!mTeacher){
    mTeacher = [self getTeacher];
    }
    ...
  }

So, if mTeacher is not nil then only it will called getTeacher.

In objective c, you can use property for this. It will set getter and setter methods of it. Or you need this object to initialize once in init method. no need to do like this.

Comments

0

Nothing wrong with this approach, why can't you create Teacher object in School init. And also if you are working on a multithreading environment make sure you are not creating the Teacher object multiple times.

6 Comments

You are right that the code is not thread-safe. But making solely accessors thread-safe is meaningless in many cases. (That's why nearly nobody uses atomic accessors.) However, if you want to have thread-safeness, one should use GCD in nowadays.
I mean we should guard the the place where we are creating instance (init method), not the accessor.
@Feroz: Lazy initialisation is very useful and in many cases essential.
@gnasher729: Yup Agreed.
I'm not denying that, I'm just telling to ensure thread safety while creating instance, Is anything wrong with that statement?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.