This question already has answers here:
Where to put iVars in "modern" Objective-C?
(5 answers)
Closed 6 years ago.
I'm a beginner to Objective-C, coming over from Swift. It seems as if there are two different #interface instances in which I can declare my ivars. One in my header file, such as this:
// Header file
#interface ViewController : UIViewController
{
// declare instance variables
}
#end
And another that I can add in my implementation file, such as this:
// Implementation file
#interface ViewController ()
// declare instance variables
#end
#implementation ViewController
#end
EDIT: I was learning the "old way" of doing things, which taught me to declare private ivars in the .h file. My confusion stemmed from seeing ivars declared in .h (old way) as well as in .m (new, preferred way). Here's what I've learned (so far...):
// .h
#interface SomeClass : UIViewController
#property (nonatomic, assign) BOOL someBool;
// declare other properties, which will all be public
#end
// .m
#interface SomeClass () <UITextFieldDelegate>
// what do I declare here?...
#end
#implementation SomeClass {
// ...and what do I declare here?
}
// method implementations
#end
However, I'm still confused as to the difference between my .m's #interface and the #implementation curly brackets. #matt said to never use curly brackets, but #rmaddy's answer here suggests that #implementation SomeClass {} is ok. So, which is it?
Do you want it to be accessible publicly? Then write in .h file.
If you don't want other classes to see it ie you want to make it private and only visible to that class itself then write in .m file.
For more information you can see this question:
Where to put iVars in "modern" Objective-C?
Related
Should I duplicate delegates declaration in the #interface () block like this:
.h file
#interface VKStartScreen : UIViewController <UIAlertViewDelegate, VKSdkUIDelegate>
#end
.m file
#interface VKStartScreen () <UIAlertViewDelegate, VKSdkUIDelegate>
#end
Or can I just omit it in the .m file?
You can omit in either file. You only need it in one place. I personally put the delegate declarations in the .m unless some other classes need to know that this class conforms to these protocols. Always opt for private and if it needs to be public for some reason open it up.
I have read in iOS Programming Fundamentals by Matt Neuberg that instance variables are protected, meaning that other classes, except for subclasses of this one, can't see them.
I have a parent class A where I define an ivar list.
(A.m)
#interface A ()
#end
#implementation A
{
NSArray *list;
}
#end
Class B extends A (B.h)
#import "A.h"
#interface B:A
#end
(B.m)
#interface B ()
#end
#implementation B
list =
...
#end
I want to use ivar list in child class B but the compiler doesn't see that the was reference declared in the parent class. I have tried explicitly using #protected but that doesn't work. I don't want to expose ivar list on the public interface. It's an internal structure that is a common element of all subclasses. How can I do this?
Instance variables that are declared outside a class's public interface (in other words, the #interface section) are private by default. You can add a visibility modifier to the declaration to change the visibility of one or more ivars like so:
#implementation A
{
NSNumber *_ivarWithDefaultVisibility;
#protected
NSArray *_list;
NSString *_anotherIvarWithProtectedVisibility;
}
(Note that according to Apple's Cocoa coding guidelines, ivar names should be prefixed with an underscore.)
This is not the usual way to implement protected properties in ObjC. (#protected and #private are very seldom used in Cocoa.) First, use a property, not an ivar. It will make it much cleaner. Declare it this way:
A.h
#interface A : NSObject
// Public interface goes here
#end
A.m
// Declare the property in a class extension inside the implementation file.
// This is the idiomatic way to create a "private" property.
#interface A ()
#property (nonatomic, readwrite, strong) NSArray *list;
#end
A+protected.h
// Enumerated any methods that should be accessible to subclasses here.
// Properties are just a special way of defining methods.
// The word "Protected" is just a category name.
#interface A (Protected)
#property (nonatomic, readwrite, strong) NSArray *list;
#end
B.h
#import "A.h"
#interface B : A
...
#end
B.m
#import "B.h"
#import "A+protected.h"
// ... now you can use self.list ...
This approach allows you to create any kind of "protected" method, not just properties, and is also the technique used to create "friend" classes.
I just got started working with delegates.
from some reason I cannot do it, and I see errors.
I tried to do the next code on a new project and it was OK, but when i'm moving this code to my main project I have a few issues.
my NSObject class .h:
#protocol myNSObjectClassDelegate <NSObject>
#required
-(void)doSomething;
#end
#interface GeneralMethods : NSObject
#property (nonatomic,strong) id<myNSObjectClassDelegate> delegate;
#end
my NSObject class .m:
#synthesize delegate;
-(void)SomeMethod {
if ([delegate respondsToSelector:#selector(doSomething)]) {
[delegate doSomething];
}
}
my UIViewController .h
#import "GeneralMethods.h"
#interface view : UIViewController<UIGestureRecognizerDelegate,
UINavigationControllerDelegate,
 UIImagePickerControllerDelegate,
myNSObjectClassDelegate>
The error is here at .h - Cannot find protocol declaration for 'myNSObjectClassDelegate'
my UIViewController .m
-(void)doSomething{
}
What am I doing wrong?
EDIT : I figure it out:
For some reason, at my NSObject class, if I'm moving the #import myUIViewcontroller after this:
#protocol myNSObjectClassDelegate <NSObject>
#required
-(void)doSomething;
#end
the problem solved.
We can't see all the code but after reading some more of the exchanges it looks like dependencies are maybe added out of order. I recommend moving the protocol into its own file and #import'ing it to all the places that use it. This way you definitely will be importing things in the order you expect.
In addition to that, the following property declaration:
#property (nonatomic,strong) id<myNSObjectClassDelegate> delegate;
Delegates should be declared as weak, not strong.
#property (nonatomic,weak) id<myNSObjectClassDelegate> delegate;
The reason is to avoid retain cycles/memory leaks. Typically, though not always the relationship looks like this:
Parent Object (usually Controller) -----STRONG-----> Child (View often)
View Thing ----WEAK--------> delegate (actually the Parent Object)
Now if the relationship is STRONG both ways, releasing the parent from all who own it will not be sufficient to release it since its child also holds an owning relationship to it.
Also you can omit the:
#synthesize delegate;
Auto property synthesis renders this obsolete.
Make sure to import your NSObject class .h. file into your UIViewController's .h file (or wherever you declare the protocol). As it stands, you haven't imported the header that declares the protocol so your view controller has no way of knowing that it exists.
Ex:
#import "FileWithProtocol.h"
#interface MyClass <MyProtocol>
...
#end
In the view controller .h file, try adding this line:
#protocol MyNSObjectClassDelegate;
before
#interface ...
Normally we use
#interface interface_name : parent_class <delegates>
{
......
}
#end
method in .h file and in .m file we synthesis the properties of variables declared in .h file.
But in some code, this #interface.....#end method is kept in the .m file also. What does it mean? What is the difference between them?
Also give some words about getters and setters for the interface file that is defined in .m file...
It's common to put an additional #interface that defines a category containing private methods:
Person.h:
#interface Person
{
NSString *_name;
}
#property(readwrite, copy) NSString *name;
-(NSString*)makeSmallTalkWith:(Person*)person;
#end
Person.m:
#interface Person () //Not specifying a name for the category makes compiler checks that these methods are implemented.
-(void)startThinkOfWhatToHaveForDinner;
#end
#implementation Person
#synthesize name = _name;
-(NSString*)makeSmallTalkWith:(Person*)person
{
[self startThinkOfWhatToHaveForDinner];
return #"How's your day?";
}
-(void)startThinkOfWhatToHaveForDinner
{
}
#end
The 'private category' (the proper name for a nameless category is not 'private category', it's 'class extension') .m prevents the compiler from warning that the methods are defined. However, because the #interface in the .m file is a category you can't define ivars in it.
Update 6th Aug '12: Objective-C has evolved since this answer was written:
ivars can be declared in a class extension (and always could be - the answer was incorrect)
#synthesize is not required
ivars can now be declared in braces at the top of #implementation:
that is,
#implementation {
id _ivarInImplmentation;
}
//methods
#end
The concept is that you can make your project much cleaner if you
limit the .h to the public interfaces of your class, and then put
private implementation details in this class extension.
when you declare variable methods or properties in ABC.h file , It
means these variables properties and methods can be access outside the
class
#interface Jain:NSObject
{
NSString *_name;
}
#property(readwrite, copy) NSString *name;
-(NSString*)makeSmallTalkWith:(Person*)jain;
#end
#Interface allows you to declare private ivars, properties and
methods. So anything you declare here cannot be accessed from outside
this class. In general, you want to declare all ivars, properties and
methods by default as private
Simply say when you declare variable methods or properties in ABC.m
file , It means these variables properties and methods can not be
access outside the class
#interface Jain()
{
NSString *_name;
}
#property(readwrite, copy) NSString *name;
-(NSString*)makeSmallTalkWith:(Person*)jain;
#end
you can even create other classes in .m file,
for instance other small classes which inherit from the class declared in .h file but having some slight different behaviour.
You could use this in a factory pattern
I have started new iOS project and have added only one property in ViewControler header file. but it gives me error:
expected specifier-qualifier-list before 'property'
here is the code:
#import <UIKit/UIKit.h>
#interface QuoteGenViewController : UIViewController {
#property (retain) NSArray *myQuotes;
}
#end
Here the general structure of a class interface
#interface Class : Superclass
{
// Instance variable declarations.
// Theirs definition could be omitted since you can declare them
// in the implementation block or synthesize them using declared properties.
}
// Method and property declarations.
#end
Since a property provides a simple way to declare and implement an object’s accessor methods (getter/setter), you need to put them in the Method and property declarations section.
I really suggest to read ocDefiningClasses doc for this.
Hope that helps.
Your code should look like this:
#import <UIKit/UIKit.h>
#interface QuoteGenViewController : UIViewController {
}
#property (retain) NSArray *myQuotes;
#end