Objective-C public get set method for private property - objective-c

I wonder if it is possible to use #synthesize on a private #property so that the get/set methods have public access.
Right now my code looks something like this
SomeClass.h
#import <Foundation/Foundation.h>
#interface SomeClass : NSObject
{
#private
int somePrivateVariable;
}
#end
SomeClass.m
#import "SomeClass.h"
#interface SomeClass ()
#property int somePrivateVariable;
#end
#implementation
#synthesize somePrivateVariable;
#end
Then in some outside function I want to be able to write:
#import "SomeClass.h"
SomeClass *someClass = [[SomeClass alloc] init];
[someClass setSomePrivateVariable:1337]; // set the var
NSLog("value: %i", [someClass getSomePrivateVariable]); // get the var
I know that I can just create my own get/set methods in the header file but I would enjoy using the #synthesize very much more.

If you want a public property to mirror a private one, just override the public property's getter and setter and return the private one.
#interface Test : NSObject
#property NSObject *publicObject;
#end
Then, in the implementation:
#interface Test ()
#property NSObject *privateObject;
#end
#implementation Test
- (NSObject *)publicObject
{
return self.privateObject;
}
- (void)setPublicObject:(NSObject *)publicObject
{
self.privateObject = publicObject;
}
#end

Related

is it possible to have a protected ivar declared in a class extension and have a superclass be able to access it or what to do instead?

I have a class which internally uses an ivar. I don't want to expose the ivar in the public interface of the class (the header) but I declare and use it in the implementation file, like so:
//--------SomeClass.h--------------
#interface SomeClass : NSObject
#end
//--------SomeClass.m--------------
#implementation SomeClass ()
{
#protected
NSMutableDictionary *_privateData;
}
#implementation SomeClass
// ...
#end
Then in a subclass of SomeClass, I try to access _privateData:
//--------SomeSubClass.m--------------
#implementation SomeSubClass
// ...
- (void)someMethod {
NSLog(#"%#", _privateData); // NOPE
NSLog(#"%#", self->_privateData); // NOPE
NSLog(#"%#", super->_privateData); // NOPE
}
// ...
#end
But I can't. Is there a way to do this?
In order to achieve the desired behavior, you should create a subclass header file which declares all of your protected data and #import it in your subclass' .m file.
MammalSubclass.h:
#interface Mammal () {
#protected
NSMutableDictionary *_privateData;
}
//...
#end
Human.m:
#import "Human.h"
#import "MammalSubclass.h"
#implementation Human //subclasses Mammal
- (void)someMethod {
NSLog(#"%#", _privateData);
}
//...
#end

Hiding properties from public framework headers, but leaving available internally

I need to have property in class that is excluded from public framework headers, but it is available for use internally in other framework classes.
What I did right now is:
MyClass.h:
#interface MyClass: NSObject
#end
MyClass+Internal.h
#interface MyClass (Internal)
#property (nonatomic, copy) NSString *mySecretProperty;
#end
MyClass.m
#import "MyClass.h"
#import "MyClass+Internal.h"
#interface MyClass ()
#property (nonatomic, copy) NSString *mySecretProperty;
#end
#implementation MyClass
#end
And I can use private property like:
MyOtherClass.m:
#import "MyClass.h"
#import "MyClass+Internal.h"
#implementation MyOtherClass
- (void)test {
MyClass *myClass = [MyClass new];
NSLog(#"%#", myClass.mySecretProperty)
}
#end
But what I don't like about this setup is that I have duplicate declaration of property in my Internal Category and inside of anonymous Category.
Is there a way to improve this setup?
I think you could do with the class extension only, there is no need to use a category. The quick fix would be to remove the category name from the parenthesis, transforming it into the class extension, then remove the class extension declaration from the .m file.
After this you only import the extension header in your framework classes and you make sure it is a private header of your framework.
MyClass.h
#interface MyClass: NSObject
#end
MyClass+Internal.h
#import "MyClass.h"
#interface MyClass ()
#property (nonatomic, copy) NSString *mySecretProperty;
#end
MyClass.m
#import "MyClass.h"
#import "MyClass+Internal.h"
#implementation MyClass
#end
MyOtherClass.m:
#import "MyClass.h"
#import "MyClass+Internal.h"
#implementation MyOtherClass
- (void)test {
MyClass *myClass = [MyClass new];
NSLog(#"%#", myClass.mySecretProperty)
}
#end
The key is understanding the difference between categories and class extensions, see here: https://stackoverflow.com/a/4540582/703809

ObjectiveC: where to declare private instance properties?

I have the following class interface:
#interface MyClass : NSObject
#property int publicProperty;
#end
then the implementation:
#interface MyClass() // class extension
- (void)privateMethod; // private methods
#end
#implementation MyClass {
int _privateProperty;
}
#property int privateProperty = _privateProperty;
#end
this is what the Apple guy showed in WWDC, but is there any reason for NOT putting _privateProperty in class extension like:
#interface MyClass() // class extension
{
int _privateProperty;
}
- (void)privateMethod; // private methods
#end
Thanks!
I usually "force" private with an extension in the implementation
In your header
#interface MyClass : NSObject
{
}
#property (nonatomic, assign) int publicProperty;
#end
In your implementation file:
#interface MyClass ()
#property (nonatomic, assign) int privateProperty;
#end
#implementation MyClass
#synthesize privateProperty;
#synthesize publicProperty;
#end
You dont have to declare your ivars in both the interface and the implementation.Because you want to make them private you can just declared them in the implementation file like so:
#implementation {
int firstVariable;
int secondVariable;
...
}
//properties and code for your methods
If you wanted to, you can then create getter and setter methods so that you can access those variables.
The person you spoke to was right, though there is not any reason why you would NOT declare them the same way in the interface. Some books actually teach you that the #interface shows the public face of the class and what you have in the implementation will be private.
Do you mean you want to declare private instance variables?
You can do this:
#interface MyClass()
{
#private //makes the following ivar private
int _privateProperty;
}
With the "modern runtime" (64-bit MacOS post-10.5 and all versions of iOS), you don't need to declare instance variables at all.
// MyClass.h
#interface MyClass : NSObject
#property int publicProperty;
#end
// MyClass.m
#implementation MyClass
#synthesize publicProperty = _privateProperty; // int _privateProperty is automatically synthesized for you.
#end

property public and private but not protected?

I'm learning the objective C language and i ask a simple question,
when i do that :
// ParentClass.h
#interface ParentClass : NSObject
#property (read, strong) NSString *parentPublicStr;
#end
// ParentClass.m
#interface ParentClass ()
#property (readwrite, strong) NSString *parentPrivateStr;
#end
#implementation ParentClass
#synthesize parentPublicStr;
#synthesize parentPrivateStr;
#end
// Subclass SubClass.h
#interface SubClass : ParentClass
- (void) test;
#end
#implementation SubClass
- (void) test
{
// Its not possible to do that : [self setParentPrivateStr:#"myStrin"]
// And for parentPublicStr, it is public property so not protected, because i can change the value
// in main.c, and it's so bad..
}
#end
I would like create a property that is protected :x
Thx you. (Sorry for my english)
Objective-C does not provide for protected methods/properties. See this question.
Edit: Also see this answer. You can still practice encapsulation by declaring the property in a class extension and including the extension in subclasses.
You can manually create an ivar for the property as long as you use the same name prefixed with an underscore:
#interface ParentClass : NSObject
{
#protected
NSString* _parentPublicStr;
}
#property (read, strong) NSString *parentPublicStr;
#end
That makes the synthesized ivar for the property #protected (default is #private) and subclasses can then use the super class' ivar directly.

Objective C: use instance class in other class

In my code, in an class I have an ivar
FirstClass *first;
and I can use first within an instance of this class.
But if I want to access first from another object instance (or even another class), how can I do that?
I assume you're talking about using FirstClass in another source file than its own, right?
In this case you'd have to import its header by adding this to the top of your second class' ".m"-file:
#import "FirstClass.h"
If you also need to reference in your second class' header ".h"-file, then you can add a
#class FirstClass;
before the #interface block. This will tell the compiler that it should consider a class of that name to be existant, but to not bother you with warnings unless you forget to import the given first class' ".h" file in the second class' ".m" file.
To allow access from foreign objects to your SecondClass' firstClass iVar you'll need to implement a getter method for firstClass.
This is done with
#property (nonatomic, readwrite, retain) FirstClass *firstClass;
in the #interface block, and
#synthesize firstClass;
in the #implementation block.
With this set up you can then either call [secondClassInstance firstClass]; or access it via the dot syntax secondClassInstance.firstClass;.
My sample will also synthesize a setter method called setFirstClass:. To make the property read-only, change readwrite to readonly in the #property declaration.
Sample:
FirstClass.h:
#import <Cocoa/Cocoa.h>
#interface FirstClass : NSObject {
#private
}
//method declarations
#end
FirstClass.m:
#import "FirstClass.h"
#implementation FirstClass
//method implementations
#end
SecondClass.h:
#import <Cocoa/Cocoa.h>
#class FirstClass;
#interface SecondClass : NSObject {
#private
FirstClass *firstClass;
}
#property (nonatomic, readwrite, retain) FirstClass *firstClass;
//method declarations
#end
SecondClass.m:
#import "SecondClass.h"
#import "FirstClass.h"
#implementation SecondClass
#synthesize firstClass;
- (id)init {
if ((self = [super init]) != nil) {
firstClass = [FirstClass alloc] init];
}
return self;
}
- (void)dealloc {
[firstClass release];
[super dealloc];
}
//method implementations
#end
I would use a property. Probably in your header of your second class something like
#property (nonatomic, retain) FirstClass *first;
and in your implementation
#synthesize first;
Than when you create an object of your SecondClass
SecondClass *second = [[SecondClass alloc] init];
you can use
second.first