.h instance variable declaration - objective-c

I'm having a hard time understanding why the following textfield is declared twice in some tutorials.
In the .h file:
# include <UIKit/UIKit.h>
#interface MyViewController : UIViewController {
UITextField *name; // <----- What do I need this for? Is it the same as below?
}
#property (nonatomic, strong) IBOutlet UITextField *name; // <----- Same as this?
#end
At first I thought this would be something like an instance variable, but they are only declared here in the .m file, right?
.m file
#import "MyViewController.h"
#implementation UIViewController {
NSString *myString; // <----- This is an instance variable, right?
}
What's the "UITextField *name;" for? Don't I only need the second one with the #property in front? Thank you.

This is an old way, just use property is OK.
If you declare both, you must use #synthesize name; in your .m file to make self.name same as name.
XCode4.2 auto synthesize name = _name. So use self.name as much as possible in your .m file.
Variable in {} just use for internal or private, when you don't want implement setter and getter.

If you are targeting iPhone OS or 64-bit Mac OS X then you do not need to define ivars for your properties. Take a look at Dynamic ivars: solving a fragile base class problem

Related

Modern Objective-C and #synthesize

I'm trying convert my code to Modern Objective-C style. How i read here http://www.techotopia.com/index.php/The_Basics_of_Modern_Objective-C": "In the case of Modern Objective-C, however, the synthesis takes place by default, making the use of #synthesize declarations unnecessary. When using default property synthesize, instance variable properties are accessible from within code using the property name prefixed with an underscore."
However, I have:
Relationship.h
#interface Relationship : NSObject <NSCoding>
//...
#property(nonatomic, weak) Person* first;
//...
#end`
OtherRelationship.h
#import "Relationship.h"
#interface OtherRelationship : Relationship
#end
OtherRelationship.m
#import "OtherRelationship.h"
#implementation OtherRelationship
#synthesize first = _first;
- (void)foo
{
NSLog(#"%#", _first);
}
and it's working. But when i delete
#synthesize first = _first;
i get "Use of undeclared identifier '_first'" error. Does inheritanced variables doesn't work with autosynthesize or should i looking for problem elsewhere?
The backing ivar in the superclass is #private to the subclass. That is, the subclass may call self.first, but not _first. If you want to #synthesize again, use a different name because you can't refer to _first. For example, replace with #synthesize first = _ffirst; or just drop the #synthesize.

Objective-C instance variables?

I'm sure my confusion here is just a result of being stuck in a "Java mindset" and not understanding how Obj-C differs in this case.
In Java, I can declare a variable in a class, like this, and each instance of that class will have it's own:
MyClass {
String myVar;
MyClass() {
// constructor
}
}
In Obj-C I tried to do the same thing by declaring a variable only in the .m file like this:
#import "MyClass.h"
#implementation MyClass
NSString *testVar;
#end
My expectation here was that this variable has a scope limited to this class. So I created a second class (identical):
#import "MySecondClass.h"
#implementation MySecondClass
NSString *testVar;
#end
What I'm seeing (and has me baffled) is that changing the variable in one class, affects the value seen in the other class. In fact, if I set a breakpoint, and then "Jump to Definition" of the variable, it takes me to th
I've created an extremely small Xcode project that demonstrates the problem here.
Change this:
#implementation MyClass
NSString *testVar;
#end
to:
#implementation MyClass {
NSString *testVar;
}
// methods go here
#end
and you'll get what you expected.
As you had it, you are actually creating a global variable. The two global variables were combined into one by the linker which is why both changed when you set one. The variable in curly braces will be a proper (and private) instance variable.
Edit: After being downvoted for no apparent reason, I thought I'd point out the "old" way of doing things, and the new way.
The old way:
SomeClass.h
#interface SomeClass : UIViewController <UITextFieldDelegate> {
UITextField *_textField;
BOOL _someBool;
}
#property (nonatomic, assign) BOOL someBool;
// a few method declarations
#end
SomeClass.m
#implementation SomeClass
#synthesize someBool = _someBool;
// the method implementations
#end
Now the new and improved way with the modern Objective-C compiler:
SomeClass.h
#interface SomeClass : UIViewController
#property (nonatomic, assign) BOOL someBool;
// a few method declarations
#end
SomeClass.m
#interface SomeClass () <UITextFieldDelegate>
#end
#implementation SomeClass {
UITextField *_textField;
}
// the method implementations
#end
The new way has several advantages. The primary advantage is that none of the implementation specific details about the class appear in the .h file. A client has no need to know what delegates the implementation needs. The client has no need to know what ivars I use. Now, if the implementation needs a new ivar or it needs to use a new protocol, the .h file doesn't change. This mean less code gets recompiled. It cleaner and much more efficient. It also makes for easier editing. When I'm editing the .m file and realize I need a new ivar, make the change in the same .m file I'm already editing. No need to swap back and forth.
Also note the implementation no longer needs an ivar or #synthesize for the property.
What you probably want (unless you're using a very old OS and compiler) is to just use property syntax. I.e.:
#interface MyClass : NSObject
// method declarations here ...
#property (copy) NSString* myVar;
// ... or here.
#end
This will do what you intended to do. This will implicitly synthesize an instance variable and a getter/setter pair for this variable. If you manually wanted to create the instance variable (you generally don't need that unless you need your code to work on very old MacOS versions), this is what the above code does under the hood to create the ivar:
#interface MyClass : NSObject
{
NSString* _myVar;
}
// method declarations here.
#end
Note the curly braces, which tell the compiler that this is not just a global variable somewhere in between the methods, but actually an instance variable that belongs to this object.
If you are creating the property only for internal use and don't want clients of your class to mess with it, you can hide this away a little bit in everything but the oldest ObjC compilers by using a class extension which "continues" the class declaration from the header, but can be placed separate from it (so usually in your implementation file). A class extension looks like a category without a name:
#interface MyClass ()
#property (copy) NSString* myVar;
#end
And you can either put your property declaration in there, or even ivar declarations (again wrapped in curly brackets). You can even declare the same property as readonly in the class interface, and then re-declare it identical, but as readwrite in the extension, so that clients only read it, but your code can change it.
Note that, if you didn't use ARC (that is, you've switched off the default of Automatic Reference Counting), you would have to set all your properties to nil in your dealloc method (unless they're set to weak or assign of course).
NB - All the above are #interface sections. Your actual code will go in separate #implementation sections. This is so you can have header files (.h) you can hand off to your class's clients that just contain the portions you intend them to use, and hide away implementation details in the implementation file (.m) where you can change them without having to worry someone might have accidentally used them and you'll break other code.
PS - Note that NSStrings and other objects that you want the immutable flavor of, but that also exist in a mutable flavor (i.e. NSMutableString) should always be copy properties, because that will turn an NSMutableString into an NSString so that nobody on the outside can change the mutable string underneath you. For all other object types, you generally use strong (or retain if not ARC). For your class's owner (e.g. its delegate) you usually use weak (or assign if not ARC).
In Java
MyClass {
String myVar;
MyClass() {
// constructor
}
}
In Objective-c
MyClass.h
#interface MyClass : NSObject{
NSString* str; // Declaration
}
#end
MyClass.m
#implementation MyClass
-(void)initializieTheString
{
//Defination
}
#end
In objective-c, you define the variable as private by doing like so
MyClass.h
#interface MyClass : NSObject{
NSString* _myTestVar; // Declaration
}
#end
and refer to it in the implementation class by doing like so
MyClass.m
#import "MyClass.h";
#implementation MyClass
-(void)initializieTheString
{
_myTestVar= #"foo"; //Initialization
}
#end

Difference in setting up a class?

I may not have worded the question right, but I am not sure if what I am asking makes 100% so here goes:-)
In Xcode you can set a #class (name of class) above the #interface in the header file.
Is this the same as changing the the UIViewController in the name of the class? See code below:
So is this the same -
#class CoreDataClass;
#interface FlipsideViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
{
}
//This file declares the UITableView
#property (nonatomic, retain) IBOutlet UITableView *mainTableView;
#property (nonatomic, retain) CoreDataClass *cdc;
As this:
#interface FlipsideViewController : CoreDataClass <UITableViewDataSource, UITableViewDelegate>
{
}
//This file declares the UITableView
#property (nonatomic, retain) IBOutlet UITableView *mainTableView;
#property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
#end
??
If this is not the same, how is it different and what are advantages to the different implementation?
The Difference is only really asked if they are similar:-)
#class is not used to create a class, but to forward declare another one. See this question for a good explanation.
They are not the same at all. The first case is a 'forward declaration' - you are telling the compiler that the class CoreDataClass exists, so that you can refer to it in your header file without actually importing the files that define it.
The second case, you are declaring that FlipsideViewController is a subclass of CoreDataClass, and inherits all its methods and instance variables.
They're not even related. The difference is that the superclass ("parent" class) of your view controller will be different (and this can lead to nice unrecognized selector errors...). Forward-declaring a class using the #class keyword is just a convenient way of referring to a class when one doesn't want to import a whole framework header hierarch just in order to refer to one class. I. e., if you don't need to know anyting about a class except that it exists, you can use this keyword. Be careful, however, if you maks heavy use of the class - in those cases, the class forward-declaration is not considered a good solution.
In first case when you use #class it's inform XCode that you will be using CoreDataClass somewhere and you will #import header for example in .m file, in second case you're inherit from CoreDataClass (you will get access to all public and protected properties)

Error in protocol declaration

I am getting an error as:
protocol declaration not found
I couldn't find out what's the reason. Now I am using ARC. I doubt that the issue is due to that. Here is the code I am using for protocol declaration
//This is the first page we are declaring the Delegate
.h
#protocol ImageDelegate
#optional
-(void)ImageSelected:(UIImage *)ImageName;
#end
#interface GetAddedMovieList : UIViewController<UITableViewDataSource,UITableViewDelegate>{
id<ImageDelegate> delegate;
}
#property(nonatomic, strong)id<ImageDelegate> delegate;
#end
.m
#synthesize delegate;
//This is page in which i tried to set delegate. Here I am getting the error.
#interface ImageEnlarge : UIViewController<ImageDelegate>{
IBOutlet UIImageView *imgEnlarge;
NSString *stgImageName;
}
I see several (possible) issues in your code.
#property(nonatomic, strong)id<ImageDelegate> delegate;
delegates should be weak. GetAddedMovieList do now own the delegate by any mean and therefore shouldn't have an impact on its life cycle.
#synthesize delegate = delegate;
By default #synth uses either ivar_ or _ivar lately. With the latest LLVM #synth aren't necessary anymore btw, neither ivars.
#synthesize outside an #implementation ?
Have you checked your #imports?
It's probably an import loop. Do you #import the correct file for where you are using the protocol? And are you importing that file in the protocol file? If so then you have an import loop. Use forward declaration in the protocol's header instead and that should solve it. (#class)
You are putting an #interface on a .m file, are you trying to create a private #interface? With an IBOutlet declared there?
After seeing your edit, I am guessing there is only missing an import on the .h of your ImageEnlarge class.
Try like it.
#protocol ImageDelegate<NSObject>
#optional
-(void)ImageSelected:(UIImage *)ImageName;
#end
And also add this property.
#property(nonatomic,assign)id<ImageDelegate> delegate;
I think it will be helpful to you.

variable accessing

I have a variable x in one class.And I want to access the updated x value in some other class.
There is so much of confusion.Can I use property?.Please help me.
Thanks in advance
Do you mean that you want to be told when the value changes? Have a look at Key Value Observing
To simply access an iVar in one class from another, a property is exactly what you want.
The syntax is :
in your .h
#interface myclass : NSObject {
UIWindow *window;
}
#property (nonatomic, retain) UIWindow *window;
#end
in your .m
#implementation myclass
#synthesize window;
...
#end
The #synthesize directive instructs the compiler to produce a lot of boilerplate code (as directed by the (nonatomic, retain) specifiers. In this case to handle thread safety and memory management.
Also note that in Objective-C 2.0 the iVar declaration UIWindow *window; is not required.
If you want to be notified in your second class when an iVar is updated, you need to look at key value observing. Unless you are writing a framework or some very dynamic code, that is probably overkill.
Maybe this tutorial will help you out..
If this is not what you mean, please rephrase the question, because i don't understand it..
Edit: Or a shared Instance can be used
you could access it by #import Classname, and then just use the getter that is created with the property. but first initialize the class you have imported..
#import "ClassY.h"
#implementation ClassX
ClassY * classY;
NSString * name;
...
name = [classY name];
...
#end