Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I am wondering what the standard layout/format is for an Objective-C interface (.h) file. I know what components are present within this file, but I have seen them laid out in many different ways.
A lot of the components of an interface file are pretty obvious like the #import, #class, etc. But for something like the #protocol and #interface declarations it can be different. I have seen people declare a new protocol above the interface declaration with its implementation of methods below:
#protocol MyNewClassDelegate;
#interface MyNewClass : UIViewController
// Properties and Methods
#end
#protocol MyNewClassDelegate <NSObject>
- (void)method
#end
The other way that I've seen it is by just having the entire #protocol declaration and implementation above the #interface statement. So it'd be something like this:
#protocol MyNewClassDelegate <NSObject>
- (void)method
#end
#interface MyNewClass : UIViewController
//Properties and Methods
#end
I have also seen it setup where one protocol is declared and implemented above the interface while another one is also declared and implemented below.
My question is which one is preferred or is a standard in the industry? Is there some kind of way you organize it based around what its functionality accomplishes?
I don't see how my answer is more right than others, but this is what i do in most of my applications.
#import
#import
#define
#define
typedef
typedef
#class ClassName
#class ClassName
#protocol ProtocolName;
#interface Name : inheritedObject <FirstProtocolSupported, SecondProtocolSupported, etc>
#property (noantomic, strong) IBOutlet Object* name;
#property (noantomic, strong) IBOutlet Object* name;
#property (noantomic, strong) IBOutlet Object* name;
#property (nonatomic, strong) Object* name;
#property (nonatomic, strong) Object* name;
#property (nonatomic, strong) Object* name;
- (IBAction)actionName:(SenderObject*)sender;
- (IBAction)actionName:(SenderObject*)sender;
- (IBAction)actionName:(SenderObject*)sender;
- (type)methodName:(Parameter*)argument;
- (type)methodName:(Parameter*)argument;
- (type)methodName:(Parameter*)argument;
#end
#protocol ProtocolName <ProtocolThatIsImplmented>
- (type)protocolMethod:(Param*)parameter;
#end
in essence it's, import statements then, #define statements then, typedef statements, #class statements then, any protocols, then class declaration, then iboutlet properties, then normal properties, then inaction methods, then normal actions, then the protocol declaration.
All in all there is no correct way to order the code in the .h file, it's all a matter of preference, as long as everything is declared accurately
As far as I know, there isn't any correct (or even preferred) convention for writing your .h files. Header files are typically very short, unless you have scores of properties and methods (as is the case with many of Apple's Foundation and UIKit classes). Even the most unwieldy header files generally don't exceed several hundred lines of code, so there's not much to worry about.
However, sometimes your protocol and its class will be codependent. In other words, the protocol needs to be aware of the class, and the class needs to be aware of the protocol.
For instance, UITableView needs to know about the protocols UITableViewDelegate and UITableViewDataSource, since it defines properties which must conform to those protocols (namely, delegate and dataSource). However, each of those protocols also need to know about UITableView since they both require a UITableView as a parameter for many of their methods (such as numberOfSectionsInTableView:).
In this scenario, your second example (declaring the protocol in its entirety before the class) wouldn't suffice unless you used a forward #class declaration ahead of the #protocol definition. Your first example would work, because you are using a forward #protocol declaration ahead of the class.
I prefer my protocols to be in their own .h file. That way they can easily be reused.
You also wouldn't have to worry about the 'order' of things when you #import it.
//Copyright & license
#import
#import "AProtocol.h"
#import "Typedefs.h"
#import "NeededConsts.h"
#class ClassName;
#class ClassName;
#interface Name : inheritedObject
#property (strong, nonatomic) Object* name;
- (type)methodName:(Parameter*)argument;
- (void)setDelegate:(id <AProtocol>)argument;
#end
Inside the Name.m file (I try to keep as much info as possible out of the .h file)
//Copyright & license
#import ...
#import "ProtocolName.h"
file wide typedef
file wide typedef
#class ClassName;
#class ClassName;
static const NSInteger cFileWideInt = 404;
#interface Name () <FirstProtocolSupported, SecondProtocolSupported, etc>
#property (strong, nonatomic) IBOutlet Object* name;
#property (strong, nonatomic) IBOutlet Object* name;
#property (weak, nonatomic) id<AProtocol> delegate;
#end
#implementation
#end
The benefit of having most of your properties and declarations inside of your .m file is that it provides 'encapsulation' for information that your other classes don't need to know. This point leads into code architecture which would turn this into a long and complex answer ;P
Related
XCode 12.1
This project target gets compiler errors after an umbrella header is added add swift functionality to an existing objective c target
Now there is an error of No type or protocol named 'ComposeDelegate' on all of the target's existing various <ComposeDelegate> declarations.
ComposeViewController.h
#class ComposeViewController;
#class DataModel;
#class Message;
// The delegate protocol for the Compose screen
#protocol ComposeDelegate <NSObject>
- (void)didSaveMessage:(Message*)message atIndex:(int)index;
#end
// The Compose screen lets the user write a new message
#interface ComposeViewController : UIViewController /*<UITextViewDelegate>*/
#property (nonatomic, assign) id<ComposeDelegate> delegate;
#property (nonatomic, strong) DataModel* dataModel;
#property (nonatomic, strong) AFHTTPClient *client;
#end
Other similar code errors appear elsewhere in the target's code as well.
How can this be fixed?
create a file for your protocol and copy the protocol declaration into that.
// ComposeDelegate.h
#idndef ComposeDelegate_h
#define ComposeDelegate_h
// The delegate protocol for the Compose screen
#protocol ComposeDelegate <NSObject>
- (void)didSaveMessage:(Message*)message atIndex:(int)index;
#end
#endif
then use this file to include where ever you want.
While creating an extra file may seem extra work, it gives you more control of the pre-processing of your source.
The macro #ifndef SomeName_h ... #endif keeps the code from being implemented twice.
PS: If you code a #interface and the declared Class is not used earlier/above you don't have to and should not pre-declare the ClassName (#class ComposeDelegate;) if not really needed.
I'm new to objective-C, so apologies if this is repeated somewhere. I have a category(?) that is something like:
inside SomeClass.h:
#interface SomeClass (SomeCategory) <SomeDelegate>
#property (nonatomic, retain) id somePublicProperty;
#property (nonatomic, retain) id someProperty; // <-- i want to move this to "private"
#end
and now in my SomeClass.m, all i have is:
#implementation SomeClass (SomeCategory)
// dynamic setters/getters here for someProperty.
#end
I think the someProperty is public. how do i make this "private"? (in other words, how do i syntactically put this in the .m file? i tried to use
#interface SomeClass (SomeCategory) {
#property (nonatomic, retain) somePrivateProperty;
}
#end
but it just complains that i have duplicate definition of the category. how do i do this correctly?
In your .h file, you should not give the category. Just use:
#interface SomeClass : SomeBaseClass < SomeDelegate>
#property (nonatomic, retain) id somePublicProperty;
#end
In your .m file, define your private property inside a class extension:
#interface SomeClass ()
#property (nonatomic, retain) id somePrivateProperty;
#end
A class extension is not a like category in that it allows you to extend an interface as well as add new storage to your class.
In a class category, you can define new properties, but no storage will be allocated for it, so you have to do it by hand:
#interface SomeClass (SomeBaseCategory)
#property (nonatomic, retain) id somePrivateProperty;
#end
#implementation SomeClass {
id _somePrivateProperty;
}
- (void)setSomePrivateProperty:(id)property {
_somePrivateProperty = property;
}
- (id)somePrivateProperty {
return _somePrivateProperty;
}
#end
Otherwise your app will crash.
In any case, keep in mind that given the dynamic nature of Objective-C, your property will never be fully private, since you can always send a message to an Objective-C object through objc_msgsend and thus set or read the property value.
EDIT:
If you do not have the source code for a class implementation, you cannot define a class extension (as per source linked above).
In this case, you could use object association to define properties.
Just add the category definition in the .m file OUTSIDE the implementation block
Like so:
#interface MyClass (MyCategory)
#property (assign) BOOL myPrivateProperty;
#end
#implementation MyClass
...
#end
Categories are best used for adding capability to code you do not own and cannot change. Adding properties via categories is not impossible, but is much more difficult.
Class Extensions are best used for keeping properties your object needs, but are not intended to be public.
If you do truly need to add properties to this object, the way to do it is with the Objective-C runtime's associated objects
There's an excellent writeup of when/how to use them here
#import "MPOContactAuthorizationManager.h"
#protocol MPOContactAuthorizationManagerDelegate <NSObject>
- (void)authorizationManger:(MPOContactAuthorizationManager *)manager
didUpdateContactState:(ContactsState)contactState;
#end
MPOContactAuthorizationManager and ContactState are not resolving to types even though they are declared in MPOContactAuthorizationManager:
#import "MPOContactAuthorizationManagerDelegate.h"
typedef enum _contactsState {
kContactsStateUnknown,
kContactsStateAllowed,
kContactsStateDisallowed
} ContactsState;
#interface MPOContactAuthorizationManager : NSObject <UIAlertViewDelegate> {
ContactsState _contactsAuthorizationState;;
}
#property (strong, nonatomic) NSObject<MPOContactAuthorizationManagerDelegate> *delegate;
#property (nonatomic) ContactsState contactsAuthorizationState;
Any ideas as to why these are not resolving? Both are getting the error "Expected a type"
Thanks
Mike
You have a circular dependency. Update the MPOContactAuthorizationManagerDelegate.h header by getting rid of the #import line and adding the following:
#class MPOContactAuthorizationManager;
just before the #protocol line.
Just put both in one .h file (you still need the forward declaration for MPOContactAuthorizationManager):
typedef enum _contactsState {
kContactsStateUnknown,
kContactsStateAllowed,
kContactsStateDisallowed
} ContactsState;
#class MPOContactAuthorizationManager;
#protocol MPOContactAuthorizationManagerDelegate <NSObject>
- (void)authorizationManger:(MPOContactAuthorizationManager *)manager
didUpdateContactState:(ContactsState)contactState;
#end
#interface MPOContactAuthorizationManager : NSObject <UIAlertViewDelegate> {
ContactsState _contactsAuthorizationState;;
}
#property (strong, nonatomic) NSObject<MPOContactAuthorizationManagerDelegate> *delegate;
#property (nonatomic) ContactsState contactsAuthorizationState;
Replace the import of "MPOContactAuthorizationManagerDelegate.h" from MPContactAuthorizationManager.h by using a forward declaration of the protocol:
#protocol MPOContactAuthorizationManagerDelegate;
typedef enum _contactsState {
kContactsStateUnknown,
kContactsStateAllowed,
kContactsStateDisallowed
} ContactsState;
#interface MPOContactAuthorizationManager : NSObject <UIAlertViewDelegate> {
ContactsState _contactsAuthorizationState;;
}
........
You need to choose this import scheme as you are referring to a user defined type (the ContactsState type) in the protocol's header - so this header needs to import the manager's header. In the manager's header, however, you only refer to the protocol as the types of the method parameters, so you can legally forward-declare here.
In general, you should only import one header from another in a few cases:
Declaring a class in your header that's a subclass of a class defined in the other header
Referring to user defined types (e.g. via a typedef) in your header that are defined in the other header
Declaring a class in your header as conforming to a protocol declared in another header
Declaring a category in your header for a class defined in another header
I think I'm forgetting one, so saving this space for that one.
Also - read this enlightening answer.
The more common case of needing protocol and class names in public method parameters and properties can be accomplished using forward declarations with #class and #protocol. Although, if it were me, I'd keep the protocol declaration in the same header as the authorization manager - seems more convenient that way. Note that you will need to do a forward-declaration within the file for this. For example:
typedef enum _contactsState {
kContactsStateUnknown,
kContactsStateAllowed,
kContactsStateDisallowed
} ContactsState;
//forward-declare the protocol before referencing it in the file
#protocol MPOContactAuthorizationManager;
#interface MPOContactAuthorizationManager : NSObject <UIAlertViewDelegate> {
ContactsState _contactsAuthorizationState;;
}
#property (strong, nonatomic) NSObject<MPOContactAuthorizationManagerDelegate> *delegate;
#property (nonatomic) ContactsState contactsAuthorizationState;
........
#end
// Provide the real protocol declaration.
#protocol MPOContactAuthorizationManagerDelegate <NSObject>
- (void)authorizationManger:(MPOContactAuthorizationManager *)manager
didUpdateContactState:(ContactsState)contactState;
#end
Sorry if this is stupid... but it confuses me?...
I'm trying a new storyboard app with Xcode and just asked myself why there is a second declaration of the #interface in my implementation file?
.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
}
#end
.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
....
#end
See Apple's documentation: https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocCategories.html
It's a class extension, subtly different from a category, since it has no name inside the parentheses. You use it for declaring properties and methods that are intended to be kept private (out of the header), and redeclaring publicly read-only properties and methods as privately read-write. This allows for cleaner encapsulation.
By request, a friendly example:
JYDuckPondManager.h
#interface JYDuckPondManager : NSObject
#property (nonatomic, assign, readonly) NSUInteger duckCount;
#property (nonatomic, assign, readonly) CGFloat waterLevel;
- (JYDuckReaction *)feedDucks:(JYDuckFood *)food;
- (JYDuckReaction *)harassDucks:(JYDuckTaunt *)taunt;
#end
JYDuckPondManager.m (extension, imaginary implementation omitted)
#interface JYDuckPondManager ()
//// Redefined for internal modification
#property (nonatomic, assign, readwrite) NSUInteger duckCount;
#property (nonatomic, assign, readwrite) CGFloat waterLevel;
//// Internally exclusive properties
#property (nonatomic, strong) NSSet *duckPersonalitySet;
#property (nonatomic, assign) CGFloat flockAnxietyLevel;
//// Private messages
- (void)recalculatePondState;
#end
Other objects should be able to interact with the pond, but they're not supposed to know certain things going on in the pond or redefine the pond's statistics. Keeping nuts-and-bolts stuff in the .m extension ensures that the .h is concise and appropriately limited.
The second #interface block in the .m file is an extension. You could add declarations for methods and instance variables you want to use internally within your class.
The second interface #interface ViewController () is a class extension which is like an anonymous category. A class extension is declared like a category only without a name. Declarations found in these extensions directly extend the declarations found in the class’s primary #interface and can sometimes (in some situations) override declarations found in the primary interface.
I'm new to iOS development and I've been seeing the following in several tutorials as well as when Xcode autogenerates code for me when subclassing one of my classes. Let's say I have the following .h and .m files
#import <UIKit/UIKit.h>
#interface Class : NSObject {
NSArray *_infos;
NSString *_context;
}
#property (nonatomic, retain) NSArray *infos;
#property (nonatomic, retain) NSString *context;
#end
#import "Class.h"
#implementation Class
#synthesize infos = _infos;
#synthesize context = _context;
#end
And then consider this which is how I would normally do it:
#import <UIKit/UIKit.h>
#interface Class : NSObject {
NSArray *infos;
NSString *context;
}
#property (nonatomic, retain) NSArray *infos;
#property (nonatomic, retain) NSString *context;
#end
#import "Class.h"
#implementation Class
#synthesize infos;
#synthesize context;
#end
What is the difference? From the notation I can just infer that they're just declaring the variables as private, but how does it work? If I'm correct.
It's a silly naming convention. Use it if you want to, leave it if you don't.
The advantage is that a method argument/local variable named context does not conflict with the ivar _context. It has little to do with privacy, since you can just specify #private to make the ivars private (or just #synthesize them in the first place).
The disadvantage is that you have underscores everywhere, and underscores are occasionally a bit special in C (though an underscore followed by a lowercase letter is only reserved in file scope, so you should be fine provided the ivar starts with a lowercase letter...). Where necessary, I stick an underscore at the end which feels less dirty.
Sidenote: A few people use method names beginning with an underscore to mean "private", but this convention is reserved by Apple.
The only difference is the name of the ivars ("instance variables") holding the properties.