Two Interfaces? - iphone

DataController.h
#class Play;
#interface DataController : NSObject
- (unsigned)countOfList;
- (Play *)objectInListAtIndex:(unsigned)theIndex;
#end
DataController.m
#import "DataController.h"
#import "Play.h"
#interface DataController ()
#property (nonatomic, copy, readwrite) NSMutableArray *list;
- (void)createDemoData;
#end
#implementation DataController
#synthesize list;
- (id)init {
if (self = [super init]) {
[self createDemoData];
}
return self;
}
Why do you think that #interface is defined twice? And also whats the meaning of ()? Shouldn't there be a class name maybe the super class between the parentheses?

In general, the syntax #interface ClassName (CategoryName) is for declaring a category. Categories are a way to add methods to a class. You can do this even with classes for which you don't have the source code. See more here.
#interface ClassName () (with nothing in the parentheses) is essentially a special case of a category and is called a class extension. The primary difference between a class extension and a category is that methods declared in a class extension must be defined/implemented in the main #implementation block for the class, or you'll get a compiler warning. Methods in a regular category can be defined in an external #implementation block.
The most common use for class extensions (as in this case) is for declaring private methods. Objective-C doesn't have support for true private methods, so an easy way to accomplish the same basic end result is to declare private methods in a class extension at the top of the .m file. Since these methods aren't defined in the .h file, other classes won't see them, and you'll get a compiler warning if you try to use them outside the class they belong to.
You can also redeclare a readonly #property as readwrite in a class extension. That way, code external to the class implementation can only read a property's value, but inside the class's implementation, you can write to it too. This is the only case where it's allowable to redeclare an #property.
(Note that class extensions were a new feature in Objective-C 2.0 and aren't available on Mac OS X 10.4 and earlier.)

Related

Can we have retain property with no getter and setters on Obj C elements?

Ok, so I was reading some articles regarding Good Programming Practices and I came across a statement which said that making all your Elements public for your classes isn't a good idea.. aka The concept of Encapsulation.
Now in Objective C, When I create a element for my class, I do the following, consider an NSMutableArray
#property (nonatomic, retain) NSMutableArray* myArray;
WHY I DO THIS?
So as to give the Retain property to myArray and therefore, giving it a simpler Memory Management cycle. Later on, I initialize the myArray in viewDidLoad as
self.myArray = [NSMutableArray arrayWithCapacity:0];
Later in Dealloc...
self.myArray = nil;
WHAT ELSE HAPPENS
By giving this property and synthesizing myArray in .m file, what I am unknowingly doing is making Public Getters and Setters for all the elements of my class.
Also, the auto-generated UI Elements from Xib files, do have the same declarations applied.
That isn't a nice idea to keep creating public Getters and setters for each and every element of your class, right?
So, there's absolutely no kind of encapsulation applied! Please correct me if I am wrong here and help me with any solutions!
Thanks!
Simply use the principle of Class Extensions that allows you to put part of your declarations in your .m file, thus making it invisible in your header and invisible from other classes.
(This is Apple's recommended way to declare private methods and properties, by the way)
YourClass.h
#interface MyClass : MySuperclass
// public properties
// public methods
#end
YourClass.m
#interface MyClass()
// This is a class extension
// put here private properties
// and private methods too
#end
#implementation MyClass
// And your implementation of course here
#end
You can even declare a property as readonly in your public interface (in the header file) and redeclare it as readwrite in your private interface (in the class extension in the .m file) for example.
See the Apple documentation for more details.
Note that:
There is NO NEED to declare the instance variable if you declare the property: the compiler will generate it automatically for you so you don't have to bother and to declare it in the .h. In the latest version of the compiler (Modern Objective-C) there is even no need for the #synthesize directive as it now generate it automatically if not present (see doc)
If you prefer to declare instance variables anyway, you can also do this in the class extension in your .m the same way you would do in your .h. That's a way to hide instance variables from the public header too. In general I really rarely use instance variables (as declaring only the properties is sufficient) and if I really need an ivar I declare it in the class extension to make it not visibile in the public header.
You can declare the property in your class.m file, so the getter and setter methods are accessible only in that class. An example:
MyClass.h
#interface MyClass : NSObject {
NSMutableArray *_myArray;
}
#end
MyClass.m
#interface MyClass ()
#property(nonatomic, retain) NSMutableArray *myArray;
#end
#implementation MyClass
[... MyClass implementation ..]
#synthesize myArray = _myArray;
#end
So you can use "self.myArray" only in "MyClass.h" file.

Objective C - Make iVars hidden

Here's my question.
Let's say I have a class called WebServiceBase.h. And I need to add a iVar in to that class called NSString *requestData. But I don't need to add that iVar in to the header file and make it visible to the external people. (If I'm distributing this as a class library)
Also I need to be able to access this requestData iVar, within the other classes that is extended from the WebServiceBase.h. (These extended classes are written by me. Not from the external people)
I tried with declaring the requestData iVar within the class extensions. But then it's not visible to the extended classes.
Any solution for this? I need to protect my data and make it hide from the external world.
You can define your ivars as protected via the #protected keyword, meaning that your class and all subclasses can access it without any problem, but the compiler won't allow this for other classes which don't inherit from your base class:
#interface Foo : NSObject
{
#protected
NSObject *a;
}
Its as simple as that and already gives you all the safety you can get from Objective-C.
You can have an ivar definition block in the #implementation block.
there are 2 ways , you can choose one you like.
1).h file
#interface YourClass
{
}
.m file
#interface YourClass ()
#property (nonatomic, retain) NSString *title;
#end
#implementation YourClass
#synthesize title;
//your method
2) .h flie
#interface YourClass
{
}
.m file
#implementation YourClass
{
NSString *title;
}
//your method
Declare a class extension that defines the ivar in another .h file. Call it something like myclass-private.h. Then import that header in both your main class your subclasses.

Problems referencing iVar in inner class

I have a class called MyClass which has a small nested inner class called MyInnerClass. The implementation file looks like the following (and also contains an ivar of the nested inner class) :
#class MyInnerClass;
#interface MyClass
{
MyInnerClass *myInnerClassIvar;
}
#property(nonatomic, retain) MyInnerClass *myInnerClassIvar;
#end
Then in the implementation file, I implement both MyClass and MyInnerClass. Looks like the following:
#interface MyInnerClass
{
iVar *x;
}
#property(nonatomic, retain) iVar *x;
#end
#implementation MyInnerClass
#synthesize x;
...
#end
#implementation MyClass
#synthesize myInnerClassIvar;
...
#end
I am now creating a subclass for MyClass, and in it I'm trying to make a call like this:
self.myInnerClassIvar.x
And I'm getting the following message:
Property x cannot be found in in forward class object MyInnerClass *
Am I forgetting something? Haven't implemented an inner class before, see no reason why this shouldn't work.
UPDATED: I moved the interface of MyInnerClass to the .h of MyClass and everything works. Is this a good solution?
I believe that Objective-C does not have inner classes in the sense that you are trying to implement. See SO. But regarding your question...
in MyClass.h there is no mention of the iVars of MyInnerClass - it is a forward definition, i.e. #class MyInnerClass therefore MySubClass has no reference point for x.
If you define two classes MyClass & MyInnerClass (probably a bad thing to name it that considering...) - have them in two separate .h files and two separate .m files (ie. as normal). Make an #property in MyClass of type MyInnerClass. Then in MySubClass you need to import both MyClass & MyInnerClass.
I moved the interface of MyInnerClass into the .h file of MyClass like following:
MyClass.h
#class MyInnerClass;
#interface MyClass
{
MyInnerClass *myInnerClassIvar;
}
#property(nonatomic, retain) MyInnerClass *myInnerClassIvar;
#end
#interface MyInnerClass
{
iVar *x;
}
#property(nonatomic, retain) iVar *x;
#end
I'll wait before I check this off as the answer because based on the previous answer, I know there is some skepticism. The only reason I tried this is because I saw it in the Apple example SimpleTextInput, except in that one the entire inner class is in the .m file. Anyway, would be interested to hear what people have to say about this, if it might incur unwanted side effects later or if its ok.

What is the point of #property and #synthesize?

I haven't been able to figure it out, and there are no websites which explain it clearly enough... what exactly are the purposes of #property and #synthesize?
Thanks in advance!
Objective-C Runtime Programming Guide: Declared Properties
#property declares the getter and the setter methods for the public property you want to implement. For example this property declaration:
#property float value;
is equivalent to:
- (float)value;
- (void)setValue:(float)newValue;
#synthesize provides default implementation for these two accessors.
Update: The above explains what these two do. It does not explain what their purpose is. :-)
#property adds a member to the public interface that acts as a data variable to your class clients, but is read and written using methods. This gives you better control over the data that is exchanged between the client and your code, for example you can do extended validation on the values your code is given.
#synthesize allows you to not explicitly write the code that will be called by the client and actually treat the property as a data variable yourself.
The "#" symbol is interpreted by the compiler as a directive. This is one of the Objective-C 'additions' to the C language. When you declare #property and then #synthesize you are instructing the compiler to create the instructions and corresponding symbols for getters and setters for you. Remember that in the C language, the "=" operator means "assign". Most of the time in the OO context that the Objective-C extensions provide, we are working with pointers (aka references) to isa data structures (Classes in Objective-C).
Prior to Objective-C 2.0, all of the getter and setter methods had to be coded by the developer for every attribute which for most cases was copy/paste code. To be completely KVC/KVO compliant requires a lot of very tedious code... willAccessValueForKey, didUpdateValueForKey statements etc. that the new compiler adds for you automatically when you use the #property/#synthesize syntax. This is a huge productivity boost for developers. The dot syntax additions to the language are a little more contentious in the community as this hides the magic the compiler is doing on you behalf to interpret the object.property = anotherObject.property; statement as [object setProperty:[anotherObject property]];
From the Apple documentation referenced in other answers
Property Declaration Attributes
You can decorate a property with attributes by using the form #property(attribute [, attribute2, ...]). Like methods, properties are scoped to their enclosing interface declaration. For property declarations that use a comma delimited list of variable names, the property attributes apply to all of the named properties.
If you use the #synthesize directive to tell the compiler to create the accessor method(s), the code it generates matches the specification given by the keywords. If you implement the accessor method(s) yourself, you should ensure that it matches the specification (for example, if you specify copy you must make sure that you do copy the input value in the setter method).
I hope this will help you.
#property and #synthesize is Use to Access Object Or Variable into Another Class.
Here is a Small Example:
This is First Class
#import <UIKit/UIKit.h>
#import "ClassB.h"
#interface ViewController : UIViewController
#property(nonatomic, retain) NSString *FirstName;
#property(nonatomic, retain) NSString *LastName;
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize FirstName, LastName;
- (void)viewDidLoad
{
[super viewDidLoad];
self.FirstName = #"Ashvin";
self.LastName = #"Ajadiya";
ClassB *ClassBOb = [[ClassB alloc] init];
ClassBOb.ViewCntrlrOb = self;
[ClassBOb CallMe];
}
#end
And This is Another Class:
#import <UIKit/UIKit.h>
#class ViewController;
#interface ClassB : UIViewController
#property(nonatomic, retain) ViewController *ViewCntrlrOb;
-(void) CallMe;
#end
#import "ClassB.h"
#import "ViewController.h"
#interface ClassB ()
#end
#implementation ClassB
#synthesize ViewCntrlrOb;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
-(void) CallMe
{
NSLog(#"FirstName = %#",ViewCntrlrOb.FirstName);
NSLog(#"LastName = %#",ViewCntrlrOb.LastName);
}
So You can Access FirstName And LastName into ClassB.
And They Print:
2012-05-25 14:38:10.766 MyExample[8751:c07] FirstName = Ashvin
2012-05-25 14:38:10.768 MyExample[8751:c07] LastName = Ajadiya
Just a quick example of why you might not want to do just "variable = 0":
Say you have this property:
#property (nonatomic, retain) id <MyDelegate> theDelegate;
Whenever you replace that delegate with a new one, your synthesized setters and getters will handle the release/retain for you every time you set it like so:
self.theDelegate = newObject;
Really what happened was this:
[self setTheDelegate:newObject];
- (void)setTheDelegate:(id <MyDelegate>)anObject {
[theDelegate release];
theDelegate = [anObject retain];
}
(This is simplified of course)
You can do very powerful things in your own setters and getters, synthesize is for those that happen over and over like retained properties, etc. When compiling it looks at your #property and builds the methods accordingly.

Object as a data member in Objective C

From what I have experienced it seems as if objects cannot be shared data members in objective c. I know you can init a pointer and alloc the object in each method but I cannot seem to figure out how one can say define a NSMutableString as a data member and allow all of the methods to use and modify its data as in c++. Is this true or am I missing something?
To define an instance variable (member), edit your .h file:
#interface MyClass : NSObject {
// ivars go here
NSObject *member;
}
// methods go here
#end
Then, in your .m file, from any instance method (one which begins with -), you can access this variable.
- (void)doThingWithIvar {
[member doThing];
}
If you want to access the variable from outside the object itself, you'll need accessors. You can do this easily with Obj-C properties:
#interface MyClass : NSObject {
// ivars go here
NSObject *member;
}
// methods go here
#property (nonatomic, retain) NSObject *member;
#end
And in the .m:
#implementation MyClass
#synthesize member;
// ...
#end
The #synthesize line creates getter/setter methods for the ivar. Then you can use property syntax:
MyClass *thing = ...;
NSLog(#"%#", thing.member); // getting
thing.member = obj; // setting
(Note that I specified (retain) for the #property; if your member isn't an Objective-C object you won't want that. And if your property's class has a mutable counterpart, you'll want (copy) instead.)
It sounds like you want to synthesize (create getter/setter methods) a property for a member variable. I just found this cheat sheet, go down to the section called, "Properties", should give a quick overview.
Other than that Apple's documentation should give you more info.