ARC complaining about instance vairiables - ios

I am trying to convert non-ARC project to use ARC but for some reason its complaining about
the use of all instance variables.
#property (nonatomic,retain)id myvariable;
results in
Error : "Use of undeclared variable _myvariable"
there are some places in my code where I don't want to modify retain count but do an assignment to the property. so I use an instance variable.
adding #syhtnesize myvariable =_myvariable resolves this problem but I am trying to figure out the right way to fix this.
Possible solutions:
1) Add synthesize
2) replace use of instance variable with self.myvariable and make property assigned.
EDIT:
Extension of problem ARC errors

With all the arc stuff
#property (nonatomic, strong) Something *myVariable;
is accessible by both
self.myVariable;
and
_myVariable;
No need to use #synthesize

It sounds like you've hit a backward compatibility feature.
Since Xcode 4.4 property declarations no longer require an #synthesize statement and without one the compiler auto-generates an _propertyName instance variable.
However with an #synthesize propertyName, as you would pre-Xcode 4.4, then the compiler will auto-generate an propertyName - note no underscore - instance variable.
The compiler messages warning you "Use of undeclared variable _myvariable" suggest you have switched the code to use underscores but still have some #synthesize myvariable statements.
Your use of #synthesize myvariable = _myvariable specifies the name to use for the instance variable directly, and so solves your problem, but removing the #synthesize completely is the usual approach.

It depends what you need. If you declare property:
#property (strong) NSString *myvariable;
And you want to change name of the private ivar to something different that _myvariable you have to add
#synthesize myvariable = _myVarNewName
but if you want to use exactly the same name with underscore on the front just remove #synthesize (works with iOS 6 and above) and the compiler do the rest so you can access the private variable like _myvariable or public like self.myvariable.

Related

What is the difference between synthesize propertyname = _propertyname

I am new to objective c. I create a property at .h header file of the class and then i synthesize.
What is the difference between
#synthesize propertyname;
and
#synthesize propertyname = _propertyname;
Both work but what is the purpose of using the first one or the second one.
Any help appreciated.
First of all you need not write #synthesize propertyname anymore.
In Objective-C when you declare a property, compiler auto generates its accessor methods for you by default. These accessor methods can be getter and setter if property is both read and write property else just a getter if it's a readonly property.
Compiler uses internal variables (called iVar) under the hood of these accessor methods implementation. (You can obviously provide your own implementation of these accessor methods and also provide your own internal variables as well)
What is the difference between #synthesize propertyname; and #synthesize propertyname = _propertyname;
when you declare a #synthesize propertyname; compiler auto generates and uses an iVar named propertyname and uses it in its default accessor implementation and you can also use it as propertyname in your .m file as compiler has already declared it for you.
property = #"abcd";
when you declare a #synthesize propertyname = _propertyname; compiler auto generates and uses a iVar named _propertyname and uses it in its default accessor implementation and you can also use it as _propertyname in your .m file as compiler has already declared it for you.
_property = #"abcd";
Broadly speaking the general difference between the two statement is just the change in name of iVar (usage of it are different though)
what is the purpose of using the first one or the second one.
As I already mentioned you need not use either of them in a normal usecase. Compiler already does that for you.
We used to write #synthesize propertyname; when we neither had any specific reservation about the name of ivar nor wanted to provide our own private variable as ivar to a specific property (Explained in detail below). This was simpler than explicitly specifying the name of iVar and we knew that compiler will generate an ivar with same name as property for us.
we typically wrote #synthesize propertyname = _propetyname when #synthesize propertyname; wasn't available or when we wanted our iVar to follow a specific nomenclature ('_' following name of property) or when we wanted to use our own private variable as iVar to a property.
In both the cases #synthesize was handy because it would relieve us from writing a boiler plate code like adding setter and getter methods for properties declared.
How to use custom variable as ivar for a property?
#interface SynthesizeExplorer : NSObject
#property (nonatomic,strong) NSString *name;
#end
#implementation SynthesizeExplorer
NSString *blaBlaName;
#synthesize name = blaBlaName;
#end
If you look at the implementation you will see that property name is backed by a internal variable named blaBlaName and not by the typical compiler generated ivar like name or _name.
As of today the only reason I see for the usage of #synthesize when you wanna use your custom internal variable to back the property you have declared. Otherwise I dont see any point in writing neither #synthesize propertyname; or #synthesize propertyname = _propertyname;

_iVar and #property?

I see someone writes codes like this
#interface SomeClass:<NSObject>{
NSString * _iVar;
}
#property(nonatomic,retain)NSString *iVar;
and in implement file
#synthesize iVar = _iVar;
But I always like write codes like this:
#interface SomeClass:<NSObject>
#property(nonatomic,retain)NSString *iVar;
and in implement file
#synthesize iVar = _iVar;
They all works fine, and I can use an instance someClass to get iVar "someClass.ivar".I just know why?
You now don't even have to synthesize the iVars anymore. The latest Xcode will automatically create a backing instance variable for each property, with the property name prefixed with an underscore.
In Objective-C when you are using anything via "." (dot syntax), it is accessing property. You have declared and synthesize a property with name iVar, so you can access it with someClass.iVar.
When you are declaring a property, a variable is automatically created with it. So, even if you do not create a variable, it will be there.
To avoid ambiguity, people are creating properties and iVar with different names. So, they can identify if the variable is being used or a property is being used. In that case people let the compiler know that a particular variable is associated with a property by low way:
#synthesize iVar = _iVar;
If you want access variable directly outside the class instead of property, you should use "->" (arrow syntax).

Should I declare variables in interface or using property in objective-c arc?

approach 1:
#interface MyController : UIViewController {
UILabel *myText;
}
#property (nonatomic, strong) UILabel *myText;
approach 2:
#interface MyController : UIViewController
#property (nonatomic, strong) UILabel *myText;
approach 3:
#interface MyController : UIViewController {
UILabel *myText;
}
I have read some articles talking about this kind of stuff but I still do not really realize which approach I have to adopt.
I also found that someone said approach 1 is a old way so I would like to know the best practice for ios sdk 6 using ARC.
I know that declaring variables using property is a easy way for generating getter and setter and someone suggested using it. However, I would like to ask in case a variable is not for calling by another class, is it necessary for the variable using property? and set it as private variable inside the interface? Or is it better for a variable only declaring inside the interface? I would like to learn the best practice so please forgive me if this is a silly question.
Moreover, some developers write #synthesize in this way
#synthesize myText=_myText;
but some write this:
#synthesize myText;
I would also want to know the difference and which one is preferable?
Thank you very much!
The most modern way1:
whenever possible, declare properties
don't declare iVars separately 2
don't #synthesize 3
locate as few properties as possible in you .h file 4
locate as many properties as possible in a class extension in your .m file 5
1 As of Xcode 4.5.2. Most of this applies back to 4.4, some of it won't compile on 4.2 (the last version available under Snow Leopard). This is preprocessor stuff, so it is all compatible back at least to iOS5 (I haven't tested on iOS4 but that should also be OK).
2 There is no point in declaring an iVar as well as a property. I am sure there are a few obscure cases where you would want to declare iVars instead of properties but I can't think of any.
3 Xcode will create an iVar with the same name as the property, preceded by an _underscore. If you (rarely) need some other kind of behaviour, you can manually #synthesize property = someOtherName. #vikingosegundo links us to this article on dynamic ivars, which is a use case for #synthesize. #RobNapier comments that you do need to #synthesize iVar = _iVar (bizarrely) if you are creating your own getters (readonly) and setters (read/write) for a property, as in this case the preprocessor will not generate the iVar for you.
4 The general rule with your interface: keep it as empty as possible. You don't actually need to declare your methods now at all, if they are for private use. If you can get the code to work without an interface declaration, that's the way to go.
5 This is an #interface block in your .m file, placed above your #implementation:
#TestClass.m
#interface TestClass()
//private property declarations here
#end
#implementation TestClass
...
You may also want to use #synthesize if you like a nice table of contents of your #synthesized properties that you can refer to and comment for clarity and organization.
Also, an #synthesize allows you to set a breakpoint on the property and trap when its value is changed.
When the compiler does everything for you, you end up being distanced from what is really happening and ignorant to it. However, not having to type out everything yourself all the time is also nice.

Instance variables, properties and transition to ARC

Finally I'm transitioning to ARC. Sounds too late but all my projects have retrocompatiilty to 3.0 (any news about App Store unsupporting?) so I can't use it. But now I'm working in a new project with base deployment in iOS 5 so I'm using ARC.
My question is so simple. I'm used to declare private instance variables and public properties. For example:
#interface MyClass : NSObject {
#private
Var *aVar_;
Var *anotherVar_;
}
#property (nonatomic, readonly) Var *aVar;
#end
#implementation MyClass
#synthesize aVar = aVar_;
#end
Inside the class I work with instance variables, not properties.
But now I'm trying to avoid instance variables because I think there are not neccessary and redundant if I use proeprties, and I read time ago that is better to use properties instead of instance variable, but I'm not sure. That class now seems like that
#interface MyClass : NSObject
#property (nonatomic, readwrite, strong) Var *aVar;
#end
#interface MyClass()
#property (nonatomic, readwrite, strong) Var *anotherVar;
#end
#implementation MyClass
#synthesize aVar = aVar_;
#synthesize anotherVar = anotherVar_;
#end
In this case I'm still using instance variables (underscored) to manage my data because is less verbose and ARC takes into account all memory issues, but I don't know if that is correct.
Also I have another question. The property of aVar in the first chunk of code is readonly but if I use only properties I have to make that property readwrite. If I want to make the public property readonly, do I have to declare a public readonly property in the #interface and a private readwrite in private #interface?
Thank you so much.
The answer to your questions is somewhat complex, but generally you have the swing of it.
Since ARC does all the memory management for you, its often simpler to just use an ivar (private to the class, declared in the implementation) for your internal needs. In that case all usages just use the name.
With properties, you can as of Xcode 4.4 let Xcode synthesize the setter and getter, as well as the ivar. Auto-synthesized ivars are created with a leading "_" character.
You can define a property as readonly in the implementation, leave it as readonly, and set it in your code as '_foo = ....'. [Many on this site would consider this a bad practice, my point is you can do it.]
Xcode 4.4 has a warning titled "Implicit Synthesized Properties" with a default of NO. This creates a warning if you do not provide a #synthesize statement for each property, even though it will do the synthesis anyway.
Personally, I use ivars whenever I can, and only define properties when I need to either make something public to other classes, or I have categories declared in multiple files (in which case I put the interface declaration of the class extension in its own file along with properties defined in it.)
With the new Objective-C update you don't even need to synthesize the property. All you need to do is declare #property (strong, nonatomic) Var *aVar; and the compiler will automatically add the synthesizing, backing the self.aVar property with an _aVar instance variable.
If you declare a property, your implementation should generally use that property even though ARC reduces some of the memory management errors.
In init some prefer to avoid using properties because doing so might trigger KVO on an object (self) that is only partially initialized.

#property declaration without #synthesizing

I am following Big Nerd Ranch iOS Programming by Joe Conway and am kinda puzzled when I saw the following code.
WebViewController.h
#import <Foundation/Foundation.h>
#interface WebViewController : UIViewController
#property (nonatomic, readonly) UIWebView *webView;
#end
WebViewController.m
#import "WebViewController.h"
#implementation WebViewController
- (void)loadView
{
// Create an instance of UIWebView as large as the screen
// Tell web view to scale web content to fit within bounds of webview
}
- (UIWebView *)webView
{
return (UIWebView *)[self view];
}
#end
Shouldn't one synthesize the property declared in .h file? Xcode didn't give an warning either (which it usually does when I declare a property with synthesizing).
By the way, in the book, he also mentioned
In WebViewController.h, add a property (but not an instance variable)
Doesn't declaring a property automatically generate an instance variable for you? Let me know what I missed. Thanks.
This is a good question, and one to which I think the answer is a bit subtle and often not immediate to people starting out with Objective-C. First of all let's dispel a myth about properties. The myth is this:
Objective-C properties are related to instance variables.
This is not necessarily true. It is often true, but not true in every case. Here's what is true:
An Objective-C property declares a getter and a setter method
(Or in the case of a readonly property, just a getter). In particular when you declare a property called foo (for the sake of discussion, let's assume it's not readonly), the only thing you are really doing is telling the compiler that the class you're writing has a method called -foo and a method called -setFoo:. By adding an #synthesize foo; declaration into the .m file, you are telling the compiler to generate those methods itself. Here you are saying, "Compiler, create an instance variable (also called foo) and generate implementations for my -foo and setFoo: methods that access this instance variable. In particular, return the value of this variable in -foo and set the value of the variable in -setFoo:.
Note, it is not necessary to have the compiler synthesize the methods for you. Rather, you can write -foo and -setFoo: yourself. Furthermore, you are not in any way required to create an instance variable to support the implementation of these methods. You can write them however you wish.
To summarize: the #property only tells the compiler about the existence of the getter and setter methods. You can then either: #synthesize the methods in your .m or write the methods yourself.
This is because the "webView" getter method is implemented in the .m file and because of that, "#synthesize" isn't necessary.
If a "webView" method wasn't explictly created in code, then the compiler would complain about the property not being synthesized. Synthesizing a "read only" property, in this case, would only create a "getter" method which would do roughly the same thing you see in the code up there.
And yes, according to the Apple docs on declared properties, it says this about "#synthesize":
You use the #synthesize directive to tell the compiler that it should synthesize the setter and/or getter methods for a property if
you do not supply them within the #implementation block. The
#synthesize directive also synthesizes an appropriate instance
variable if it is not otherwise declared.

Resources