Obj-C #synthesize [duplicate] - iphone

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Prefixing property names with an underscore in Objective C
iPhone App Developer Beginner here:
in .h
#property (nonatomic, retain) IBOutlet UILabel *detailDescriptionLabel;
in .m
#synthesize detailDescriptionLabel = _detailDescriptionLabel;
I'm used to seeing
#synthesize detailDescriptionLabel;
the = _ is throwing me off, what is this doing?

Each property is backed by an instance variable. The language allows for them to be named differently. By doing #synthesize detailDescriptionLabel = _detailDescriptionLabel;, you're basically saying that use _detailDescriptionLabel as the backing instance variable for the property detailDescriptionLabel. If you just do #synthesize detailDescriptionLabel;, it implicitly understands that the instance variable has the same name.

n .h
UILabel *_detailDescriptionLabel;
}
#property (strong, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
in .m
#synthesize detailDescriptionLabel = _detailDescriptionLabel;
This line means that the property "detailDescriptionLabel" will have a setter and getter for the class attribute named "_detailDescriptionLabel"
If the name was the same, you will have
#synthesize detailDescriptionLabel;

Related

Local declaration of "speed view" hides instance variable

So I have been searching in a few hours for why my iPhone app hates me. This is the error I get:
Warning: local declaration of 'speedView' hides instance variable.
Here is my .m file
#implementation MainViewController
#synthesize speedCount;
#synthesize speedView;
#synthesize popoverController;
- (void)setspeedView:(UILabel *)speedView
{
[speedView setText: [NSString stringWithFormat:#"%d",speedCount]];
speedCount = 0;
speedCount++;
}
.h file
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MainViewController : UIViewController <LoginDelegate,WEPopoverParentView,PopoverControllerDelegate,MainMenuDelegate,MKMapViewDelegate,UIActionSheetDelegate,UIAccelerometerDelegate, CLLocationManagerDelegate>
{
AppDelegate *appDelegate;
IBOutlet MKMapView *userMap;
IBOutlet UILabel *speedView;
CLLocationManager *locationManager;
}
#property (strong, nonatomic) IBOutlet UILabel *speedView;
#property(nonatomic) int speedCount;
I really don't understand why it says that I am hiding the instance variable.
You have a ivar (an instance variable) called speedView.
In your method
- (void)setspeedView:(UILabel *)speedView
speedView is a local variable whose name clashes with the ivar.
If you are using a modern version of the compiler just remove the #synthesize directive.
It will be automatically added by the compiler in this form
#synthesize speedView = _speedView
which will create the ivar _speedView, whose name doesn't clash anymore with the local variable.
Also note that declaring both the instance variable and the property is redundant. The ivar will be automatically created by the (implicit) #synthesize directive.
Here's a "modern" version of your class:
.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MainViewController : UIViewController <LoginDelegate,WEPopoverParentView,PopoverControllerDelegate,MainMenuDelegate,MKMapViewDelegate,UIActionSheetDelegate,UIAccelerometerDelegate, CLLocationManagerDelegate>
#property (strong, nonatomic) IBOutlet UILabel *speedView;
#property (strong, nonatomic) CLLocationManager *locationManager;
#property (strong, nonatomic) IBOutlet MKMapView *userMap;
#property (strong, nonatomic) AppDelegate *appDelegate;
#property (nonatomic) int speedCount;
.m
#implementation MainViewController
- (void)setspeedView:(UILabel *)speedView {
[speedView setText:[NSString stringWithFormat:#"%d", self.speedCount]];
self.speedCount = 0;
self.speedCount++;
}
Please note:
properties are nice: use them whenever you can
#synthesize is implicit
the implicit version of #sythesize declares a _ivar for the property ivar
always access variables through the getters/setters, i.e. self.ivar, a part from init methods. If you need to access the var directly use _ivar or self->_ivar
As a final remark, this looks a bit weird
self.speedCount = 0;
self.speedCount++;
and it could be replaced with
self.speedCount = 1;
Are you sure it's what you mean? Also, as noted in the comments by others, you are not using the method parameter speedView. That smells bad and you may want to double check your implementation.

nonatomic and readonly property in Objective-C

A few times already I wanted to make a property, which is nonatomic and readonly at the same time.
This has the advantage that I can override the getter and check if an instance has already been created or not. And if not I can simply create it.
At the same time I can protect it from being overwritten.
.h
#property (strong, readonly, nonatomic) Foo *bar;
.m
- (Foo *)bar {
if (!_bar) {
_bar = [[Foo alloc] init];
}
return _bar;
}
Whenever I do this, the compiler doesn't create an instance variable for me, so _bar doesn't exist.
Why? How can I create a readonly nonatomic property?
Your property declaration is correct. I believe the problem here is that, because your property was declared as readonly, the compiler didn't automatically synthesize an underlying instance variable. The solution in this case is to synthesize one yourself using...
#synthesize bar = _bar;
You could create a private setter:
#interface YourClass() // In the .m file
#property (strong, readwrite, nonatomic) Foo *bar;
#end
Then when assigning the variable:
self.bar = [[Foo alloc] init];
EDIT
Mark Adam's answer is also correct.
In the implementation add #synthesize bar = _bar.

Regarding #property and #synthesize [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
#property #synthesize
Hi i found in so many apps after creating the #property we have to declare #synthsize also but i would like to know the difference between
NSArray *_failedBankInfos;
#property (nonatomic, retain) NSArray *failedBankInfos;
#synthesize failedBankInfos = _failedBankInfos;
and
#property (nonatomic, retain) NSArray *_failedBankInfos;
#synthesize _failedBankInfos;
can anyone explain this please.
#synthesize will map the property with the declaration of the iVar i.e. will create the getter and setter methods without needing the developer to implement the accessor methods explicitly and the memory management in them(as per the parameters inside the #property eg: retain, copy.).
So, when we use the *_iVar(which is supposed to be a private iVar as per the naming conventions) and we want to have the accessor methods look like the ones without the "_" eg: [aClass getIVar] and not [aClass get_iVar] we map the _iVar with the #synthesize iVar=_iVar to the property #property(retain/copy/assign,atomic/nonatomic) NSObject *iVar;
PS: Also refer the Automatic Reference Count in iOS>=5.0 at Ray's

When declaring class properties/variables, can you just declare it via #property?

I've noticed that some generated classes only declare class properties/variables via #property, and don't include them within the #interface, as such:
#interface AddItemViewController : UITableViewController {
}
#property (nonatomic, retain) UITextField *itemName;
I was just curious if that's an acceptable way to do it, or if that is done for different reasons?
I normally do this:
#interface AddItemViewController : UITableViewController {
UITextField *itemName;
}
#property (nonatomic, retain) UITextField *itemName;
I declare it first in the #interface and then add the #property for it...
* Update *
I just wanted to update this a bit, because it's still not 100% clear to me.
I always thought that to declare a #property, you first needed to declare it within the #interface first, and then I saw this:
#interface mInventoryAppDelegate : NSObject <UIApplicationDelegate> {
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
#property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
#property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#end
All of those #property declarations are declared only as #properties, and not within the #interface.
For example, if I had say NSString *myString - I can declare that in the #interface and not as a #property and still have access to it no problem, but the getters and setters won't be created. I could also declare it in both. But what if I just declare it as #property, as such:
#interface AddItemViewController : UITableViewController {
}
#property (nonatomic, retain) NSString *myString;
Notice how I didn't add it between the #interface { } - how does it differ.
Sorry for repeating, but I'm just trying to reword this so that I can get an answer that makes more sense to me.
With the "modern" runtime, which the iPhone uses, the compilers can create the instance variable for you. Just use:
#synthesize itemName;
or if you prefer...
#synthesize itemName=_itemName;
...in your implementation. The compilers will then create ivar 'itemName' or '_itemName'.
This is of course for the case that the property is a simple getter/setter for one particular instance variable.
EDIT: NVM, per #bbum, what I thought of in my mind as the "32-bit" sim is actually the older simulator that didn't behave like the new runtime. The newer simulator is still 32-bit, and supports this behavior. See his comment below.
update
In response to your updated question:
The "interface" for a class is everything up to the #end. I think what you are calling "interface" is actually just the instance variables within the {}. What is between the {} are the instance variables for your class. The whole #interface includes those instance variables PLUS the method and #property declarations between the {} and the #end.
So I think what you are really asking is if you have a #property in your #interface, and that #property is just a simple getter/setter pair, then do you need to declare a "backing" instance variable also in your #interface, within the {}.
The answer for iPhone is NO. The compilers (both) can create that instance variable for you.
I hope that answers the question?
It is perfectly acceptable to do it this way. You would however need to implement the setter/getter methods yourself. These can not be created using the #synthesize syntax.
One reason to use this approach could be to have the properties based on something more complex than just setting and getting a value. It doesn't however make much sense for simple Nib connections as in your example.

Assignment from incompatible pointer type?

I am completely new to iPhone development and basically any C language at all. I understand the concept of variables and so forth, so I'm trying to use them in basic way to get a better grasp on the concept. Unfortunately, I'm getting compiler warnings when I try to do something very simple: I just want to assign my 5 variables values.
ViewController.h code:
#interface MyApplicationViewController : UIViewController {
IBOutlet UITextView *variable1;
IBOutlet UITextView *variable2;
IBOutlet UITextView *variable3;
IBOutlet UITextView *variable4;
IBOutlet UITextView *variable5;
}
[I know that theoretically I could connect those variables to text views in IB, but I'm not]
#property (nonatomic, retain) IBOutlet UITextView *variable1;
#property (nonatomic, retain) IBOutlet UITextView *variable2;
#property (nonatomic, retain) IBOutlet UITextView *variable3;
#property (nonatomic, retain) IBOutlet UITextView *variable4;
#property (nonatomic, retain) IBOutlet UITextView *variable5;
#end
ViewController.m code:
#implementation MyApplicationViewController
#synthesize variable1;
#synthesize variable2;
#synthesize variable3;
#synthesize variable4;
#synthesize variable5;
- (void)viewDidLoad {
variable1 = "memory text1"; [Warning]
variable2 = "memory text2"; [Warning]
variable3 = "memory text3"; [Warning]
variable4 = "memory text4"; [Warning]
variable5 = "memory text5"; [Warning]
}
I do not deallocate my variables because I want to keep them in memory until the application is completely terminated. Why am I getting these warnings? Am I doing anything wrong? All I'm intending to do here is save the variables' values (memorytext1, memory text 2, etc.) in the memory. I've looked at the other conversation about this warning on Stack Overflow, but their problem didn't seem to match mine, although the warning was the same. Please don't say anything too complicated, because I am still new to this. Thanks!
There're 2 problems:
1st problem is that you're trying to assign string to your text fields variables - if you want to set field's text then you should use its text property
2nd problem (that actually gives you compiler warning) is that "string" means c-string literal - you should use #"string" instead
So correct code to set textfield's text should be
variable1.text = #"text1";
You are missing the # at the beginning of the text!
variable1.text = #"memory text1";
variable2.text = #"memory text2";
variable3.text = #"memory text3";
variable4.text = #"memory text4";
variable5.text = #"memory text5";
Vladimir is correct, assuming you are using a NIB file to assign the UITextView properties. If you are not using a NIB your variables will be nil and your strings will not be assigned anywhere.