1

I have read in iOS Programming Fundamentals by Matt Neuberg that instance variables are protected, meaning that other classes, except for subclasses of this one, can't see them.

I have a parent class A where I define an ivar list. (A.m)

@interface A ()

@end

@implementation A
{
     NSArray *list;
}

@end

Class B extends A (B.h)

#import "A.h"

@interface B:A

@end

(B.m)

@interface B ()

@end

@implementation B

list = 
...

@end

I want to use ivar list in child class B but the compiler doesn't see that the was reference declared in the parent class. I have tried explicitly using @protected but that doesn't work. I don't want to expose ivar list on the public interface. It's an internal structure that is a common element of all subclasses. How can I do this?

1
  • You have to declare the instance variable in A.h so that B can see it, and you have to declare it as @protected Commented May 28, 2015 at 18:45

2 Answers 2

1

Instance variables that are declared outside a class's public interface (in other words, the @interface section) are private by default. You can add a visibility modifier to the declaration to change the visibility of one or more ivars like so:

@implementation A
{
     NSNumber *_ivarWithDefaultVisibility;

@protected
     NSArray *_list;
     NSString *_anotherIvarWithProtectedVisibility;
}

(Note that according to Apple's Cocoa coding guidelines, ivar names should be prefixed with an underscore.)

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

1 Comment

This @implementation block is in the A.m file, so B won't be able to see it (the compiler doesn't have access to A.m when it's building B.m). You'd have to declare these ivars in the @interface block in A.h if you were going to do it this way.
0

This is not the usual way to implement protected properties in ObjC. (@protected and @private are very seldom used in Cocoa.) First, use a property, not an ivar. It will make it much cleaner. Declare it this way:

A.h

@interface A : NSObject
// Public interface goes here
@end

A.m

// Declare the property in a class extension inside the implementation file.
// This is the idiomatic way to create a "private" property.
@interface A ()
@property (nonatomic, readwrite, strong) NSArray *list;
@end

A+protected.h

// Enumerated any methods that should be accessible to subclasses here.
// Properties are just a special way of defining methods.
// The word "Protected" is just a category name.

@interface A (Protected)
@property (nonatomic, readwrite, strong) NSArray *list;
@end

B.h

#import "A.h"   
@interface B : A
...
@end

B.m

#import "B.h"
#import "A+protected.h"

// ... now you can use self.list ...

This approach allows you to create any kind of "protected" method, not just properties, and is also the technique used to create "friend" classes.

Comments

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.