Why does assigning to this ivar have no effect? - objective-c

I have a class, BPGameEngine, with a readonly property, currCharacter. In the past, I had been assigning to the ivar directly (like _currCharacter = someCharacter;) inside BPGameEngine. In a subclass I found myself needing to write to this property, and therefore redeclared it in an anonymous category like so
#interface BPGameKitMPGameEngine()
#property (readwrite, assign) BPCharacterInstance* currCharacter;
#end
The compiler then had an error (which, bizarrely, I can't reproduce anymore, two days later), which alluded to needing an #synthesize statement, so I added #synthesize currCharacter = _currCharacter; in the subclass (BPGameKitMPEngine).
I did not add a similar anonymous category in the superclass, because I was just using the iVar directly. I then discovered that the line _currCharacter = someCharacter; which is inside a method of BPGameEngine called by BPGameKitMPEngine in a call to super ([super methodContainingAssignmentToCurCharIvar]) simply did nothing. _currCharacter showed up in the debugger, and someCharacter was not nil, but after the line was executed, _currCharacter remained nil. Bizarrely, adding a similar anonymous category in the subclass fixed the problem, as did removing the #synthesize (which no longer causes Xcode to complain of compiler errors).
The inconsistent requirement for an #synthesize seems like it must be a bug in Xcode, but the rest of this has me stumped. Can someone explain the problem with having the #synthesize in the subclass?

An auto synthesised instance variable backing a property is private to the class it is created in. Therefore you cannot (directly) extend a read-only property to read-write one in a subclass - there is no access to original instance variable.
You should get various errors, such as ones pointing out you cannot access a private instance variable from your superclass if you try this. It sounds like you may have managed to create two properties, each with their own backing variable, hence a change to one is not as a change to the other - but how you managed that in this case I've no idea.
Of course you can bypass the private access... the following should work:
#interface BPGameKitMPGameEngine ()
- (void) setCurrCharacter:(int)value;
#end
and:
- (void) setCurrCharacter:(BPCharacterInstance *)value
{
[self setValue:value forKey:#"_currCharacter"];
}
HTH

I'm not sure if I did understand you problem 100% but please do the following:
Create a new class extension file for BPGameKitMPGameEngine called Private.
Import that file (#import "BPGameKitMPGameEngine_Private.h") into BPGameKitMPGameEngine.m and BPGameKitMPEngine.m.
Remove the existing class extension code from BPGameKitMPGameEngine.
And now check if it works as you would expect.

Related

Different Ways To Declare Objective C Instance Variables [duplicate]

I have been unable to find any information on this topic and most of what I know about it has come by complete accident (and a few hours of trying to figure out why my code wasn't working). While learning objective-c most tutorials I have found make variables and properties with the same name. I don't understand the significance because it seems that the property does all the work and the variable just kind of sits there. For instance:
Test.h
#interface Test : NSObject {
int _timesPlayed, _highscore;
}
#property int timesPlayed, highscore;
// Methods and stuff
#end
Test.m
#implementation Test
#synthesize timesPlayed = _timesPlayed;
#synthesize highscore = _highscore;
// methods and stuff
#end
What I know
1) Okay so today I found out (after hours of confusion) that no matter how much changing you do to the properties highscore = 5091231 it won't change anything when you try to call [test highscore] as it will still be returning the value of _highscore which (I think) is the ivar that was set in test.h. So all changing of variables in test.m needs to be changing _highscore and not highscore. (Correct me if I'm wrong here please)
2) If I understand it correctly (I probably don't) the ivars set in test.h represent the actual memory where as the #properties are just ways to access that memory. So outside of the implementation I can't access _highscore without going through the property.
What I don't understand
Basically what I don't get about this situation is whether or not I need to use the ivars at all or if I can just use #property and #synthesize. It seems like the ivars are just extra code that don't really do anything but confuse me. Some of the most recent tuts I've seen don't seem to use ivars but then some do. So is this just a coding preference thing or is it actually important? I have tried searching through Apple's Documentation but I get rather lost in there and never seem to find what I'm looking for. Any guidance will be greatly appreciated.
You can think of the syntax for synthesizing properties as #synthesize propertyName = variableName.
This means that if you write #synthesize highscore = _highscore; a new ivar with the name _highscore will be created for you. So if you wanted to you could access the variable that the property is stored in directly by going to the _highscore variable.
Some background
Prior to some version of the compiler that I don't remember the synthesis statement didn't create the ivar. Instead it only said what variable it should use so you had to declare both the variable and the property. If you synthesized with a underscore prefix then your variable needed to have the same prefix. Now you don't have to create the variable yourself anymore, instead a variable with the variableName that you specified in the synthesis statement will be created (if you didn't already declare it yourself in which case it is just used as the backing variable of the property).
What your code is doing
You are explicitly creating one ivar called highscore when declaring the variable and then implicitly creating another ivar called _highscore when synthesizing the property. These are not the same variable so changing one of them changes nothing about the other.
Should you use variables or not?
This is really a question about preference.
Pro variables
Some people feel that the code becomes cleaner if you don't have to write self. all over the place. People also say that it is faster since it doesn't require a method call (though it is probably never ever going to have a measurable effect on your apps performance).
Pro properties
Changing the value of the property will call all the necessary KVO methods so that other classes can get notified when the value changes. By default access to properties is also atomic (cannot be accessed from more then one thread) so the property is safer to read and write to from multiple thread (this doesn't mean that the object that the property points to is thread safe, if it's an mutable array then multiple thread can still break things really bad, it will only prevent two threads from setting the property to different things).
You can just use #property and #synthesize without declaring the ivars, as you suggested. The problem above is that your #synthesize mapped the property name to a new ivar that is generated by the compiler. So, for all intents and purposes, your class definition is now:
#interface Test : NSObject {
int timesPlayed;
int highscore;
int _timesPlayed;
int _highscore;
}
...
#end
Assigning a value directly to the ivar timesPlayed will never show up if you access it via self.timesPlayed since you didn't modify the correct ivar.
You have several choices:
1 Remove the two ivars you declared in your original post and just let the #property / #synthesize dynamic duo do their thing.
2 Change your two ivars to be prefixed by an underscore '_'
3 Change your #synthesize statements to be:
#implemenation Test
#synthesize timesPlayed;
#synthesize highscore;
...
I typically just use #property and #synthenize.
#property gives the compiler and the user directions on how to use your property. weather it has a setter, what that setter is. What type of value it expects and returns. These instructions are then used by the autocomplete (and ultimately the code that will compile against the class) and by the #synthesize
#synthesize will by default create an instance variable with the same name as your property (this can get confusing)
I typically do the following
#synthesize propertyItem = _propertyItem;
this will by default create a getter and a setter and handle the autorelease as well as create the instance variable. The instance variable it uses is _propertyItem. if you want to access the instance variable you can use it as such.
_propertyItem = #"Blah";
this is a mistake tho. You should always use the getter and setter. this will let the app release and renew as needed.
self.propertyItem = #"Blah";
This is the better way to handle it. And the reason for using the = _propertyItem section of synthesize is so you cannot do the following.
propertyItem = #"Blah"; // this will not work.
it will recommend you replace it with _propertyItem. but you should use self.propertyItem instead.
I hope that information helps.
In your example, #synthesize timesPlayed = _timesPlayed; creates a new ivar called _timesPlayed and the property refers to that ivar. timesPlayed will be an entirely separate variable with no relation whatsoever to the property. If you just use #synthesize timesPlayed; then the property will refer to timesPlayed.
The purpose of the underscore convention is to make it easier to avoid accidentally assigning directly to an ivar when you want to be doing it through the property (i.e. through the synthesized setter method). However, you can still acces _timesPlayed directly if you really want to. Synthesizing a property simply auto-generates a getter and setter for the ivar.
In general you do not need to declare an ivar for a property, although there may be special cases where you would want to.
This may be an old question.. but in "modern times", #synthesize- is NOT necessary.
#interface SomeClass : NSObject
#property NSString * autoIvar;
#end
#implementation SomeClass
- (id) init { return self = super.init ? _autoIvar = #"YAY!", self : nil; }
#end
The _underscored backing ivar IS synthesized automatically... and is available within THIS class' implementation, directly (ie. without calling self / calling the automatically generated accessors).
You only need to synthesize it if you want to support subclass' ability to access the _backingIvar (without calling self), or for myriad other reasons, described elsewhere.

How to access protected variable in Objective-C?

I know protected variable can't be access out side the class but is it possible to access them in Category or in SubClass, I think it's not possible for Subclass but is it the same case for Category ?
What I want to do is some modification to a library form github but I don't want to modify the original source code. I want to achieve this through subclassing or using category but the problem is I want reference to some protected variable.
Protected variable in .m file:-
#interface Someclass() {
NSMutableDictionary *viewControllers;
__weak UIViewController *rootViewController;
UIPageViewController *pageController;
}
#end
A category cannot access private instance variables nor can a subclass do that.
As you have access to the source code and just don't want to change the original source code you could create another class with exactly the same data structure. (same variable names and types declared exactly in the same way and sequence).
#interface Shadowclass() {
NSMutableDictionary *viewControllers;
__weak UIViewController *rootViewController;
UIPageViewController *pageController;
}
#end
Then add getters and setters to Shadowclass to make the values accessible.
The do:
Someclass *someclass = ... // you get the object from somewhere somehow.
object_setClass(someClass, [ShadowClass class]);
How someclass is of the type ShadowClass and you can access the getter and setter. Frankly I am not sure how the current compiler allows for accessing the getters directly of if you are allowed to cast someClass now an ShadowClass type object variable, but you can use performSelector for accessing the getters or setters.
Accessability of getters and setters directly like [shadowClass rootViewController:xxx] may even vary whether you are using ARC or not. (The compiler's behaviour here may even be configurable. This, too, I do not know on detail out of the top of my head.)
However, I am not sure whether I really want to recommend that! You may find less "hacky" alternatives.
And do not underestimate the importance of creating exactly the same structure for Shadowclass as for Someclass!

Why are there only sometimes compiler errors when accessing a property without self?

I noticed that in some old versions of Xcode you could use properties of objects without self just fine.
Now it gives me an error when I try to access my property without self, but today I'm writing this code, and it works fine, and doesn't give me any errors.
[aCoder encodeObject:itemName forKey:#"itemName"];
Why is it this way? Why don't I get an error in this case? Why is an error raised in other cases? Why can't this behavior be unified, and what should I use?
You have never been able to access properties without self. If you didn't use self, then you were directly accessing the instance variable that had the same name as the property. This has caused endless issues for many developers.
This is why the latest compilers (in the latest versions of Xcode) generate property ivars with a leading underscore. This way, if you forget to use self when trying to access the property, you get an error because there is no ivar with the same name.
To unify your experience you should use the following pattern with older compilers:
Define #property int foo;. Then define ivar int _foo. And then use #synthesize foo = _foo;.
With newer compilers you simply declare #property int foo and you are done. The compiler will generate the ivar int _foo for you.
In both cases you use self.foo for the property and _foo to directly access the ivar.
Whenever you create a property with new LLVM compiler, it creates an ivar named _property .
If you don't over-ride the auto-synthesized then you need to use _property or self.property.
In your case it looks like you are using old compiler (i.e. coming with XCode4.3 bacwards) or you have over-riden auto-synthesized as:
#synthesize aCoder;
I assume you mean this warning:
A lot of projects do not enable many warnings in their build settings, so that could be one reason that you aren't seeing this warning.
There are also certain methods where it is common to access instance variables directly, and Xcode will ignore direct ivar access; these include init* and dealloc methods (but unfortunately not getter/setter methods).
If you define properties in a class and #synthesize them to use the same naming, then you can access them without self
e.g.
In .h
#property(nonatomic, copy) NSString *str1;
In .m
#synthesize str1 = str1;
str1 = #"hello";
self.str1 = #"hello"; // Or this
If you don't use explicit #synthesize, then XCode automatically does #synthesize property = _property (since recently) so you can do the following
In .h
#property(nonatomic, copy) NSString *str1;
In .m
_str1 = #"hello";
self._str1 = #"hello"; // Or this
You won't be able to use self if the property is defined in a parent class. You'll have to synthesize in your current class to be able to use it.

Objective C shenanigans

In my quest to be the grandmaster of Objective C, I keep running into it's subtleties, which I want to share with ya'll and gain an understanding why
1) I have two init methods, the one that is inherited by NSObject for my Objective C class and one is a custom method that I create off my own, let's say
initCustomMethod:(int)par1 argument2:(int)par2;
My Aim is to call initCustomMethod through the provided init method, essentially
-(id)init{
return [self initCustomMethod:1 argument2:3];
}
Naturally, maintaining the order, I have init appearing before initCustomMethod in the .m file. Xcode warns me telling me that the initCustomMethod is not found, I go ahead and shuffle the order and have init appearing after initCustomMethod is declared and there is no such warning message anymore and everything is fine.
I concur that the order is important since it's essentially derived from C, however I am not sure of this. Because, i shuffled the order of some properties and their custom methods, with the properties #synthesize being declared after the custom setter method for a given property, but there was no such error replica.
Can anyone point out the malice here?
Thanks guys!!!
Very cool guys, thanks for helping me out with this. Also, since I have a custom init method, I am initializing the super in this method and using the original init method to call the custom init method.
Anything wrong with this?
Before you reference it anywhere, you should declare initCustomMethod:argument2 in your interface, which would usually be in your header file.
For example, you would usually have a .h file that looks like:
#interface MyClass
{
//instance variables
int anInstanceVariable;
}
// properties
#property (nonatomic, assign) int aProperty;
// methods
-(id)initCustomMethod:(int)par1 argument2:(int)par2;
#end
And if you did this, the order in which you define init and initCustomMethod:argument2: won't matter. This is because the declaration tells the compiler that you are going to define the method, and what it will look like, so it isn't confused when you use it later.
It's a bad idea in Objective-C to use a function or a method before it is either declared or defined. Putting initCustomMethod:argument2: before init means that the former is already defined in the latter. But if you'd just declare it in the header, it wouldn't matter which order they went in.
Add your custom method name in your header file - the compiler just goes through things in order. If you don't have a forward declaration, the compiler won't know what to do with that call. You're going to need to put it in the header if you want other parts of your program to be able to call it anyway.

why to declare some instance variables as properties

Though this is somewhat a very basic question but I have some doubts still left after reading so many documents and questions on stackoverflow.com.
I want to know why to declare some instance variables as properties.
MYViewController.h
#interface MyViewController : UIViewController {
UIButton *btn;
NSString *name;
}
#property (nonatomic, retain) UIButton *btn;
#property (nonatomic, retain) NSString *name;
MyViewController.m
#implementation MyViewController
#synthesize btn;
-(void) viewDidLoad()
{
[btn setTitle:#"Hello" forState:UIControlstaeNormal]; //this is first way where there is no need to declare btn as property
[self.btn setTitle:#"Hello" forState:UIControlstaeNormal]; //this is second way where we do need to decalre btn as property as we are accessing it through self
//Setting value of name
name = #"abc"; //this is first way where there is no need to declare name as property
[self setName:#"abc"; //this is second way where we do need to declare name as property as we are accessing its aetter method through self
}
Now in the above code I wanna know when we can use the getter/setter methods of btn variable without declaring it as property then what is the need to declare it as property and which is the better way to set the value of "name".
Somewhere I read that when you want your instance variables to be accessed my other class objects then you should declare them as instance variables. Is it the only situation where we should declare them as properties.
Basically I am a little confused about in which situations to declare the instance variables as properties.
Please suggest.
Thanks in advance.
In short, you don't have to declare instance variables as properties unless you want to.
You declare a variable as a property in order to auto-generate getter and setter methods. In your property declaration you can specify how you want them set up (retain vs assign, atomic vs nonatomic). Then, the getter and setter are generated with the #synthesize directive.
So, again, there is no right or wrong way to use properties. Some people never use them, some people make every variable a property. It's really up to you.
typically, you'll use them because:
1) the property belongs in the public interface of the class
used when the class needs to expose a given method. the downside is that clients and subclasses may abuse the public interface (all objc methods are public, where visible), unless you're careful to hide these details (which is also a pain at times). sometimes you're forced to go well out of your way in order to achieve the class interface you need (with the proper levels of visibility).
2) you want auto-generated accessors
implementing nonspecialized accessors is tedious, and error prone. it's better to save the time and let the compiler generate them for you.
3) to document behavior
sometimes it's better to write #property (copy) NSString * title; instead of over-documenting the expected result.
4) stricter selector matching with dot-syntax
the compiler performs stricter selector matching. prefer to catch the errors/issues at compilation, if possible.
5) to force the subclasses to use them instead of handling the ivars directly
objc ivars are protected by default. you'll often want them to be private (depending on how the class is used and distributed, or just to ensure the subclass uses the base class correctly).
there are a ton of reasons for this. threading and maintenance are the big ones.
if you declare the ivar as private and provide a property for the subclass to use, then the subclass is forced to use the property in their implementation (although there are ways they could cheat) rather than giving them direct access to the ivar.
so... it ultimately depends on your preference, and the implementation details of your class, paired with the interfaces you're using. i don't think there's a hard and fast rule here - lesser evils and convenience are key motivations.