I'd like to define a member in objective C class that can only be read outside the class (public getter). The writing (setter) however shell remain private.
I've read that It's possible to conceal object's setter using the readonly property while exposing the getter using #synthesize syntax but I'm not sure how it works exactly.
Base on this information here's what I did, and I wonder what's happening here under the hood, and if this is the proper way of doing so ?
#interface MyObject : NSObject
//This line suppose to conceal both getter and setter.
#property (readonly) MyCppBaseObject *myCppBaseObject;
- (void)setMyCppBaseObject:(NSString *)SomeInput;
#end
// This line suppose to tell the compiler that the getter is exposed
#synthesize myCppBaseObject = _myCppBaseObject;
#implementation MyObject
-(void)setMyCppBaseObject:(NSString *)SomeInput {
if (someCondition) {
self.myCppBaseObject = new myCppObjectDerive1(...);
} else {
self.myCppBaseObject = new myCppObjectDerive2(...);
}
}
#end
P.S. I've seen a different approach explained in the following link, but I wish to understand the above implementation.
First, you should use the private extension described in the link you provide. That's the correct way to do this.
But to your question, what you've written here is not quite correct.
#property (readonly) MyCppBaseObject *myCppBaseObject;
This line makes a promise to implement -myCppBaseObject. That's all it does. It's just a promise. If you fail to live up to your promise, the compiler will auto-generate (synthesize) one for you using a backing ivar.
- (void)setMyCppBaseObject:(NSString *)SomeInput;
This line is not correct for your purposes. It's making a public setter. But you said you don't want the setter to be public. You could put this in a private extension, however.
#synthesize myCppBaseObject = _myCppBaseObject;
This asks the compiler to create a backing ivar _myCppBaseObject for the property myCppBaseObject. This is the default behavior, however, and so isn't required. (There was a time when it was, but that was a very long time ago.)
-(void)setMyCppBaseObject:(NSString *)SomeInput {
if (someCondition) {
self.myCppBaseObject = new myCppObjectDerive1(...);
} else {
self.myCppBaseObject = new myCppObjectDerive2(...);
}
}
This code is completely incorrect. It is an infinite loop, since self.x =... is syntactic sugar for [self setX:...]. What you mean is:
_myCppBaseObject = ...
You're going to create a lot of headaches having the name of the custom setter be exactly the expected name of the default setter, but with a different type. Don't do this. In theory it could work most of the time, but don't. Especially when there's dot-syntax involved. Especially since one of your objects does not appear to be ARC-compatible (i.e. a C++ object), this is going to really be a trap for really confusing problems. Name your setter differently.
Related
I know this question has been asked before but possibly not in the same context. My question is that I have a singleton class that is only dipatched_once in the lifetime of the app. In the class I have some methods that are accessing the instance variables and acting upon if they have been set on the instance. This is example of how I am attempting to access them:
// .m file:
Interface:
#property (nonatomic, assign, readwrite) BOOL userLoggedIn;
Implementation:
// method:
-(void)someMethod{
if(!_userLoggedIn){
}
else {
}
}
I know I can also use self to evaluate the value like this:
-(void)someMethod{
if(self.userLoggedIn){
}
else {
}
}
Wondering which is correct way of accessing the value? I am not synthesizing the properties since they are all declared in the interface only in the .m file. Thanks for the help!
It depends.
Do you want the accessor invoked or not? _variable is direct access. self.variable invokes -variable, which is automatically synthesized by the compiler.
The former does not trigger KVO when the value changes. The latter does. That may be a feature or anti-feature.
But, whichever you choose, especially for write operations, make it consistent or else you'll be tracking down bugs in the future.
A general rule:
access directly in -init/-dealloc
access through setter/getter (dot syntax) everywhere else
Note also that direct access will not respect atomic.
#interface RandomObject : NSObject
{
NSString* someObject; // I know I don't have to explicitly declare. Just to clarify my point.
}
#property (nonatomic, strong) NSString *someObject;
#end
#implementation RandomObject
#synthesize someObject;
#end
Given the code above and Xcode 4.3 is used (hence, no auto-synthesizing), here is my question.
The property/synthesize will create accessors for someObject, namely getter and setter. So if I want to assign a value to someObject, I can do this.
self.someObject = #"Tomato"; // [self setSomeObject: #"Tomato"];
If my understanding is correct, self will send #"Tomato" to setSomeObject method. But what if you do this?
someObject = #"Tomato"; // or maybe _someObject = #"Tomato" if you are doing auto-synthesizing
Directly accessing an iVar object seems like a bad idea, but since someObject is a private variable, within the same class you have access to that, right?
I understand why you would need to use self.someOject if you want to manipulate someObject from another class. But why is it that you'd need to do the same even though you are still in the same class. Why is it that it's a bad idea to directly access iVar.
Generally speaking accessors have more pros than cons and I use them everywhere I can.
The main issue is that every place you reference the ivar directly is another potential place your code will need to change.
For example imagine you have referenced someObject in multiple places throughout your class. Then the requirements change and now you decide that when the value of someObject is assigned you need to so some other work. Due to the fact that you have accessed the ivar directly throughout the class you now have to either duplicate this new code everywhere you assign someObject or refactor. If you was using an accessor you just have one piece of code to change
- (void)setSomeObject:(id)anObject
{
if (anObject != someObject) {
someObject = anObject;
[self doSomeWork];
}
}
You can have the same issue with the getter - imagine you store an array of objects in someObjects - this works great but then later down the line you decide that you don't actually need to store someObjects as it can be dynamically computed from other values. If you have directly accessed the ivar everywhere then this becomes a big chore. If you stick to abstracting someObject behind a getter then all you now have to do is
- (NSArray *)someObjects
{
return [self calculateSomeObjects];
}
This is exactly the idea with non-ARC code, which puts the memory management of the ivar in one place (behind accessors) so that you do not have to litter your code with repetitive code.
The property does more than just assigning an object to the ivar.
If you don't use ARC, the property will auto-generate retain/release code to handle memory management. Just calling someObject = #"Tomato" creates a memory leak (if someObject is assigned)
If your property is atomic, the property will provide thread safety, while accessing the ivar would not be thread safe.
See https://stackoverflow.com/a/589348/1597531 for examples of auto-generated property code.
I'm still new to Objective-C and I recently learned how to make properties, so far so good, but one thing that bothers me is that the setter and getter methods are still publicly available even after the property is made.
let's say I have the following code:
// myClass.h
#interface myClass : NSObject {
int _startPos;
}
#property (assign, readwrite, setter = setStartPos:, getter = getStartPos) int startPos;
-(void) setStartPos: (int) pos;
-(int) getStartPos;
#end
the implementation file should be rather self-explanatory, I'm not trying to do anything specific.
Now, I read somewhere, and tried it in practice that if you make a category in the implementation file, and add some methods to that, it's possible to make those methods invisible (aka private) to things outside of the myClass.m file.
"Alright" I think, and decide to try it out:
//myClass.m
#import <Foundation/Foundation.h>
#import "myClass.h"
#interface myClass (hidden)
-(void) setHiddenStartPos: (int) hPos;
-(int) getHiddenStartPos;
#end
#implementation myClass (hidden)
-(void) setHiddenStartPos: (int) hPos {
_startPos = hPos;
}
-(int) getHiddenStartPos {
return _startPos;
}
#end
#implementation myClass
-(void) setStartPos: (int) Pos {
[self setHiddenStartPos: Pos];
}
-(int) getStartPos {
return [self getHiddenStartPos]; //this is to see if I can get the value from the hidden methods through the non-hidden ones
}
#end
that's all fine, and testing it in main() I can see that the methods with "hidden" in their name are in fact inaccessible, and therefore act as if they are private.
Then I tried to add this to the header file:
#property (assign, readwrite, setter = setHiddenStartPos:, getter = getHiddenStartPos) int
to see if I could access the hidden methods through the property
but when I did that, the hidden methods became accessible in main() and the whole plan with making the methods only accessible through the property went down the drain
So I ask you, is there a way to make methods inaccessible to anything BUT the property and/or the object itself?
Edit: I realize that getters don't usually have get in the name, so please stop commenting on it?
also to emphasise what I meant:
I wanted to make properties like in c#, where the content of the setters and getters are private to the property itself
public int exampleProperty
{
set{...}
get{...}
}
it doesn't use methods as getters and setters, and therefore the code in the setters and getters are accessible to only the property, JUST like the code within a method is local to the method itself
Add a class continuation in your .m file. i.e.:
#interface myClass ()
#property (assign, readwrite, setter = setHiddenStartPos:, getter = getHiddenStartPos) int hiddenStartPos;
#end
#implimentation myClass
#synthesize hiddenStartPos = _hiddenStartPos;
...
#end
Have a look at: What is an Objective-C "class continuation"?
PS: Your getters should just be hiddenStartPos rather than getHiddenStartPos...
It seems to me that the your confusion comes from misunderstanding exactly what an #property declaration is. It is essentially a declaration that setter and getter methods exist.
So, this
#property int hiddenStartPos;
is the same as this
- (int)hiddenStartPos;
- (void)setHiddenStartPos;
So, the implementation of these two methods is the implementation of the property. By decaring the property in the .h file, you're advertising to anyone who imports the .h that the class in question implements these two methods (the getter and the setter, respectively).
I also want to reemphasize that getter methods should not be prefixed with "get" in Objective-C.
You're over-thinking what "private" means. In ObjC, "private" just means "not visible." It doesn't mean "not callable." The way you make a method private is to not put it in your .h file, which declares your public interface.
There is no way to control who passes a message. This is a key fact of ObjC and cannot (and should not) be changed. ObjC is a dynamic language. At runtime, I am free to generate selectors and call performSelector: on any object I want. Anything that stopped that would either (a) introduce significant performance penalties, or (b) break many very useful and common techniques in ObjC (probably both). ObjC is not Java or C#. It's not even C or C++. It's Smalltalk on top of C. It's a highly dynamic language and that has a lot of strengths. Unlearning other languages is the first step towards becoming a good Cocoa developer.
It would be nice to have a compiler-checked #private for methods (of which properties are just a special case), and it would especially be awesome to have a compiler-checked #protected for methods (these exist for ivars). These would make it slightly simpler to avoid some kinds of mistakes. But that's the only way you should be thinking about this. The goal is not to protect one part of the code from another part of the code. The other code is not the enemy. It's all written by people who want the program to work. The goal is to avoid mistakes. Correct naming, consistency, and the absolute elimination of warnings is how you achieve that in ObjC.
So yes, I'd love to be able to put #protected in front of my #property declarations occasionally. Today you can't, and there is no real equivalent (I sometimes use a +Protected category in a separate header, but it's generally more trouble than its worth). But that said, having it wouldn't change very much, and I only find a case where I would even use this a few times a year. I can't think of single case where #private for a method would have been really useful, though.
I'm coming from C# development and just started to learn Objective-C and Xcode 4.
As far as I understand "#synthesize" is replacing getter/setter methods for properties if you don't need to check/control the values which are being read or written.
But why does Xcode 4 create a instance variable for me automatically?
Wouldn't this be enough:
#synthesize myProperty;
instead of:
#synthesize myProperty = _myProperty;
?
Why would I want to use/have the instance variable instead of the actual property if I don't have/need any getters or setters?
Thanks in advance!
MemphiZ
EDIT:
I understand that #synthesize is replacing getters/setters but what is this part good for: = _myProperty;?
Why would I want to have a instance variable if I could use "myProperty" directly? I would understand using "_myProperty" if the setter for example would check for a condition of the value. If I then want to skip this check I would use _myProperty. But as I use #synthesize I don't have a setter in place that does some check. So why do I have/want an instance variable then?
ANSWER:
See the comments in MattyG's post!
This is a convention used to remind the programmer to access the instance variables through the setters and getters with self. So if you're using:
#synthesize myProperty = _myProperty;
Then to access the variable directly you must write:
_myProperty = something;
To access the variable through it's setter you must write:
self.myProperty = something;
The benefit is that if you forget to access through self. then the compiler will warn you:
myProperty = something; //this won't compile
See this also this Question.
Well, you DECLARE a property's instance variable in the .h file, as well as the property itself. The interface to the property as well as the instance variable it'll use have been established with that... its implementation has not. That's where the #synthesize keyword comes in. It just implements the property for you, so that you don't have to write it out yourself.
Here are ways to declare properties in C#
private int _int1;
public int int1 {
get { return _int1; }
set { _int1 = value; }
}
This is a pretty common piece of code, and C# lets you abbreviate it to avoid having to type the same thing over and over
public int int1 { get; set; }
The difference between these two code segments is that the private variable "_int1" does not exist in the latter, since C# creates a variable internally. The #synthesize keyword is nice because it saves you the hassle of writing down the same code over and over while still allowing you to access the instance variable it's based on.
Edit. It's also important to note that getters and setters do exist in objective C. They just have different names than in C#, where they're labeled get{} and set{}. In objective C, the getter is a method with the same name as its instance variable, and the setter is a method with the word 'set' followed by the instance variable name with the first letter capitalized.
So, lets say you have this in your .h file
int myVar;
...
#property(nonatomic, assign) int myVar;
You can implement getters and setters yourself in the .m file
-(int)myVar {
return myVar;
}
-(void)setMyVar:(int)newVar {
myVar = newVar;
}
or you can just use #synthesize to have the getter and setter written automatically
I have seen this code in most of the time. Here there are two variable names defined and in the implementation it synthesizing by assigning. Whats the purpose of doing some thing like this? Like keeping 2 separate variable names. Is this sort of a convention?
Test.h
#interface Test {
id<something> _variable1;
}
#property (nonatomic, retain) id<something> variable2;
Test.m
#synthesize variable2 = _variable1
There is only one variable. The thing named variable2 is actually a property, which is basically a syntactic shortcut for a get/set method pair. When defining a property, you can either write the get/set methods explicitly...
- (void)setVariable2:(id<something>)value {
if (_variable1 != value) {
[_variable1 release];
_variable1 = [value retain];
}
}
- (id<something>)variable2 {
return _variable1;
}
...or use the #synthesize construct to generate the above methods automatically, thus sparing you a lot of monotonous typing. (It also emits code to release _variable1 on destruction of the object, which I haven't included here.)
Sometimes, however, you might want to implement one or other of these methods differently to the default. In this case, you would write your own. You can even mix together #synthesize and a custom version of just one of the methods.